From 8b2a478a25352c0a63d1c9a85d4def9c2b6c5b7f Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 21 Dec 2021 09:37:06 +0000 Subject: [PATCH] Update location text fallback and test it (#7408) --- .../views/location/LocationButton.tsx | 92 +++++++++++++++++++ .../views/rooms/CollapsibleButton.tsx | 34 +++++++ .../views/rooms/MessageComposer.tsx | 82 +---------------- src/i18n/strings/en_EN.json | 2 +- .../views/location/LocationButton-test.tsx | 34 +++++++ 5 files changed, 165 insertions(+), 79 deletions(-) create mode 100644 src/components/views/location/LocationButton.tsx create mode 100644 src/components/views/rooms/CollapsibleButton.tsx create mode 100644 test/components/views/location/LocationButton-test.tsx diff --git a/src/components/views/location/LocationButton.tsx b/src/components/views/location/LocationButton.tsx new file mode 100644 index 0000000000..92ee2ee852 --- /dev/null +++ b/src/components/views/location/LocationButton.tsx @@ -0,0 +1,92 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { ReactElement } from 'react'; +import { Room } from "matrix-js-sdk/src/models/room"; +import classNames from 'classnames'; + +import { _t } from '../../../languageHandler'; +import LocationShareType from "./LocationShareType"; +import LocationPicker from './LocationPicker'; +import { CollapsibleButton, ICollapsibleButtonProps } from '../rooms/CollapsibleButton'; +import ContextMenu, { aboveLeftOf, useContextMenu, AboveLeftOf } from "../../structures/ContextMenu"; + +interface IProps extends Pick { + room: Room; + shareLocation: ( + uri: string, + ts: number, + type: LocationShareType, + description: string, + ) => boolean; + menuPosition: AboveLeftOf; + narrowMode: boolean; +} + +export const LocationButton: React.FC = ( + { shareLocation, menuPosition, narrowMode }, +) => { + const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); + + let contextMenu: ReactElement; + if (menuDisplayed) { + const position = menuPosition ?? aboveLeftOf( + button.current.getBoundingClientRect()); + + contextMenu = + + ; + } + + const className = classNames( + "mx_MessageComposer_button", + "mx_MessageComposer_location", + { + "mx_MessageComposer_button_highlight": menuDisplayed, + }, + ); + + // TODO: replace ContextMenuTooltipButton with a unified representation of + // the header buttons and the right panel buttons + return + + + { contextMenu } + ; +}; + +export function textForLocation( + uri: string, + ts: number, + description: string | null, +): string { + const date = new Date(ts).toISOString(); + if (description) { + return `Location "${description}" ${uri} at ${date}`; + } else { + return `Location ${uri} at ${date}`; + } +} + diff --git a/src/components/views/rooms/CollapsibleButton.tsx b/src/components/views/rooms/CollapsibleButton.tsx new file mode 100644 index 0000000000..c66129afbe --- /dev/null +++ b/src/components/views/rooms/CollapsibleButton.tsx @@ -0,0 +1,34 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { ComponentProps } from 'react'; + +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; + +export interface ICollapsibleButtonProps + extends ComponentProps +{ + narrowMode: boolean; + title: string; +} + +export const CollapsibleButton = ({ narrowMode, title, ...props }: ICollapsibleButtonProps) => { + return ; +}; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 9fca185d8e..397d3da84a 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps, createRef, ReactElement } from 'react'; +import React, { createRef } from 'react'; import classNames from 'classnames'; import { MatrixEvent, IEventRelation } from "matrix-js-sdk/src/models/event"; import { Room } from "matrix-js-sdk/src/models/room"; @@ -53,7 +53,6 @@ import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInse import { Action } from "../../../dispatcher/actions"; import EditorModel from "../../../editor/model"; import EmojiPicker from '../emojipicker/EmojiPicker'; -import LocationPicker from '../location/LocationPicker'; import UIStore, { UI_EVENTS } from '../../../stores/UIStore'; import Modal from "../../../Modal"; import RoomContext from '../../../contexts/RoomContext'; @@ -61,6 +60,8 @@ import ErrorDialog from "../dialogs/ErrorDialog"; import PollCreateDialog from "../elements/PollCreateDialog"; import LocationShareType from "../location/LocationShareType"; import { SettingUpdatedPayload } from "../../../dispatcher/payloads/SettingUpdatedPayload"; +import { CollapsibleButton, ICollapsibleButtonProps } from './CollapsibleButton'; +import { LocationButton, textForLocation } from '../location/LocationButton'; let instanceCount = 0; const NARROW_MODE_BREAKPOINT = 500; @@ -80,19 +81,6 @@ function SendButton(props: ISendButtonProps) { ); } -interface ICollapsibleButtonProps extends ComponentProps { - narrowMode: boolean; - title: string; -} - -const CollapsibleButton = ({ narrowMode, title, ...props }: ICollapsibleButtonProps) => { - return ; -}; - interface IEmojiButtonProps extends Pick { addEmoji: (unicode: string) => boolean; menuPosition: AboveLeftOf; @@ -131,54 +119,6 @@ const EmojiButton: React.FC = ({ addEmoji, menuPosition, narr ; }; -interface ILocationButtonProps extends Pick { - room: Room; - shareLocation: (uri: string, ts: number, type: LocationShareType, description: string) => boolean; - menuPosition: AboveLeftOf; - narrowMode: boolean; -} - -const LocationButton: React.FC = ( - { shareLocation, menuPosition, narrowMode }, -) => { - const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); - - let contextMenu: ReactElement; - if (menuDisplayed) { - const position = menuPosition ?? aboveLeftOf( - button.current.getBoundingClientRect()); - - contextMenu = - - ; - } - - const className = classNames( - "mx_MessageComposer_button", - "mx_MessageComposer_location", - { - "mx_MessageComposer_button_highlight": menuDisplayed, - }, - ); - - // TODO: replace ContextMenuTooltipButton with a unified representation of - // the header buttons and the right panel buttons - return - - - { contextMenu } - ; -}; - interface IUploadButtonProps { roomId: string; relation?: IEventRelation | null; @@ -513,20 +453,6 @@ export default class MessageComposer extends React.Component { return true; }; - private textForLocation = ( - uri: string, - ts: number, - description: string | null, - ): string => { - const date = new Date(ts).toISOString(); - // TODO: translation, as soon as we've re-worded this better - if (description) { - return `${description} at ${uri} as of ${date}`; - } else { - return `Location at ${uri} as of ${date}`; - } - }; - private shareLocation = ( uri: string, ts: number, @@ -535,7 +461,7 @@ export default class MessageComposer extends React.Component { ): boolean => { if (!uri) return false; try { - const text = this.textForLocation(uri, ts, description); + const text = textForLocation(uri, ts, description); MatrixClientPeg.get().sendMessage( this.props.room.roomId, makeLocationContent(text, uri, ts, description), diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index edd793887f..e07cf5a32b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1666,7 +1666,6 @@ "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)", "Send message": "Send message", "Add emoji": "Add emoji", - "Share location": "Share location", "Upload file": "Upload file", "You do not have permission to start polls in this room.": "You do not have permission to start polls in this room.", "Create poll": "Create poll", @@ -2121,6 +2120,7 @@ "edited": "edited", "Submit logs": "Submit logs", "Can't load this message": "Can't load this message", + "Share location": "Share location", "Share custom location": "Share custom location", "Share my current location as a once off": "Share my current location as a once off", "My location": "My location", diff --git a/test/components/views/location/LocationButton-test.tsx b/test/components/views/location/LocationButton-test.tsx new file mode 100644 index 0000000000..66c9fd08bd --- /dev/null +++ b/test/components/views/location/LocationButton-test.tsx @@ -0,0 +1,34 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from "../../../skinned-sdk"; +import { textForLocation } from "../../../../src/components/views/location/LocationButton"; + +sdk.getComponent("LocationPicker"); + +describe("LocationButton", () => { + describe("textForLocation", () => { + it("with no description, simply dumps URI and date", () => { + expect(textForLocation("geo:43.2,54.6", 12345, null)).toBe( + "Location geo:43.2,54.6 at 1970-01-01T00:00:12.345Z"); + }); + + it("with a description, includes that in the text", () => { + expect(textForLocation("geo:12,43,3;u=2", 54321, "Me!")).toBe( + 'Location "Me!" geo:12,43,3;u=2 at 1970-01-01T00:00:54.321Z'); + }); + }); +});