-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from tchapgouv/feat/46_create_room
Create Room
- Loading branch information
Showing
15 changed files
with
685 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"src/@types/tchap.ts": "src/@types/tchap.ts", | ||
"src/components/views/dialogs/CreateRoomDialog.tsx": "src/components/views/dialogs/TchapCreateRoomDialog.tsx", | ||
"src/components/views/elements/TchapRoomTypeSelector.tsx": "src/components/views/elements/TchapRoomTypeSelector.tsx" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
.tc_TchapRoomTypeSelector { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 24px; | ||
|
||
>.tc_TchapRoomTypeSelector_RadioButton { | ||
flex-grow: 0; | ||
flex-shrink: 1; | ||
display: flex; | ||
flex-direction: column; | ||
padding: 10px; | ||
|
||
border-width: 3px; | ||
border-style: solid; | ||
border-color: transparent; | ||
border-radius: 10px; | ||
|
||
.tc_TchapRoomTypeSelector_RadioButton_title { | ||
font-weight: bold; | ||
} | ||
} | ||
|
||
.tc_TchapRoomTypeSelector_private { | ||
.tc_TchapRoomTypeSelector_RadioButton_title { | ||
color: var(--private-color); | ||
&::before { | ||
width: 12px; | ||
height: 16px; | ||
content: ""; | ||
display: inline-block; | ||
vertical-align: sub; | ||
background-image: url("../../../img/tchap/padlock-private.svg"); | ||
background-repeat: no-repeat; | ||
background-size: 100%; | ||
margin-right: 4px; | ||
} | ||
} | ||
|
||
&.tc_TchapRoomTypeSelector_RadioButton_selected { | ||
border-color: var(--private-color); | ||
} | ||
} | ||
|
||
.tc_TchapRoomTypeSelector_external { | ||
.tc_TchapRoomTypeSelector_RadioButton_title { | ||
color: var(--external-color); | ||
&::before { | ||
width: 12px; | ||
height: 16px; | ||
content: ""; | ||
display: inline-block; | ||
vertical-align: sub; | ||
background-image: url("../../../img/tchap/padlock-external.svg"); | ||
background-repeat: no-repeat; | ||
background-size: 100%; | ||
margin-right: 4px; | ||
} | ||
} | ||
|
||
&.tc_TchapRoomTypeSelector_RadioButton_selected { | ||
border-color: var(--external-color); | ||
} | ||
|
||
} | ||
|
||
.tc_TchapRoomTypeSelector_forum { | ||
.tc_TchapRoomTypeSelector_RadioButton_title { | ||
color: var(--forum-color); | ||
&::before { | ||
width: 12px; | ||
height: 16px; | ||
content: ""; | ||
display: inline-block; | ||
vertical-align: sub; | ||
background-image: url("../../../img/tchap/padlock-forum.svg"); | ||
background-repeat: no-repeat; | ||
background-size: 100%; | ||
margin-right: 4px; | ||
} | ||
} | ||
|
||
&.tc_TchapRoomTypeSelector_RadioButton_selected { | ||
border-color: var(--forum-color); | ||
} | ||
|
||
.mx_SettingsFlag { | ||
flex-direction: row; | ||
display: flex; | ||
align-items: center; | ||
margin-top: 10px; | ||
.mx_SettingsFlag_label { | ||
padding-top: 0px; | ||
} | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export enum TchapRoomType { | ||
Direct = "direct", | ||
Private = "private", | ||
External = "external", | ||
Forum = "forum", | ||
} | ||
|
||
export enum TchapRoomAccessRule { | ||
Unrestricted = "unrestricted", // accessible to externals | ||
Restricted = "restricted" // not accessible to externals | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
/* | ||
Copyright 2022 DINUM | ||
Replaces CreateRoomDialog.tsx | ||
Tchap has 3 types of rooms only : private, private open to externs, and public (forum). | ||
Tchap does not support spaces for now, so there are no settings dependent on spaces (for example "Visible to space | ||
members"). Element uses JoinRule.Restricted for this. | ||
When/if Tchap supports spaces, we can decide on more specific settings if needed. | ||
Note on imports : because this file will be copied to a different directory by the customisations | ||
mechanism, imports must use absolute paths. | ||
Except when importing from other customisation files. Then imports must use relative paths. | ||
*/ | ||
import React, { ChangeEvent, createRef, KeyboardEvent } from "react"; | ||
import { Room } from "matrix-js-sdk/src/models/room"; | ||
import withValidation, { IFieldState } from 'matrix-react-sdk/src/components/views/elements/Validation'; | ||
import { _t } from 'matrix-react-sdk/src/languageHandler'; | ||
import { IOpts } from "matrix-react-sdk/src/createRoom"; | ||
import { getKeyBindingsManager } from "matrix-react-sdk/src/KeyBindingsManager"; | ||
import { KeyBindingAction } from "matrix-react-sdk/src/accessibility/KeyboardShortcuts"; | ||
import * as sdk from 'matrix-react-sdk/src/index'; | ||
import Field from "matrix-react-sdk/src/components/views/elements/Field"; | ||
|
||
import TchapUtils from '../../../util/TchapUtils'; | ||
import TchapRoomTypeSelector from "./../elements/TchapRoomTypeSelector"; | ||
import { TchapRoomType } from "../../../@types/tchap"; | ||
import roomCreateOptions from "../../../lib/createTchapRoom"; | ||
|
||
// We leave the same props as Element's version, to avoid unknown props warnings. | ||
interface IProps { | ||
defaultPublic?: boolean; // unused for Tchap version | ||
defaultName?: string; | ||
parentSpace?: Room; // unused for Tchap version | ||
defaultEncrypted?: boolean; // unused for Tchap version | ||
onFinished(proceed: boolean, opts?: IOpts): void; | ||
} | ||
|
||
interface IState { | ||
name: string; | ||
nameIsValid: boolean; | ||
tchapRoomType: TchapRoomType; | ||
isFederated: boolean; | ||
showFederateSwitch: boolean; | ||
} | ||
|
||
export default class TchapCreateRoomDialog extends React.Component<IProps, IState> { | ||
private nameField = createRef<Field>(); | ||
|
||
constructor(props) { | ||
super(props); | ||
|
||
const federationOptions = TchapUtils.getRoomFederationOptions(); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
this.state = { | ||
name: this.props.defaultName || "", | ||
nameIsValid: false, | ||
tchapRoomType: TchapRoomType.Private, | ||
isFederated: federationOptions.roomFederationDefault, | ||
showFederateSwitch: federationOptions.showRoomFederationOption, | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
// move focus to first field when showing dialog | ||
this.nameField.current.focus(); | ||
} | ||
|
||
componentWillUnmount() { | ||
} | ||
|
||
private onCancel = () => { | ||
this.props.onFinished(false); | ||
}; | ||
|
||
private onFederatedChange = (isFederated: boolean) => { | ||
this.setState({ isFederated: isFederated }); | ||
}; | ||
|
||
private onTchapRoomTypeChange = (tchapRoomType: TchapRoomType) => { | ||
this.setState({ tchapRoomType: tchapRoomType }); | ||
}; | ||
|
||
private onNameChange = (ev: ChangeEvent<HTMLInputElement>) => { | ||
this.setState({ name: ev.target.value }); | ||
}; | ||
|
||
private onNameValidate = async (fieldState: IFieldState) => { | ||
const result = await TchapCreateRoomDialog.validateRoomName(fieldState); | ||
this.setState({ nameIsValid: result.valid }); | ||
return result; | ||
}; | ||
|
||
private static validateRoomName = withValidation({ | ||
rules: [ | ||
{ | ||
key: "required", | ||
test: async ({ value }) => !!value, | ||
invalid: () => _t("Please enter a name for the room"), | ||
}, | ||
], | ||
}); | ||
|
||
private onKeyDown = (event: KeyboardEvent) => { | ||
const action = getKeyBindingsManager().getAccessibilityAction(event); | ||
switch (action) { | ||
case KeyBindingAction.Enter: | ||
this.onOk(); | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
break; | ||
} | ||
}; | ||
|
||
private onOk = async () => { | ||
const activeElement = document.activeElement as HTMLElement; | ||
if (activeElement) { | ||
activeElement.blur(); | ||
} | ||
await this.nameField.current.validate({ allowEmpty: false }); | ||
// Validation and state updates are async, so we need to wait for them to complete | ||
// first. Queue a `setState` callback and wait for it to resolve. | ||
await new Promise<void>(resolve => this.setState({}, resolve)); | ||
if (this.state.nameIsValid) { | ||
this.props.onFinished(true, roomCreateOptions( | ||
this.state.name, | ||
this.state.tchapRoomType, | ||
this.state.isFederated)); | ||
} else { | ||
let field; | ||
if (!this.state.nameIsValid) { | ||
field = this.nameField.current; | ||
} | ||
if (field) { | ||
field.focus(); | ||
field.validate({ allowEmpty: false, focused: true }); | ||
} | ||
} | ||
}; | ||
|
||
render() { | ||
const Field = sdk.getComponent("elements.Field"); | ||
const DialogButtons = sdk.getComponent("elements.DialogButtons"); | ||
const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); | ||
|
||
const shortDomain: string = TchapUtils.getShortDomain(); | ||
|
||
const title = _t("Create a room"); | ||
|
||
return ( | ||
<BaseDialog | ||
className="tc_TchapCreateRoomDialog" | ||
onFinished={this.props.onFinished} | ||
title={title} | ||
screenName="CreateRoom" | ||
> | ||
<form onSubmit={this.onOk} onKeyDown={this.onKeyDown}> | ||
<div className="mx_Dialog_content"> | ||
<Field | ||
ref={this.nameField} | ||
label={_t('Name')} | ||
onChange={this.onNameChange} | ||
onValidate={this.onNameValidate} | ||
value={this.state.name} | ||
/> | ||
|
||
<TchapRoomTypeSelector | ||
onChange={this.onTchapRoomTypeChange} | ||
value={this.state.tchapRoomType} | ||
label={_t("Type of room")} | ||
showFederateSwitch={this.state.showFederateSwitch} | ||
shortDomain={shortDomain} | ||
isFederated={this.state.isFederated} | ||
onFederatedChange={this.onFederatedChange} | ||
/> | ||
|
||
</div> | ||
</form> | ||
<DialogButtons primaryButton={_t('Create Room')} | ||
onPrimaryButtonClick={this.onOk} | ||
onCancel={this.onCancel} /> | ||
</BaseDialog> | ||
); | ||
} | ||
} |
Oops, something went wrong.
Move getRoomFederationOptions to a TchapConfig class? I would reserve TchapUtils for code that contains no business logic.