diff --git a/res/css/_common.scss b/res/css/_common.scss index fd93c8c967..4e327ab28d 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -249,12 +249,6 @@ textarea { box-shadow: none; } -/* View Source Dialog overide */ -.mx_Dialog_wrapper.mx_Dialog_viewsource .mx_Dialog { - padding-left: 10px; - padding-right: 10px; -} - .mx_Dialog { background-color: $primary-bg-color; color: $light-fg-color; diff --git a/res/css/structures/_ViewSource.scss b/res/css/structures/_ViewSource.scss index a4c7dcf58a..b908861c6f 100644 --- a/res/css/structures/_ViewSource.scss +++ b/res/css/structures/_ViewSource.scss @@ -14,6 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_ViewSource_label_left { + float: left; +} + +.mx_ViewSource_label_right { + float: right; +} + +.mx_ViewSource_label_bottom { + clear: both; + border-bottom: 1px solid #e5e5e5; +} + .mx_ViewSource pre { text-align: left; font-size: 12px; diff --git a/res/css/views/rooms/_WhoIsTypingTile.scss b/res/css/views/rooms/_WhoIsTypingTile.scss index eb51595858..ef20c24c84 100644 --- a/res/css/views/rooms/_WhoIsTypingTile.scss +++ b/res/css/views/rooms/_WhoIsTypingTile.scss @@ -40,6 +40,7 @@ limitations under the License. } .mx_WhoIsTypingTile_remainingAvatarPlaceholder { + position: relative; display: inline-block; color: #acacac; background-color: #ddd; diff --git a/src/BasePlatform.js b/src/BasePlatform.js index 79f0d69e2c..54310d1849 100644 --- a/src/BasePlatform.js +++ b/src/BasePlatform.js @@ -113,4 +113,29 @@ export default class BasePlatform { reload() { throw new Error("reload not implemented!"); } + + supportsAutoLaunch(): boolean { + return false; + } + + // XXX: Surely this should be a setting like any other? + async getAutoLaunchEnabled(): boolean { + return false; + } + + async setAutoLaunchEnabled(enabled: boolean): void { + throw new Error("Unimplemented"); + } + + supportsMinimizeToTray(): boolean { + return false; + } + + async getMinimizeToTrayEnabled(): boolean { + return false; + } + + async setMinimizeToTrayEnabled(enabled: boolean): void { + throw new Error("Unimplemented"); + } } diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index 89fce9c718..b80f49d051 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -34,6 +34,7 @@ import GroupStore from '../../stores/GroupStore'; import FlairStore from '../../stores/FlairStore'; import { showGroupAddRoomDialog } from '../../GroupAddressPicker'; import {makeGroupPermalink, makeUserPermalink} from "../../matrix-to"; +import {Group} from "matrix-js-sdk"; const LONG_DESC_PLACEHOLDER = _td( `

HTML for your community's page

@@ -569,7 +570,7 @@ export default React.createClass({ _onShareClick: function() { const ShareDialog = sdk.getComponent("dialogs.ShareDialog"); Modal.createTrackedDialog('share community dialog', '', ShareDialog, { - target: this._matrixClient.getGroup(this.props.groupId), + target: this._matrixClient.getGroup(this.props.groupId) || new Group(this.props.groupId), }); }, diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 000195d349..7088347ff4 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -26,6 +26,7 @@ import dis from '../../dispatcher'; import VectorConferenceHandler from '../../VectorConferenceHandler'; import TagPanelButtons from './TagPanelButtons'; import SettingsStore from '../../settings/SettingsStore'; +import {_t} from "../../languageHandler"; const LeftPanel = React.createClass({ @@ -212,6 +213,7 @@ const LeftPanel = React.createClass({ ); const searchBox = (); diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 8e32802d0a..85f3afdfa5 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -537,12 +537,12 @@ module.exports = React.createClass({ case 'picture_snapshot': this.uploadFile(payload.file); break; - case 'notifier_enabled': case 'upload_failed': // 413: File was too big or upset the server in some way. - if(payload.error.http_status === 413) { + if (payload.error && payload.error.http_status === 413) { this._fetchMediaConfig(true); } + case 'notifier_enabled': case 'upload_started': case 'upload_finished': this.forceUpdate(); @@ -1305,7 +1305,10 @@ module.exports = React.createClass({ }, onSearchClick: function() { - this.setState({ searching: true, showingPinned: false }); + this.setState({ + searching: !this.state.searching, + showingPinned: false, + }); }, onCancelSearchClick: function() { diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index 10628ccd13..3f9d954f9f 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,12 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -'use strict'; - import React from 'react'; -import { _t } from '../../languageHandler'; +import PropTypes from 'prop-types'; import { KeyCode } from '../../Keyboard'; -import sdk from '../../index'; import dis from '../../dispatcher'; import { throttle } from 'lodash'; import AccessibleButton from '../../components/views/elements/AccessibleButton'; @@ -28,8 +26,10 @@ module.exports = React.createClass({ displayName: 'SearchBox', propTypes: { - onSearch: React.PropTypes.func, - onCleared: React.PropTypes.func, + onSearch: PropTypes.func, + onCleared: PropTypes.func, + className: PropTypes.string, + placeholder: PropTypes.string.isRequired, }, getInitialState: function() { @@ -102,21 +102,22 @@ module.exports = React.createClass({ const clearButton = this.state.searchTerm.length > 0 ? ( {this._clearSearch("button")} }> - ) : undefined; + onClick={ () => {this._clearSearch("button"); } }> + ) : undefined; + const className = this.props.className || ""; return (
{ clearButton }
diff --git a/src/components/structures/ViewSource.js b/src/components/structures/ViewSource.js index 4844149f59..fd35fdbeef 100644 --- a/src/components/structures/ViewSource.js +++ b/src/components/structures/ViewSource.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,11 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -'use strict'; - import React from 'react'; import PropTypes from 'prop-types'; import SyntaxHighlight from '../views/elements/SyntaxHighlight'; +import {_t} from "../../languageHandler"; +import sdk from "../../index"; module.exports = React.createClass({ @@ -27,31 +28,24 @@ module.exports = React.createClass({ propTypes: { content: PropTypes.object.isRequired, onFinished: PropTypes.func.isRequired, - }, - - componentDidMount: function() { - document.addEventListener("keydown", this.onKeyDown); - }, - - componentWillUnmount: function() { - document.removeEventListener("keydown", this.onKeyDown); - }, - - onKeyDown: function(ev) { - if (ev.keyCode == 27) { // escape - ev.stopPropagation(); - ev.preventDefault(); - this.props.onFinished(); - } + roomId: PropTypes.string.isRequired, + eventId: PropTypes.string.isRequired, }, render: function() { + const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return ( -
- - { JSON.stringify(this.props.content, null, 2) } - -
+ +
Room ID: { this.props.roomId }
+
Event ID: { this.props.eventId }
+
+ +
+ + { JSON.stringify(this.props.content, null, 2) } + +
+ ); }, }); diff --git a/src/components/views/auth/CaptchaForm.js b/src/components/views/auth/CaptchaForm.js index bb4785f299..90f8ebe6d3 100644 --- a/src/components/views/auth/CaptchaForm.js +++ b/src/components/views/auth/CaptchaForm.js @@ -66,7 +66,7 @@ module.exports = React.createClass({ } const scriptTag = document.createElement('script'); scriptTag.setAttribute( - 'src', `${protocol}//www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`, + 'src', `${protocol}//www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`, ); this.refs.recaptchaContainer.appendChild(scriptTag); } diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index ffa2a0bf5c..b376fd5b2c 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -98,6 +98,8 @@ module.exports = React.createClass({ onViewSourceClick: function() { const ViewSource = sdk.getComponent('structures.ViewSource'); Modal.createTrackedDialog('View Event Source', '', ViewSource, { + roomId: this.props.mxEvent.getRoomId(), + eventId: this.props.mxEvent.getId(), content: this.props.mxEvent.event, }, 'mx_Dialog_viewsource'); this.closeMenu(); @@ -106,6 +108,8 @@ module.exports = React.createClass({ onViewClearSourceClick: function() { const ViewSource = sdk.getComponent('structures.ViewSource'); Modal.createTrackedDialog('View Clear Event Source', '', ViewSource, { + roomId: this.props.mxEvent.getRoomId(), + eventId: this.props.mxEvent.getId(), // FIXME: _clearEvent is private content: this.props.mxEvent._clearEvent, }, 'mx_Dialog_viewsource'); @@ -211,7 +215,8 @@ module.exports = React.createClass({ }, render: function() { - const eventStatus = this.props.mxEvent.status; + const mxEvent = this.props.mxEvent; + const eventStatus = mxEvent.status; let resendButton; let redactButton; let cancelButton; @@ -251,8 +256,8 @@ module.exports = React.createClass({ ); } - if (isSent && this.props.mxEvent.getType() === 'm.room.message') { - const content = this.props.mxEvent.getContent(); + if (isSent && mxEvent.getType() === 'm.room.message') { + const content = mxEvent.getContent(); if (content.msgtype && content.msgtype !== 'm.bad.encrypted' && content.hasOwnProperty('body')) { forwardButton = (
@@ -282,7 +287,7 @@ module.exports = React.createClass({
); - if (this.props.mxEvent.getType() !== this.props.mxEvent.getWireType()) { + if (mxEvent.getType() !== mxEvent.getWireType()) { viewClearSourceButton = (
{ _t('View Decrypted Source') } @@ -303,8 +308,11 @@ module.exports = React.createClass({ // XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID) const permalinkButton = (
- { _t('Share Message') } + + { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' + ? _t('Share Permalink') : _t('Share Message') } +
); @@ -318,12 +326,12 @@ module.exports = React.createClass({ // Bridges can provide a 'external_url' to link back to the source. if ( - typeof(this.props.mxEvent.event.content.external_url) === "string" && - isUrlPermitted(this.props.mxEvent.event.content.external_url) + typeof(mxEvent.event.content.external_url) === "string" && + isUrlPermitted(mxEvent.event.content.external_url) ) { externalURLButton = (
- { _t('Source URL') }
); diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 15b8357b24..a537c4ca5d 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -321,6 +321,9 @@ module.exports = withMatrixClient(React.createClass({ const {tile, replyThread} = this.refs; + let e2eInfoCallback = null; + if (this.props.mxEvent.isEncrypted()) e2eInfoCallback = () => this.onCryptoClicked(); + ContextualMenu.createMenu(MessageContextMenu, { chevronOffset: 10, mxEvent: this.props.mxEvent, @@ -328,7 +331,7 @@ module.exports = withMatrixClient(React.createClass({ top: y, eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined, collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined, - e2eInfoCallback: () => this.onCryptoClicked(), + e2eInfoCallback: e2eInfoCallback, onFinished: function() { self.setState({menu: false}); }, diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index f01ef3e3ec..f9ce672c16 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -339,12 +339,11 @@ module.exports = React.createClass({ return nameA.localeCompare(nameB); }, - onSearchQueryChanged: function(ev) { - const q = ev.target.value; + onSearchQueryChanged: function(searchQuery) { this.setState({ - searchQuery: q, - filteredJoinedMembers: this._filterMembers(this.state.members, 'join', q), - filteredInvitedMembers: this._filterMembers(this.state.members, 'invite', q), + searchQuery, + filteredJoinedMembers: this._filterMembers(this.state.members, 'join', searchQuery), + filteredInvitedMembers: this._filterMembers(this.state.members, 'invite', searchQuery), }); }, @@ -438,6 +437,7 @@ module.exports = React.createClass({ return
; } + const SearchBox = sdk.getComponent('structures.SearchBox'); const TruncatedList = sdk.getComponent("elements.TruncatedList"); const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); @@ -445,7 +445,6 @@ module.exports = React.createClass({ const room = cli.getRoom(this.props.roomId); let inviteButton; if (room && room.getMyMembership() === 'join') { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); inviteButton = @@ -477,9 +476,10 @@ module.exports = React.createClass({ { invitedSection }
- + +
); }, diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index be6fbee4f6..8f3768864b 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -362,34 +362,6 @@ export default class MessageComposer extends React.Component { const canSendMessages = !this.state.tombstone && this.props.room.maySendMessage(); - // TODO: Remove temporary logging for riot-web#7838 - // Note: we rip apart the power level event ourselves because we don't want to - // log too much data about it - just the bits we care about. Many of the variables - // logged here are to help figure out where in the stack the 'cannot post in room' - // warning is coming from. This means logging various numbers from the PL event to - // verify RoomState._maySendEventOfType is doing the right thing. - const room = this.props.room; - const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); - let plEventString = ""; - if (plEvent) { - const content = plEvent.getContent(); - if (!content) { - plEventString = ""; - } else { - const stringifyFalsey = (v) => v === null ? '' : (v === undefined ? '' : v); - const actualUserPl = stringifyFalsey(content.users ? content.users[room.myUserId] : ""); - const usersPl = stringifyFalsey(content.users_default); - const actualEventPl = stringifyFalsey(content.events ? content.events['m.room.message'] : ""); - const eventPl = stringifyFalsey(content.events_default); - plEventString = `actualUserPl=${actualUserPl} defaultUserPl=${usersPl} actualEventPl=${actualEventPl} defaultEventPl=${eventPl}`; - } - } - console.log( - `[riot-web#7838] renderComposer() hasTombstone=${!!this.state.tombstone} maySendMessage=${room.maySendMessage()}` + - ` myMembership=${room.getMyMembership()} maySendEvent=${room.currentState.maySendEvent('m.room.message', room.myUserId)}` + - ` myUserId=${room.myUserId} roomId=${room.roomId} hasPlEvent=${!!plEvent} powerLevels='${plEventString}'` - ); - if (canSendMessages) { // This also currently includes the call buttons. Really we should // check separately for whether we can call, but this is slightly @@ -469,8 +441,6 @@ export default class MessageComposer extends React.Component { ); } else { - // TODO: Remove temporary logging for riot-web#7838 - console.log("[riot-web#7838] Falling back to showing cannot post in room error"); controls.push(
{ _t('You do not have permission to post to this room') } diff --git a/src/components/views/rooms/WhoIsTypingTile.js b/src/components/views/rooms/WhoIsTypingTile.js index dba40f033a..9dd690f6e5 100644 --- a/src/components/views/rooms/WhoIsTypingTile.js +++ b/src/components/views/rooms/WhoIsTypingTile.js @@ -170,6 +170,7 @@ module.exports = React.createClass({ width={24} height={24} resizeMethod="crop" + viewUserOnClick={true} /> ); }); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5e4765b3af..cf90c0a280 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -540,6 +540,7 @@ "Labs": "Labs", "Notifications": "Notifications", "Start automatically after system login": "Start automatically after system login", + "Close button should minimize window to tray": "Close button should minimize window to tray", "Preferences": "Preferences", "Composer": "Composer", "Timeline": "Timeline", @@ -1202,6 +1203,7 @@ "View Decrypted Source": "View Decrypted Source", "Unhide Preview": "Unhide Preview", "Share Message": "Share Message", + "Share Permalink": "Share Permalink", "Quote": "Quote", "Source URL": "Source URL", "Collapse Reply Thread": "Collapse Reply Thread",