diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index ad1656efbb..8199121420 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -18,6 +18,7 @@ limitations under the License. display: flex; flex-direction: row; min-width: 0; + min-height: 0; height: 100%; } diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 36bf96359b..26382b55e8 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -20,35 +20,54 @@ limitations under the License. flex-direction: column; } + +@keyframes mx_RoomView_fileDropTarget_animation { + from { + opacity: 0; + } + to { + opacity: 0.95; + } +} + .mx_RoomView_fileDropTarget { min-width: 0px; width: 100%; + height: 100%; + font-size: $font-18px; text-align: center; pointer-events: none; - padding-left: 12px; - padding-right: 12px; - margin-left: -12px; + background-color: $primary-bg-color; + opacity: 0.95; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - - background-color: $droptarget-bg-color; - border: 2px #e1dddd solid; - border-bottom: none; position: absolute; - top: 52px; - bottom: 0px; z-index: 3000; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + animation: mx_RoomView_fileDropTarget_animation; + animation-duration: 0.5s; } -.mx_RoomView_fileDropTargetLabel { - top: 50%; - width: 100%; - margin-top: -50px; - position: absolute; +@keyframes mx_RoomView_fileDropTarget_image_animation { + from { + width: 0px; + } + to { + width: 32px; + } +} + +.mx_RoomView_fileDropTarget_image { + animation: mx_RoomView_fileDropTarget_image_animation; + animation-duration: 0.5s; + margin-bottom: 16px; } .mx_RoomView_auxPanel { @@ -117,7 +136,6 @@ limitations under the License. } .mx_RoomView_body { - position: relative; //for .mx_RoomView_auxPanel_fullHeight display: flex; flex-direction: column; flex: 1; diff --git a/res/img/upload-big.svg b/res/img/upload-big.svg index 6099c2e976..9a6a265fdb 100644 --- a/res/img/upload-big.svg +++ b/res/img/upload-big.svg @@ -1,19 +1,3 @@ - - - - icons_upload_drop - Created with bin/sketchtool. - - - - - - - - - - - - - + + diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 76bf2ddc21..b6906d16be 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -67,9 +67,6 @@ $groupFilterPanel-bg-color: rgba(232, 232, 232, 0.77); // used by RoomDirectory permissions $plinth-bg-color: $secondary-accent-color; -// used by RoomDropTarget -$droptarget-bg-color: rgba(255,255,255,0.5); - // used by AddressSelector $selected-color: $secondary-accent-color; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 1961779d0e..96808e651e 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -192,6 +192,7 @@ export interface IState { rejecting?: boolean; rejectError?: Error; hasPinnedWidgets?: boolean; + dragCounter: number; } export default class RoomView extends React.Component { @@ -242,6 +243,7 @@ export default class RoomView extends React.Component { canReply: false, layout: SettingsStore.getValue("layout"), matrixClientIsReady: this.context && this.context.isInitialSyncComplete(), + dragCounter: 0, }; this.dispatcherRef = dis.register(this.onAction); @@ -535,8 +537,8 @@ export default class RoomView extends React.Component { if (!roomView.ondrop) { roomView.addEventListener('drop', this.onDrop); roomView.addEventListener('dragover', this.onDragOver); - roomView.addEventListener('dragleave', this.onDragLeaveOrEnd); - roomView.addEventListener('dragend', this.onDragLeaveOrEnd); + roomView.addEventListener('dragenter', this.onDragEnter); + roomView.addEventListener('dragleave', this.onDragLeave); } } @@ -580,8 +582,8 @@ export default class RoomView extends React.Component { const roomView = this.roomView.current; roomView.removeEventListener('drop', this.onDrop); roomView.removeEventListener('dragover', this.onDragOver); - roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd); - roomView.removeEventListener('dragend', this.onDragLeaveOrEnd); + roomView.removeEventListener('dragenter', this.onDragEnter); + roomView.removeEventListener('dragleave', this.onDragLeave); } dis.unregister(this.dispatcherRef); if (this.context) { @@ -1141,6 +1143,31 @@ export default class RoomView extends React.Component { this.updateTopUnreadMessagesBar(); }; + private onDragEnter = ev => { + ev.stopPropagation(); + ev.preventDefault(); + + this.setState({ + dragCounter: this.state.dragCounter + 1, + draggingFile: true, + }); + }; + + private onDragLeave = ev => { + ev.stopPropagation(); + ev.preventDefault(); + + this.setState({ + dragCounter: this.state.dragCounter - 1, + }); + + if (this.state.dragCounter === 0) { + this.setState({ + draggingFile: false, + }); + } + }; + private onDragOver = ev => { ev.stopPropagation(); ev.preventDefault(); @@ -1148,7 +1175,6 @@ export default class RoomView extends React.Component { ev.dataTransfer.dropEffect = 'none'; if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) { - this.setState({ draggingFile: true }); ev.dataTransfer.dropEffect = 'copy'; } }; @@ -1159,14 +1185,12 @@ export default class RoomView extends React.Component { ContentMessages.sharedInstance().sendContentListToRoom( ev.dataTransfer.files, this.state.room.roomId, this.context, ); - this.setState({ draggingFile: false }); dis.fire(Action.FocusComposer); - }; - private onDragLeaveOrEnd = ev => { - ev.stopPropagation(); - ev.preventDefault(); - this.setState({ draggingFile: false }); + this.setState({ + draggingFile: false, + dragCounter: this.state.dragCounter - 1, + }); }; private injectSticker(url, info, text) { @@ -1768,6 +1792,19 @@ export default class RoomView extends React.Component { } } + let fileDropTarget = null; + if (this.state.draggingFile) { + fileDropTarget = ( +
+ + { _t("Drop file here to upload") } +
+ ); + } + // We have successfully loaded this room, and are not previewing. // Display the "normal" room view. @@ -1891,7 +1928,6 @@ export default class RoomView extends React.Component { room={this.state.room} fullHeight={false} userId={this.context.credentials.userId} - draggingFile={this.state.draggingFile} maxHeight={this.state.auxPanelMaxHeight} showApps={this.state.showApps} onResize={this.onResize} @@ -2060,6 +2096,7 @@ export default class RoomView extends React.Component {
{auxPanel}
+ {fileDropTarget} {topUnreadMessagesBar} {jumpToBottom} {messagePanel} diff --git a/src/components/views/rooms/AuxPanel.tsx b/src/components/views/rooms/AuxPanel.tsx index 4ce31be410..d193b98ec1 100644 --- a/src/components/views/rooms/AuxPanel.tsx +++ b/src/components/views/rooms/AuxPanel.tsx @@ -17,10 +17,8 @@ limitations under the License. import React from 'react'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import { Room } from 'matrix-js-sdk/src/models/room' -import * as sdk from '../../../index'; import dis from "../../../dispatcher/dispatcher"; import AppsDrawer from './AppsDrawer'; -import { _t } from '../../../languageHandler'; import classNames from 'classnames'; import RateLimitedFunc from '../../../ratelimitedfunc'; import SettingsStore from "../../../settings/SettingsStore"; @@ -36,9 +34,6 @@ interface IProps { userId: string, showApps: boolean, // Render apps - // set to true to show the file drop target - draggingFile: boolean, - // maxHeight attribute for the aux panel and the video // therein maxHeight: number, @@ -149,21 +144,6 @@ export default class AuxPanel extends React.Component { } render() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); - - let fileDropTarget = null; - if (this.props.draggingFile) { - fileDropTarget = ( -
-
- -
- { _t("Drop file here to upload") } -
-
- ); - } - const callView = ( { { stateViews } { appsDrawer } - { fileDropTarget } { callView } { this.props.children } diff --git a/src/contexts/RoomContext.ts b/src/contexts/RoomContext.ts index b00dc148e4..30ff74b071 100644 --- a/src/contexts/RoomContext.ts +++ b/src/contexts/RoomContext.ts @@ -43,6 +43,7 @@ const RoomContext = createContext({ canReply: false, layout: Layout.Group, matrixClientIsReady: false, + dragCounter: 0, }); RoomContext.displayName = "RoomContext"; export default RoomContext; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a1999acb3b..267721b533 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1419,8 +1419,6 @@ "Remove %(phone)s?": "Remove %(phone)s?", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.", "Phone Number": "Phone Number", - "Drop File Here": "Drop File Here", - "Drop file here to upload": "Drop file here to upload", "This user has not verified all of their sessions.": "This user has not verified all of their sessions.", "You have not verified this user.": "You have not verified this user.", "You have verified this user. This user has verified all of their sessions.": "You have verified this user. This user has verified all of their sessions.", @@ -2589,6 +2587,7 @@ "No more results": "No more results", "Room": "Room", "Failed to reject invite": "Failed to reject invite", + "Drop file here to upload": "Drop file here to upload", "You have %(count)s unread notifications in a prior version of this room.|other": "You have %(count)s unread notifications in a prior version of this room.", "You have %(count)s unread notifications in a prior version of this room.|one": "You have %(count)s unread notification in a prior version of this room.", "Unnamed Space": "Unnamed Space",