mirror of
https://mau.dev/maunium/synapse.git
synced 2024-08-28 13:11:56 +00:00
![Kegan Dougal](/assets/img/avatar_default.png)
This allows images to be clicked by clicking on the edge with the bubble. This is important since Redactions are only visible on the event info screen.
233 lines
14 KiB
HTML
233 lines
14 KiB
HTML
<div ng-controller="RoomController" data-ng-init="onInit()" class="room" style="height: 100%;">
|
|
|
|
<script type="text/ng-template" id="eventInfoTemplate.html">
|
|
<div class="modal-body">
|
|
<pre> {{event_selected | json}} </pre>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button ng-click="redact()" type="button" class="btn btn-danger"
|
|
ng-disabled="!events.rooms[room_id]['m.room.ops_levels'].content.redact_level || !pow(room_id, state.user_id) || pow(room_id, state.user_id) < events.rooms[room_id]['m.room.ops_levels'].content.redact_level"
|
|
title="Delete this event on all home servers. This cannot be undone.">
|
|
Redact
|
|
</button>
|
|
</div>
|
|
</script>
|
|
|
|
<div id="roomHeader">
|
|
<a href ng-click="goToPage('/')"><img src="img/logo-small.png" width="100" height="43" alt="[matrix]"/></a>
|
|
<div class="roomHeaderInfo">
|
|
|
|
<div class="roomNameSection">
|
|
<div ng-hide="name.isEditing" ng-dblclick="name.editName()" id="roomName">
|
|
{{ room_id | mRoomName }}
|
|
</div>
|
|
<form ng-submit="name.updateName()" ng-show="name.isEditing" class="roomNameForm">
|
|
<input ng-model="name.newNameText" ng-blur="name.cancelEdit()" class="roomNameInput" placeholder="Room name"/>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="roomTopicSection">
|
|
<button ng-hide="events.rooms[room_id]['m.room.topic'].content.topic || topic.isEditing"
|
|
ng-click="topic.editTopic()" class="roomTopicSetNew">
|
|
Set Topic
|
|
</button>
|
|
<div ng-show="events.rooms[room_id]['m.room.topic'].content.topic || topic.isEditing">
|
|
<div ng-hide="topic.isEditing" ng-dblclick="topic.editTopic()" id="roomTopic">
|
|
{{ events.rooms[room_id]['m.room.topic'].content.topic | limitTo: 200}}
|
|
</div>
|
|
<form ng-submit="topic.updateTopic()" ng-show="topic.isEditing" class="roomTopicForm">
|
|
<input ng-model="topic.newTopicText" ng-blur="topic.cancelEdit()" class="roomTopicInput" placeholder="Topic"/>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="roomPage">
|
|
<div id="roomWrapper">
|
|
|
|
<div id="roomRecentsTableWrapper">
|
|
<div ng-include="'recents/recents.html'"></div>
|
|
</div>
|
|
|
|
<div id="usersTableWrapper" ng-hide="state.permission_denied">
|
|
<table id="usersTable">
|
|
<tr ng-repeat="member in members | orderMembersList">
|
|
<td class="userAvatar mouse-pointer" ng-click="$parent.goToUserPage(member.id)" ng-class="member.membership == 'invite' ? 'invited' : ''">
|
|
<img class="userAvatarImage"
|
|
ng-src="{{member.avatar_url || 'img/default-profile.png'}}"
|
|
alt="{{ member.displayname || member.id.substr(0, member.id.indexOf(':')) }}"
|
|
title="{{ member.id }} - power: {{ member.powerLevel }}"
|
|
width="80" height="80"/>
|
|
<img class="userAvatarGradient" src="img/gradient.png" title="{{ member.id }}" width="80" height="24"/>
|
|
<div class="userPowerLevel" ng-style="{'width': member.powerLevelNorm +'%'}"></div>
|
|
<div class="userName">
|
|
<div ng-show="member.displayname">
|
|
{{ member.id | mUserDisplayName: room_id }}
|
|
</div>
|
|
<div ng-hide="member.displayname">
|
|
{{ member.id.substr(0, member.id.indexOf(':')) }}<br/>
|
|
{{ member.id.substr(member.id.indexOf(':')) }}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td class="userPresence" ng-class="(member.presence === 'online' ? 'online' : (member.presence === 'unavailable' ? 'unavailable' : '')) + ' ' + (member.membership == 'invite' ? 'invited' : '')">
|
|
<span ng-show="member.last_active_ago">{{ member.last_active_ago + (now - member.last_updated) | duration }}<br/>ago</span>
|
|
</td>
|
|
</table>
|
|
</div>
|
|
|
|
<div id="messageTableWrapper"
|
|
ng-hide="state.permission_denied"
|
|
ng-style="{ 'visibility': state.messages_visibility }"
|
|
keep-scroll>
|
|
<table id="messageTable" infinite-scroll="paginateMore()">
|
|
<tr ng-repeat="msg in events.rooms[room_id].messages"
|
|
ng-class="(events.rooms[room_id].messages[$index + 1].user_id !== msg.user_id ? 'differentUser' : '') + (msg.user_id === state.user_id ? ' mine' : '')" scroll-item>
|
|
<td class="leftBlock">
|
|
<div class="sender" ng-hide="events.rooms[room_id].messages[$index - 1].user_id === msg.user_id"> {{ msg.user_id | mUserDisplayName: room_id }}</div>
|
|
<div class="timestamp"
|
|
ng-class="msg.echo_msg_state">
|
|
{{ (msg.origin_server_ts) | date:'MMM d HH:mm' }}
|
|
</div>
|
|
</td>
|
|
<td class="avatar">
|
|
<img class="avatarImage" ng-src="{{ members[msg.user_id].avatar_url || 'img/default-profile.png' }}" width="32" height="32"
|
|
ng-hide="events.rooms[room_id].messages[$index - 1].user_id === msg.user_id || msg.user_id === state.user_id"/>
|
|
</td>
|
|
<td ng-class="(!msg.content.membership && ('m.room.topic' !== msg.type && 'm.room.name' !== msg.type))? (msg.content.msgtype === 'm.emote' ? 'emote text' : 'text') : 'membership text'">
|
|
<div class="bubble" ng-click="openJson(msg)">
|
|
<span ng-if="'join' === msg.content.membership && msg.changedKey === 'membership'">
|
|
{{ members[msg.state_key].displayname || msg.state_key }} joined
|
|
</span>
|
|
<span ng-if="'leave' === msg.content.membership && msg.changedKey === 'membership'">
|
|
<span ng-if="msg.user_id === msg.state_key">
|
|
{{ members[msg.state_key].displayname || msg.state_key }} left
|
|
</span>
|
|
<span ng-if="msg.user_id !== msg.state_key && msg.prev_content">
|
|
{{ members[msg.user_id].displayname || msg.user_id }}
|
|
{{ {"invite": "kicked", "join": "kicked", "ban": "unbanned"}[msg.prev_content.membership] }}
|
|
{{ members[msg.state_key].displayname || msg.state_key }}
|
|
<span ng-if="'join' === msg.prev_content.membership && msg.content.reason">
|
|
: {{ msg.content.reason }}
|
|
</span>
|
|
</span>
|
|
</span>
|
|
<span ng-if="'invite' === msg.content.membership && msg.changedKey === 'membership' ||
|
|
'ban' === msg.content.membership && msg.changedKey === 'membership'">
|
|
{{ members[msg.user_id].displayname || msg.user_id }}
|
|
{{ {"invite": "invited", "ban": "banned"}[msg.content.membership] }}
|
|
{{ members[msg.state_key].displayname || msg.state_key }}
|
|
<span ng-if="msg.prev_content && 'ban' === msg.prev_content.membership && msg.content.reason">
|
|
: {{ msg.content.reason }}
|
|
</span>
|
|
</span>
|
|
<span ng-if="msg.changedKey === 'displayname'">
|
|
{{ msg.user_id }} changed their display name from {{ msg.prev_content.displayname }} to {{ msg.content.displayname }}
|
|
</span>
|
|
|
|
<span ng-show='msg.content.msgtype === "m.emote"'
|
|
ng-class="msg.echo_msg_state"
|
|
ng-bind-html="'* ' + (members[msg.user_id].displayname || msg.user_id) + ' ' + msg.content.body | linky:'_blank'"
|
|
/>
|
|
|
|
<span ng-show='msg.content.msgtype === "m.text"'
|
|
class="message"
|
|
ng-class="containsBingWord(msg.content.body) && msg.user_id != state.user_id ? msg.echo_msg_state + ' messageBing' : msg.echo_msg_state"
|
|
ng-bind-html="(msg.content.msgtype === 'm.text' && msg.type === 'm.room.message' && msg.content.format === 'org.matrix.custom.html') ?
|
|
(msg.content.formatted_body | unsanitizedLinky) :
|
|
(msg.content.msgtype === 'm.text' && msg.type === 'm.room.message') ? (msg.content.body | linky:'_blank') : '' "/>
|
|
|
|
<span ng-show='msg.type === "m.call.invite" && msg.user_id == state.user_id'>Outgoing Call{{ isWebRTCSupported ? '' : ' (But your browser does not support VoIP)' }}</span>
|
|
<span ng-show='msg.type === "m.call.invite" && msg.user_id != state.user_id'>Incoming Call{{ isWebRTCSupported ? '' : ' (But your browser does not support VoIP)' }}</span>
|
|
|
|
<div ng-show='msg.content.msgtype === "m.image"'>
|
|
<div ng-hide='msg.content.thumbnail_url' ng-style="msg.content.body.h && { 'height' : (msg.content.body.h < 320) ? msg.content.body.h : 320}">
|
|
<img class="image" ng-src="{{ msg.content.url }}"/>
|
|
</div>
|
|
<div ng-show='msg.content.thumbnail_url' ng-style="{ 'height' : msg.content.thumbnail_info.h }">
|
|
<img class="image mouse-pointer" ng-src="{{ msg.content.thumbnail_url }}"
|
|
ng-click="$parent.fullScreenImageURL = msg.content.url; $event.stopPropagation();"/>
|
|
</div>
|
|
</div>
|
|
|
|
<span ng-if="'m.room.topic' === msg.type">
|
|
{{ members[msg.user_id].displayname || msg.user_id }} changed the topic to: {{ msg.content.topic }}
|
|
</span>
|
|
|
|
<span ng-if="'m.room.name' === msg.type">
|
|
{{ members[msg.user_id].displayname || msg.user_id }} changed the room name to: {{ msg.content.name }}
|
|
</span>
|
|
|
|
</div>
|
|
</td>
|
|
<td class="rightBlock">
|
|
<img class="avatarImage" ng-src="{{ members[msg.user_id].avatar_url || 'img/default-profile.png' }}" width="32" height="32"
|
|
ng-hide="events.rooms[room_id].messages[$index - 1].user_id === msg.user_id || msg.user_id !== state.user_id"/>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<div ng-show="state.permission_denied">
|
|
{{ state.permission_denied }}
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="controlPanel">
|
|
<div id="controls">
|
|
<table id="inputBarTable">
|
|
<tr>
|
|
<td id="userIdCell" width="1px">
|
|
{{ state.user_id }}
|
|
</td>
|
|
<td width="*">
|
|
<textarea id="mainInput" rows="1" ng-enter="send()"
|
|
ng-disabled="state.permission_denied"
|
|
ng-focus="true" autocomplete="off" tab-complete command-history/>
|
|
</td>
|
|
<td id="buttonsCell">
|
|
<button ng-click="send()" ng-disabled="state.permission_denied">Send</button>
|
|
<button m-file-input="imageFileToSend" class="extraControls" ng-disabled="state.permission_denied">Image</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<div class="extraControls">
|
|
<span>
|
|
Invite a user:
|
|
<input ng-model="userIDToInvite" size="32" type="text" ng-enter="inviteUser()" ng-disabled="state.permission_denied" placeholder="User ID (ex:@user:homeserver)"/>
|
|
<button ng-click="inviteUser()" ng-disabled="state.permission_denied">Invite</button>
|
|
</span>
|
|
<button ng-click="leaveRoom()" ng-disabled="state.permission_denied">Leave</button>
|
|
<button ng-click="startVoiceCall()"
|
|
ng-show="(currentCall == undefined || currentCall.state == 'ended')"
|
|
ng-disabled="state.permission_denied || !isWebRTCSupported || memberCount() != 2"
|
|
title ="{{ !isWebRTCSupported ? 'VoIP requires webRTC but your browser does not support it' : (memberCount() == 2 ? '' : 'VoIP calls can only be made in rooms with two participants') }}"
|
|
>
|
|
Voice Call
|
|
</button>
|
|
<button ng-click="startVideoCall()"
|
|
ng-show="(currentCall == undefined || currentCall.state == 'ended')"
|
|
ng-disabled="state.permission_denied || !isWebRTCSupported || memberCount() != 2"
|
|
title ="{{ !isWebRTCSupported ? 'VoIP requires webRTC but your browser does not support it' : (memberCount() == 2 ? '' : 'VoIP calls can only be made in rooms with two participants') }}"
|
|
>
|
|
Video Call
|
|
</button>
|
|
</div>
|
|
|
|
{{ feedback }}
|
|
<div ng-show="state.stream_failure">
|
|
{{ state.stream_failure.data.error || "Connection failure" }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="room-fullscreen-image" ng-show="fullScreenImageURL" ng-click="fullScreenImageURL = undefined;">
|
|
<img ng-src="{{ fullScreenImageURL }}"/>
|
|
</div>
|
|
|
|
</div>
|