Add basic types
This commit is contained in:
parent
0e92251f70
commit
d7e6f4b4b5
29 changed files with 542 additions and 340 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2015, 2016, 2017, 2018, 2019 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2015-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.
|
||||
|
@ -94,7 +94,7 @@ interface IState {
|
|||
// be seeing.
|
||||
serverIsAlive: boolean;
|
||||
serverErrorIsFatal: boolean;
|
||||
serverDeadError: string;
|
||||
serverDeadError?: ReactNode;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2015, 2016, 2017, 2018, 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2015-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.
|
||||
|
@ -95,7 +95,7 @@ interface IState {
|
|||
// be seeing.
|
||||
serverIsAlive: boolean;
|
||||
serverErrorIsFatal: boolean;
|
||||
serverDeadError: string;
|
||||
serverDeadError?: ReactNode;
|
||||
|
||||
// Our matrix client - part of state because we can't render the UI auth
|
||||
// component without it.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019-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.
|
||||
|
@ -15,14 +15,13 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t} from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as Lifecycle from '../../../Lifecycle';
|
||||
import Modal from '../../../Modal';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import {sendLoginRequest} from "../../../Login";
|
||||
import {ISSOFlow, LoginFlow, sendLoginRequest} from "../../../Login";
|
||||
import AuthPage from "../../views/auth/AuthPage";
|
||||
import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "../../../BasePlatform";
|
||||
import SSOButtons from "../../views/elements/SSOButtons";
|
||||
|
@ -42,26 +41,38 @@ const FLOWS_TO_VIEWS = {
|
|||
"m.login.sso": LOGIN_VIEW.SSO,
|
||||
};
|
||||
|
||||
@replaceableComponent("structures.auth.SoftLogout")
|
||||
export default class SoftLogout extends React.Component {
|
||||
static propTypes = {
|
||||
// Query parameters from MatrixChat
|
||||
realQueryParams: PropTypes.object, // {loginToken}
|
||||
|
||||
// Called when the SSO login completes
|
||||
onTokenLoginCompleted: PropTypes.func,
|
||||
interface IProps {
|
||||
// Query parameters from MatrixChat
|
||||
realQueryParams: {
|
||||
loginToken?: string;
|
||||
};
|
||||
fragmentAfterLogin?: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Called when the SSO login completes
|
||||
onTokenLoginCompleted: () => void,
|
||||
}
|
||||
|
||||
interface IState {
|
||||
loginView: number;
|
||||
keyBackupNeeded: boolean;
|
||||
busy: boolean;
|
||||
password: string;
|
||||
errorText: string;
|
||||
flows: LoginFlow[];
|
||||
}
|
||||
|
||||
@replaceableComponent("structures.auth.SoftLogout")
|
||||
export default class SoftLogout extends React.Component<IProps, IState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loginView: LOGIN_VIEW.LOADING,
|
||||
keyBackupNeeded: true, // assume we do while we figure it out (see componentDidMount)
|
||||
|
||||
busy: false,
|
||||
password: "",
|
||||
errorText: "",
|
||||
flows: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -247,7 +258,7 @@ export default class SoftLogout extends React.Component {
|
|||
} // else we already have a message and should use it (key backup warning)
|
||||
|
||||
const loginType = this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso";
|
||||
const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType);
|
||||
const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType) as ISSOFlow;
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2020-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.
|
||||
|
@ -110,7 +110,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
|||
console.error(e);
|
||||
|
||||
const stateForError = AutoDiscoveryUtils.authComponentStateForError(e);
|
||||
if (stateForError.isFatalError) {
|
||||
if (stateForError.serverErrorIsFatal) {
|
||||
let error = _t("Unable to validate homeserver");
|
||||
if (e.translatedMessage) {
|
||||
error = e.translatedMessage;
|
||||
|
@ -168,7 +168,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
|||
text = _t("Matrix.org is the biggest public homeserver in the world, so it’s a good place for many.");
|
||||
}
|
||||
|
||||
let defaultServerName = this.defaultServer.hsName;
|
||||
let defaultServerName: React.ReactNode = this.defaultServer.hsName;
|
||||
if (this.defaultServer.hsNameIsDifferent) {
|
||||
defaultServerName = (
|
||||
<TextWithTooltip class="mx_Login_underlinedServerName" tooltip={this.defaultServer.hsUrl}>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2020-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.
|
||||
|
@ -67,7 +67,7 @@ const ServerPicker = ({ title, dialogTitle, serverConfig, onServerConfigChange }
|
|||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
let serverName = serverConfig.isNameResolvable ? serverConfig.hsName : serverConfig.hsUrl;
|
||||
let serverName: React.ReactNode = serverConfig.isNameResolvable ? serverConfig.hsName : serverConfig.hsUrl;
|
||||
if (serverConfig.hsNameIsDifferent) {
|
||||
serverName = <TextWithTooltip class="mx_Login_underlinedServerName" tooltip={serverConfig.hsUrl}>
|
||||
{serverConfig.hsName}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2015-2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
Copyright 2019 - 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.
|
||||
|
@ -15,11 +15,13 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import classNames from "classnames";
|
||||
import {EventType} from "matrix-js-sdk/src/@types/event";
|
||||
import {EventStatus} from 'matrix-js-sdk/src/models/event';
|
||||
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Relations } from "matrix-js-sdk/src/models/relations";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
|
||||
import ReplyThread from "../elements/ReplyThread";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -27,7 +29,7 @@ import * as TextForEvent from "../../../TextForEvent";
|
|||
import * as sdk from "../../../index";
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {Layout, LayoutPropType} from "../../../settings/Layout";
|
||||
import {Layout} from "../../../settings/Layout";
|
||||
import {formatTime} from "../../../DateUtils";
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
|
||||
|
@ -40,6 +42,8 @@ import {WIDGET_LAYOUT_EVENT_TYPE} from "../../../stores/widgets/WidgetLayoutStor
|
|||
import {objectHasDiff} from "../../../utils/objects";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import Tooltip from "../elements/Tooltip";
|
||||
import { EditorStateTransfer } from "../../../utils/EditorStateTransfer";
|
||||
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||
|
||||
const eventTileTypes = {
|
||||
[EventType.RoomMessage]: 'messages.MessageEvent',
|
||||
|
@ -169,101 +173,130 @@ const MAX_READ_AVATARS = 5;
|
|||
// | '--------------------------------------' |
|
||||
// '----------------------------------------------------------'
|
||||
|
||||
interface IReadReceiptProps {
|
||||
userId: string;
|
||||
roomMember: RoomMember;
|
||||
ts: number;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
// the MatrixEvent to show
|
||||
mxEvent: MatrixEvent;
|
||||
|
||||
// true if mxEvent is redacted. This is a prop because using mxEvent.isRedacted()
|
||||
// might not be enough when deciding shouldComponentUpdate - prevProps.mxEvent
|
||||
// references the same this.props.mxEvent.
|
||||
isRedacted?: boolean;
|
||||
|
||||
// true if this is a continuation of the previous event (which has the
|
||||
// effect of not showing another avatar/displayname
|
||||
continuation?: boolean;
|
||||
|
||||
// true if this is the last event in the timeline (which has the effect
|
||||
// of always showing the timestamp)
|
||||
last?: boolean;
|
||||
|
||||
// true if the event is the last event in a section (adds a css class for
|
||||
// targeting)
|
||||
lastInSection?: boolean;
|
||||
|
||||
// True if the event is the last successful (sent) event.
|
||||
lastSuccessful?: boolean;
|
||||
|
||||
// true if this is search context (which has the effect of greying out
|
||||
// the text
|
||||
contextual?: boolean;
|
||||
|
||||
// a list of words to highlight, ordered by longest first
|
||||
highlights?: string[];
|
||||
|
||||
// link URL for the highlights
|
||||
highlightLink?: string;
|
||||
|
||||
// should show URL previews for this event
|
||||
showUrlPreview?: boolean;
|
||||
|
||||
// is this the focused event
|
||||
isSelectedEvent?: boolean;
|
||||
|
||||
// callback called when dynamic content in events are loaded
|
||||
onHeightChanged?: () => void,
|
||||
|
||||
// a list of read-receipts we should show. Each object has a 'roomMember' and 'ts'.
|
||||
readReceipts?: IReadReceiptProps[],
|
||||
|
||||
// opaque readreceipt info for each userId; used by ReadReceiptMarker
|
||||
// to manage its animations. Should be an empty object when the room
|
||||
// first loads
|
||||
readReceiptMap?: any,
|
||||
|
||||
// A function which is used to check if the parent panel is being
|
||||
// unmounted, to avoid unnecessary work. Should return true if we
|
||||
// are being unmounted.
|
||||
checkUnmounting?: () => boolean,
|
||||
|
||||
// the status of this event - ie, mxEvent.status. Denormalised to here so
|
||||
// that we can tell when it changes.
|
||||
eventSendStatus?: string;
|
||||
|
||||
// the shape of the tile. by default, the layout is intended for the
|
||||
// normal room timeline. alternative values are: "file_list", "file_grid"
|
||||
// and "notif". This could be done by CSS, but it'd be horribly inefficient.
|
||||
// It could also be done by subclassing EventTile, but that'd be quite
|
||||
// boiilerplatey. So just make the necessary render decisions conditional
|
||||
// for now.
|
||||
tileShape?: string;
|
||||
|
||||
// show twelve hour timestamps
|
||||
isTwelveHour?: boolean;
|
||||
|
||||
// helper function to access relations for this event
|
||||
getRelationsForEvent?: (eventId: string, relationType: string, eventType: string) => Relations,
|
||||
|
||||
// whether to show reactions for this event
|
||||
showReactions?: boolean;
|
||||
|
||||
// which layout to use
|
||||
layout: Layout,
|
||||
|
||||
// whether or not to show flair at all
|
||||
enableFlair?: boolean;
|
||||
|
||||
// whether or not to show read receipts
|
||||
showReadReceipts?: boolean;
|
||||
|
||||
// Used while editing, to pass the event, and to preserve editor state
|
||||
// from one editor instance to another when remounting the editor
|
||||
// upon receiving the remote echo for an unsent event.
|
||||
editState?: EditorStateTransfer;
|
||||
|
||||
// Event ID of the event replacing the content of this event, if any
|
||||
replacingEventId?: string;
|
||||
|
||||
// Helper to build permalinks for the room
|
||||
permalinkCreator?: RoomPermalinkCreator;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
// Whether the action bar is focused.
|
||||
actionBarFocused: boolean;
|
||||
// Whether all read receipts are being displayed. If not, only display
|
||||
// a truncation of them.
|
||||
allReadAvatars: boolean;
|
||||
// Whether the event's sender has been verified.
|
||||
verified: string;
|
||||
// Whether onRequestKeysClick has been called since mounting.
|
||||
previouslyRequestedKeys: boolean;
|
||||
// The Relations model from the JS SDK for reactions to `mxEvent`
|
||||
reactions: Relations;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.rooms.EventTile")
|
||||
export default class EventTile extends React.Component {
|
||||
static propTypes = {
|
||||
/* the MatrixEvent to show */
|
||||
mxEvent: PropTypes.object.isRequired,
|
||||
|
||||
/* true if mxEvent is redacted. This is a prop because using mxEvent.isRedacted()
|
||||
* might not be enough when deciding shouldComponentUpdate - prevProps.mxEvent
|
||||
* references the same this.props.mxEvent.
|
||||
*/
|
||||
isRedacted: PropTypes.bool,
|
||||
|
||||
/* true if this is a continuation of the previous event (which has the
|
||||
* effect of not showing another avatar/displayname
|
||||
*/
|
||||
continuation: PropTypes.bool,
|
||||
|
||||
/* true if this is the last event in the timeline (which has the effect
|
||||
* of always showing the timestamp)
|
||||
*/
|
||||
last: PropTypes.bool,
|
||||
|
||||
// true if the event is the last event in a section (adds a css class for
|
||||
// targeting)
|
||||
lastInSection: PropTypes.bool,
|
||||
|
||||
// True if the event is the last successful (sent) event.
|
||||
isLastSuccessful: PropTypes.bool,
|
||||
|
||||
/* true if this is search context (which has the effect of greying out
|
||||
* the text
|
||||
*/
|
||||
contextual: PropTypes.bool,
|
||||
|
||||
/* a list of words to highlight, ordered by longest first */
|
||||
highlights: PropTypes.array,
|
||||
|
||||
/* link URL for the highlights */
|
||||
highlightLink: PropTypes.string,
|
||||
|
||||
/* should show URL previews for this event */
|
||||
showUrlPreview: PropTypes.bool,
|
||||
|
||||
/* is this the focused event */
|
||||
isSelectedEvent: PropTypes.bool,
|
||||
|
||||
/* callback called when dynamic content in events are loaded */
|
||||
onHeightChanged: PropTypes.func,
|
||||
|
||||
/* a list of read-receipts we should show. Each object has a 'roomMember' and 'ts'. */
|
||||
readReceipts: PropTypes.arrayOf(PropTypes.object),
|
||||
|
||||
/* opaque readreceipt info for each userId; used by ReadReceiptMarker
|
||||
* to manage its animations. Should be an empty object when the room
|
||||
* first loads
|
||||
*/
|
||||
readReceiptMap: PropTypes.object,
|
||||
|
||||
/* A function which is used to check if the parent panel is being
|
||||
* unmounted, to avoid unnecessary work. Should return true if we
|
||||
* are being unmounted.
|
||||
*/
|
||||
checkUnmounting: PropTypes.func,
|
||||
|
||||
/* the status of this event - ie, mxEvent.status. Denormalised to here so
|
||||
* that we can tell when it changes. */
|
||||
eventSendStatus: PropTypes.string,
|
||||
|
||||
/* the shape of the tile. by default, the layout is intended for the
|
||||
* normal room timeline. alternative values are: "file_list", "file_grid"
|
||||
* and "notif". This could be done by CSS, but it'd be horribly inefficient.
|
||||
* It could also be done by subclassing EventTile, but that'd be quite
|
||||
* boiilerplatey. So just make the necessary render decisions conditional
|
||||
* for now.
|
||||
*/
|
||||
tileShape: PropTypes.string,
|
||||
|
||||
// show twelve hour timestamps
|
||||
isTwelveHour: PropTypes.bool,
|
||||
|
||||
// helper function to access relations for this event
|
||||
getRelationsForEvent: PropTypes.func,
|
||||
|
||||
// whether to show reactions for this event
|
||||
showReactions: PropTypes.bool,
|
||||
|
||||
// which layout to use
|
||||
layout: LayoutPropType,
|
||||
|
||||
// whether or not to show flair at all
|
||||
enableFlair: PropTypes.bool,
|
||||
|
||||
// whether or not to show read receipts
|
||||
showReadReceipts: PropTypes.bool,
|
||||
};
|
||||
export default class EventTile extends React.Component<IProps, IState> {
|
||||
private _suppressReadReceiptAnimation: boolean;
|
||||
private _isListeningForReceipts: boolean;
|
||||
private _tile = React.createRef();
|
||||
private _replyThread = React.createRef();
|
||||
|
||||
static defaultProps = {
|
||||
// no-op function because onHeightChanged is optional yet some sub-components assume its existence
|
||||
|
@ -292,9 +325,6 @@ export default class EventTile extends React.Component {
|
|||
// don't do RR animations until we are mounted
|
||||
this._suppressReadReceiptAnimation = true;
|
||||
|
||||
this._tile = createRef();
|
||||
this._replyThread = createRef();
|
||||
|
||||
// Throughout the component we manage a read receipt listener to see if our tile still
|
||||
// qualifies for a "sent" or "sending" state (based on their relevant conditions). We
|
||||
// don't want to over-subscribe to the read receipt events being fired, so we use a flag
|
||||
|
@ -1190,14 +1220,18 @@ function E2ePadlockUnauthenticated(props) {
|
|||
);
|
||||
}
|
||||
|
||||
class E2ePadlock extends React.Component {
|
||||
static propTypes = {
|
||||
icon: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
};
|
||||
interface IE2ePadlockProps {
|
||||
icon: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
interface IE2ePadlockState {
|
||||
hover: boolean;
|
||||
}
|
||||
|
||||
class E2ePadlock extends React.Component<IE2ePadlockProps, IE2ePadlockState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
hover: false,
|
||||
|
@ -1215,14 +1249,13 @@ class E2ePadlock extends React.Component {
|
|||
render() {
|
||||
let tooltip = null;
|
||||
if (this.state.hover) {
|
||||
tooltip = <Tooltip className="mx_EventTile_e2eIcon_tooltip" label={this.props.title} dir="auto" />;
|
||||
tooltip = <Tooltip className="mx_EventTile_e2eIcon_tooltip" label={this.props.title} />;
|
||||
}
|
||||
|
||||
const classes = `mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${this.props.icon}`;
|
||||
return (
|
||||
<div
|
||||
className={classes}
|
||||
onClick={this.onClick}
|
||||
onMouseEnter={this.onHoverStart}
|
||||
onMouseLeave={this.onHoverEnd}
|
||||
>{tooltip}</div>
|
||||
|
@ -1239,8 +1272,8 @@ interface ISentReceiptState {
|
|||
}
|
||||
|
||||
class SentReceipt extends React.PureComponent<ISentReceiptProps, ISentReceiptState> {
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
hover: false,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2015-2018, 2020, 2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2015-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.
|
||||
|
@ -13,15 +13,17 @@ 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, {createRef} from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import * as sdk from '../../../index';
|
||||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import {Room} from "matrix-js-sdk/src/models/room";
|
||||
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Stickerpicker from './Stickerpicker';
|
||||
import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
|
||||
import { makeRoomPermalink, RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||
import ContentMessages from '../../../ContentMessages';
|
||||
import E2EIcon from './E2EIcon';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
@ -35,19 +37,26 @@ import VoiceRecordComposerTile from "./VoiceRecordComposerTile";
|
|||
import {VoiceRecordingStore} from "../../../stores/VoiceRecordingStore";
|
||||
import {RecordingState} from "../../../voice/VoiceRecording";
|
||||
import Tooltip, {Alignment} from "../elements/Tooltip";
|
||||
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||
import { E2EStatus } from '../../../utils/ShieldUtils';
|
||||
import SendMessageComposer from "./SendMessageComposer";
|
||||
|
||||
function ComposerAvatar(props) {
|
||||
interface IComposerAvatarProps {
|
||||
me: object;
|
||||
}
|
||||
|
||||
function ComposerAvatar(props: IComposerAvatarProps) {
|
||||
const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar');
|
||||
return <div className="mx_MessageComposer_avatar">
|
||||
<MemberStatusMessageAvatar member={props.me} width={24} height={24} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
ComposerAvatar.propTypes = {
|
||||
me: PropTypes.object.isRequired,
|
||||
};
|
||||
interface ISendButtonProps {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
function SendButton(props) {
|
||||
function SendButton(props: ISendButtonProps) {
|
||||
return (
|
||||
<AccessibleTooltipButton
|
||||
className="mx_MessageComposer_sendMessage"
|
||||
|
@ -57,10 +66,6 @@ function SendButton(props) {
|
|||
);
|
||||
}
|
||||
|
||||
SendButton.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const EmojiButton = ({addEmoji}) => {
|
||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||
|
||||
|
@ -68,7 +73,7 @@ const EmojiButton = ({addEmoji}) => {
|
|||
if (menuDisplayed) {
|
||||
const buttonRect = button.current.getBoundingClientRect();
|
||||
const EmojiPicker = sdk.getComponent('emojipicker.EmojiPicker');
|
||||
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} catchTab={false}>
|
||||
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu}>
|
||||
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
|
||||
</ContextMenu>;
|
||||
}
|
||||
|
@ -98,17 +103,17 @@ const EmojiButton = ({addEmoji}) => {
|
|||
</React.Fragment>;
|
||||
};
|
||||
|
||||
class UploadButton extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
}
|
||||
interface IUploadButtonProps {
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
class UploadButton extends React.Component<IUploadButtonProps> {
|
||||
private _uploadInput = React.createRef<HTMLInputElement>();
|
||||
private _dispatcherRef: string;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onUploadClick = this.onUploadClick.bind(this);
|
||||
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
||||
|
||||
this._uploadInput = createRef();
|
||||
this._dispatcherRef = dis.register(this.onAction);
|
||||
}
|
||||
|
||||
|
@ -116,13 +121,13 @@ class UploadButton extends React.Component {
|
|||
dis.unregister(this._dispatcherRef);
|
||||
}
|
||||
|
||||
onAction = payload => {
|
||||
private onAction = payload => {
|
||||
if (payload.action === "upload_file") {
|
||||
this.onUploadClick();
|
||||
}
|
||||
};
|
||||
|
||||
onUploadClick(ev) {
|
||||
private onUploadClick = () => {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
|
@ -130,7 +135,7 @@ class UploadButton extends React.Component {
|
|||
this._uploadInput.current.click();
|
||||
}
|
||||
|
||||
onUploadFileInputChange(ev) {
|
||||
private onUploadFileInputChange = (ev) => {
|
||||
if (ev.target.files.length === 0) return;
|
||||
|
||||
// take a copy so we can safely reset the value of the form control
|
||||
|
@ -171,19 +176,34 @@ class UploadButton extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
resizeNotifier: ResizeNotifier;
|
||||
permalinkCreator: RoomPermalinkCreator;
|
||||
replyToEvent?: MatrixEvent;
|
||||
e2eStatus?: E2EStatus;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
tombstone: MatrixEvent;
|
||||
canSendMessages: boolean;
|
||||
isComposerEmpty: boolean;
|
||||
haveRecording: boolean;
|
||||
recordingTimeLeftSeconds?: number;
|
||||
me?: RoomMember;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.rooms.MessageComposer")
|
||||
export default class MessageComposer extends React.Component {
|
||||
export default class MessageComposer extends React.Component<IProps, IState> {
|
||||
private dispatcherRef: string;
|
||||
private messageComposerInput: SendMessageComposer;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onInputStateChanged = this.onInputStateChanged.bind(this);
|
||||
this._onRoomStateEvents = this._onRoomStateEvents.bind(this);
|
||||
this._onTombstoneClick = this._onTombstoneClick.bind(this);
|
||||
this.renderPlaceholderText = this.renderPlaceholderText.bind(this);
|
||||
VoiceRecordingStore.instance.on(UPDATE_EVENT, this._onVoiceStoreUpdate);
|
||||
this._dispatcherRef = null;
|
||||
|
||||
this.state = {
|
||||
tombstone: this._getRoomTombstone(),
|
||||
tombstone: this.getRoomTombstone(),
|
||||
canSendMessages: this.props.room.maySendMessage(),
|
||||
isComposerEmpty: true,
|
||||
haveRecording: false,
|
||||
|
@ -191,7 +211,13 @@ export default class MessageComposer extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
onAction = (payload) => {
|
||||
componentDidMount() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents);
|
||||
this.waitForOwnMember();
|
||||
}
|
||||
|
||||
private onAction = (payload) => {
|
||||
if (payload.action === 'reply_to_event') {
|
||||
// add a timeout for the reply preview to be rendered, so
|
||||
// that the ScrollPanel listening to the resizeNotifier can
|
||||
|
@ -203,13 +229,7 @@ export default class MessageComposer extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents);
|
||||
this._waitForOwnMember();
|
||||
}
|
||||
|
||||
_waitForOwnMember() {
|
||||
private waitForOwnMember() {
|
||||
// if we have the member already, do that
|
||||
const me = this.props.room.getMember(MatrixClientPeg.get().getUserId());
|
||||
if (me) {
|
||||
|
@ -227,34 +247,28 @@ export default class MessageComposer extends React.Component {
|
|||
|
||||
componentWillUnmount() {
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("RoomState.events", this._onRoomStateEvents);
|
||||
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
|
||||
}
|
||||
VoiceRecordingStore.instance.off(UPDATE_EVENT, this._onVoiceStoreUpdate);
|
||||
dis.unregister(this.dispatcherRef);
|
||||
}
|
||||
|
||||
_onRoomStateEvents(ev, state) {
|
||||
private onRoomStateEvents = (ev, state) => {
|
||||
if (ev.getRoomId() !== this.props.room.roomId) return;
|
||||
|
||||
if (ev.getType() === 'm.room.tombstone') {
|
||||
this.setState({tombstone: this._getRoomTombstone()});
|
||||
this.setState({tombstone: this.getRoomTombstone()});
|
||||
}
|
||||
if (ev.getType() === 'm.room.power_levels') {
|
||||
this.setState({canSendMessages: this.props.room.maySendMessage()});
|
||||
}
|
||||
}
|
||||
|
||||
_getRoomTombstone() {
|
||||
private getRoomTombstone() {
|
||||
return this.props.room.currentState.getStateEvents('m.room.tombstone', '');
|
||||
}
|
||||
|
||||
onInputStateChanged(inputState) {
|
||||
// Merge the new input state with old to support partial updates
|
||||
inputState = Object.assign({}, this.state.inputState, inputState);
|
||||
this.setState({inputState});
|
||||
}
|
||||
|
||||
_onTombstoneClick(ev) {
|
||||
private onTombstoneClick = (ev) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
||||
|
@ -284,7 +298,7 @@ export default class MessageComposer extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
renderPlaceholderText() {
|
||||
private renderPlaceholderText = () => {
|
||||
if (this.props.replyToEvent) {
|
||||
if (this.props.e2eStatus) {
|
||||
return _t('Send an encrypted reply…');
|
||||
|
@ -386,7 +400,7 @@ export default class MessageComposer extends React.Component {
|
|||
const continuesLink = replacementRoomId ? (
|
||||
<a href={makeRoomPermalink(replacementRoomId)}
|
||||
className="mx_MessageComposer_roomReplaced_link"
|
||||
onClick={this._onTombstoneClick}
|
||||
onClick={this.onTombstoneClick}
|
||||
>
|
||||
{_t("The conversation continues here.")}
|
||||
</a>
|
||||
|
@ -433,14 +447,3 @@ export default class MessageComposer extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposer.propTypes = {
|
||||
// js-sdk Room object
|
||||
room: PropTypes.object.isRequired,
|
||||
|
||||
// string representing the current voip call state
|
||||
callState: PropTypes.string,
|
||||
|
||||
// string representing the current room app drawer state
|
||||
showApps: PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd.
|
||||
Copyright 2019-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.
|
||||
|
@ -15,9 +15,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import {Room} from "matrix-js-sdk/src/models/room";
|
||||
import {_t} from "../../../languageHandler";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import * as sdk from "../../../index";
|
||||
|
@ -27,11 +27,22 @@ import RoomAvatar from "../avatars/RoomAvatar";
|
|||
import RoomName from "../elements/RoomName";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
interface IProps {
|
||||
event: MatrixEvent;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
stateKey: string;
|
||||
roomId: string;
|
||||
displayName: string;
|
||||
invited: boolean;
|
||||
canKick: boolean;
|
||||
senderName: string;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.rooms.ThirdPartyMemberInfo")
|
||||
export default class ThirdPartyMemberInfo extends React.Component {
|
||||
static propTypes = {
|
||||
event: PropTypes.instanceOf(MatrixEvent).isRequired,
|
||||
};
|
||||
export default class ThirdPartyMemberInfo extends React.Component<IProps, IState> {
|
||||
private room: Room;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2020-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.
|
||||
|
@ -28,10 +28,17 @@ import {SettingLevel} from "../../../settings/SettingLevel";
|
|||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import SeshatResetDialog from '../dialogs/SeshatResetDialog';
|
||||
|
||||
interface IState {
|
||||
enabling: boolean;
|
||||
eventIndexSize: number;
|
||||
roomCount: number;
|
||||
eventIndexingEnabled: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.EventIndexPanel")
|
||||
export default class EventIndexPanel extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
export default class EventIndexPanel extends React.Component<{}, IState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
enabling: false,
|
||||
|
@ -68,7 +75,7 @@ export default class EventIndexPanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
async componentDidMount(): void {
|
||||
componentDidMount(): void {
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
|
@ -104,6 +111,8 @@ export default class EventIndexPanel extends React.Component {
|
|||
|
||||
_onManage = async () => {
|
||||
Modal.createTrackedDialogAsync('Message search', 'Message search',
|
||||
// @ts-ignore: TS doesn't seem to like the type of this now that it
|
||||
// has also been converted to TS as well, but I can't figure out why...
|
||||
import('../../../async-components/views/dialogs/eventindex/ManageEventIndexDialog'),
|
||||
{
|
||||
onFinished: () => {},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019-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.
|
||||
|
@ -16,7 +16,6 @@ limitations under the License.
|
|||
|
||||
import url from 'url';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t} from "../../../languageHandler";
|
||||
import * as sdk from '../../../index';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
|
@ -59,16 +58,28 @@ async function checkIdentityServerUrl(u) {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.SetIdServer")
|
||||
export default class SetIdServer extends React.Component {
|
||||
static propTypes = {
|
||||
// Whether or not the ID server is missing terms. This affects the text
|
||||
// shown to the user.
|
||||
missingTerms: PropTypes.bool,
|
||||
};
|
||||
interface IProps {
|
||||
// Whether or not the ID server is missing terms. This affects the text
|
||||
// shown to the user.
|
||||
missingTerms: boolean;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
interface IState {
|
||||
defaultIdServer?: string;
|
||||
currentClientIdServer: string;
|
||||
idServer?: string;
|
||||
error?: string;
|
||||
busy: boolean;
|
||||
disconnectBusy: boolean;
|
||||
checking: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.SetIdServer")
|
||||
export default class SetIdServer extends React.Component<IProps, IState> {
|
||||
private dispatcherRef: string;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let defaultIdServer = '';
|
||||
if (!MatrixClientPeg.get().getIdentityServerUrl() && getDefaultIdentityServerUrl()) {
|
||||
|
@ -371,7 +382,7 @@ export default class SetIdServer extends React.Component {
|
|||
|
||||
let discoSection;
|
||||
if (idServerUrl) {
|
||||
let discoButtonContent = _t("Disconnect");
|
||||
let discoButtonContent: React.ReactNode = _t("Disconnect");
|
||||
let discoBodyText = _t(
|
||||
"Disconnecting from your identity server will mean you " +
|
||||
"won't be discoverable by other users and you won't be " +
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019, 2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019-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.
|
||||
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t, _td} from "../../../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../..";
|
||||
|
@ -23,6 +22,7 @@ import AccessibleButton from "../../../elements/AccessibleButton";
|
|||
import Modal from "../../../../../Modal";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
import {EventType} from "matrix-js-sdk/src/@types/event";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
|
||||
const plEventsToLabels = {
|
||||
// These will be translated for us later.
|
||||
|
@ -63,14 +63,14 @@ function parseIntWithDefault(val, def) {
|
|||
return isNaN(res) ? def : res;
|
||||
}
|
||||
|
||||
export class BannedUser extends React.Component {
|
||||
static propTypes = {
|
||||
canUnban: PropTypes.bool,
|
||||
member: PropTypes.object.isRequired, // js-sdk RoomMember
|
||||
by: PropTypes.string.isRequired,
|
||||
reason: PropTypes.string,
|
||||
};
|
||||
interface IBannedUserProps {
|
||||
canUnban: boolean;
|
||||
member: RoomMember;
|
||||
by: string;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export class BannedUser extends React.Component<IBannedUserProps> {
|
||||
_onUnbanClick = (e) => {
|
||||
MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
@ -107,12 +107,12 @@ export class BannedUser extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab")
|
||||
export default class RolesRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
};
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab")
|
||||
export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||
componentDidMount(): void {
|
||||
MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2019-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.
|
||||
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../..";
|
||||
|
@ -26,16 +25,28 @@ import StyledRadioGroup from '../../../elements/StyledRadioGroup';
|
|||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import {UIFeature} from "../../../../../settings/UIFeature";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||
|
||||
type JoinRule = "public" | "knock" | "invite" | "private";
|
||||
type GuestAccess = "can_join" | "forbidden";
|
||||
type History = "invited" | "joined" | "shared" | "world_readable";
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
joinRule: JoinRule;
|
||||
guestAccess: GuestAccess;
|
||||
history: History;
|
||||
hasAliases: boolean;
|
||||
encrypted: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.SecurityRoomSettingsTab")
|
||||
export default class SecurityRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
export default class SecurityRoomSettingsTab extends React.Component<IProps, IState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
joinRule: "invite",
|
||||
|
@ -47,23 +58,23 @@ export default class SecurityRoomSettingsTab extends React.Component {
|
|||
}
|
||||
|
||||
// TODO: [REACT-WARNING] Move this to constructor
|
||||
async UNSAFE_componentWillMount(): void { // eslint-disable-line camelcase
|
||||
async UNSAFE_componentWillMount(): Promise<void> { // eslint-disable-line camelcase
|
||||
MatrixClientPeg.get().on("RoomState.events", this._onStateEvent);
|
||||
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
const state = room.currentState;
|
||||
|
||||
const joinRule = this._pullContentPropertyFromEvent(
|
||||
const joinRule: JoinRule = this._pullContentPropertyFromEvent(
|
||||
state.getStateEvents("m.room.join_rules", ""),
|
||||
'join_rule',
|
||||
'invite',
|
||||
);
|
||||
const guestAccess = this._pullContentPropertyFromEvent(
|
||||
const guestAccess: GuestAccess = this._pullContentPropertyFromEvent(
|
||||
state.getStateEvents("m.room.guest_access", ""),
|
||||
'guest_access',
|
||||
'forbidden',
|
||||
);
|
||||
const history = this._pullContentPropertyFromEvent(
|
||||
const history: History = this._pullContentPropertyFromEvent(
|
||||
state.getStateEvents("m.room.history_visibility", ""),
|
||||
'history_visibility',
|
||||
'shared',
|
||||
|
@ -163,8 +174,8 @@ export default class SecurityRoomSettingsTab extends React.Component {
|
|||
// invite them, you clearly want them to join, whether they're a
|
||||
// guest or not. In practice, guest_access should probably have
|
||||
// been implemented as part of the join_rules enum.
|
||||
let joinRule = "invite";
|
||||
let guestAccess = "can_join";
|
||||
let joinRule: JoinRule = "invite";
|
||||
let guestAccess: GuestAccess = "can_join";
|
||||
|
||||
switch (roomAccess) {
|
||||
case "invite_only":
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019-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.
|
||||
|
@ -16,7 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t, getCurrentLanguage} from "../../../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
|
@ -27,16 +25,21 @@ import * as sdk from "../../../../..";
|
|||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
|
||||
import UpdateCheckButton from "../../UpdateCheckButton";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||
|
||||
interface IProps {
|
||||
closeSettingsFn: () => {};
|
||||
}
|
||||
|
||||
interface IState {
|
||||
appVersion: string;
|
||||
canUpdate: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab")
|
||||
export default class HelpUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
closeSettingsFn: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
export default class HelpUserSettingsTab extends React.Component<IProps, IState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
appVersion: null,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019-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.
|
||||
|
@ -25,10 +25,16 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
|||
import * as sdk from "../../../../../index";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
interface IState {
|
||||
busy: boolean;
|
||||
newPersonalRule: string;
|
||||
newList: string;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.MjolnirUserSettingsTab")
|
||||
export default class MjolnirUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
export default class MjolnirUserSettingsTab extends React.Component<{}, IState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
busy: false,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2019-2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -23,10 +23,24 @@ import Field from "../../../elements/Field";
|
|||
import * as sdk from "../../../../..";
|
||||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||
|
||||
interface IState {
|
||||
autoLaunch: boolean;
|
||||
autoLaunchSupported: boolean;
|
||||
warnBeforeExit: boolean;
|
||||
warnBeforeExitSupported: boolean;
|
||||
alwaysShowMenuBarSupported: boolean;
|
||||
alwaysShowMenuBar: boolean;
|
||||
minimizeToTraySupported: boolean;
|
||||
minimizeToTray: boolean;
|
||||
autocompleteDelay: string,
|
||||
readMarkerInViewThresholdMs: string,
|
||||
readMarkerOutOfViewThresholdMs: string,
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.PreferencesUserSettingsTab")
|
||||
export default class PreferencesUserSettingsTab extends React.Component {
|
||||
export default class PreferencesUserSettingsTab extends React.Component<{}, IState> {
|
||||
static ROOM_LIST_SETTINGS = [
|
||||
'breadcrumbs',
|
||||
];
|
||||
|
@ -68,8 +82,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
// Autocomplete delay (niche text box)
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
autoLaunch: false,
|
||||
|
@ -89,7 +103,7 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
async componentDidMount(): void {
|
||||
async componentDidMount(): Promise<void> {
|
||||
const platform = PlatformPeg.get();
|
||||
|
||||
const autoLaunchSupported = await platform.supportsAutoLaunch();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue