import { Component, linkEvent } from 'inferno';
-import { Link } from 'inferno-router';
+import { Prompt } from 'inferno-router';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
UserDetailsResponse,
GetUserDetailsForm,
SortType,
-} from '../interfaces';
+ WebSocketJsonResponse,
+} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import {
- msgOp,
capitalizeFirstLetter,
- markdownHelpUrl,
- mdToHtml,
- showAvatars,
- pictshareAvatarThumbnail,
+ wsJsonToRes,
toast,
+ setupTippy,
} from '../utils';
-import autosize from 'autosize';
+import { UserListing } from './user-listing';
+import { MarkdownTextArea } from './markdown-textarea';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
this.state = this.emptyState;
+ this.handleContentChange = this.handleContentChange.bind(this);
+
if (this.props.privateMessage) {
this.state.privateMessageForm = {
content: this.props.privateMessage.content,
this.state.privateMessageForm.recipient_id = this.props.params.recipient_id;
let form: GetUserDetailsForm = {
user_id: this.state.privateMessageForm.recipient_id,
- sort: SortType[SortType.New],
+ sort: SortType.New,
saved_only: false,
};
WebSocketService.Instance.getUserDetails(form);
}
componentDidMount() {
- autosize(document.querySelectorAll('textarea'));
+ setupTippy();
+ }
+
+ componentDidUpdate() {
+ if (!this.state.loading && this.state.privateMessageForm.content) {
+ window.onbeforeunload = () => true;
+ } else {
+ window.onbeforeunload = undefined;
+ }
}
componentWillUnmount() {
this.subscription.unsubscribe();
+ window.onbeforeunload = null;
}
render() {
return (
<div>
+ <Prompt
+ when={!this.state.loading && this.state.privateMessageForm.content}
+ message={i18n.t('block_leaving')}
+ />
<form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
{!this.props.privateMessage && (
<div class="form-group row">
{this.state.recipient && (
<div class="col-sm-10 form-control-plaintext">
- <Link
- className="text-info"
- to={`/u/${this.state.recipient.name}`}
- >
- {this.state.recipient.avatar && showAvatars() && (
- <img
- height="32"
- width="32"
- src={pictshareAvatarThumbnail(
- this.state.recipient.avatar
- )}
- class="rounded-circle mr-1"
- />
- )}
- <span>{this.state.recipient.name}</span>
- </Link>
+ <UserListing
+ user={{
+ name: this.state.recipient.name,
+ preferred_username: this.state.recipient
+ .preferred_username,
+ avatar: this.state.recipient.avatar,
+ id: this.state.recipient.id,
+ local: this.state.recipient.local,
+ actor_id: this.state.recipient.actor_id,
+ }}
+ />
</div>
)}
</div>
)}
<div class="form-group row">
- <label class="col-sm-2 col-form-label">{i18n.t('message')}</label>
+ <label class="col-sm-2 col-form-label">
+ {i18n.t('message')}
+ <span
+ onClick={linkEvent(this, this.handleShowDisclaimer)}
+ class="ml-2 pointer text-danger"
+ data-tippy-content={i18n.t('disclaimer')}
+ >
+ <svg class={`icon icon-inline`}>
+ <use xlinkHref="#icon-alert-triangle"></use>
+ </svg>
+ </span>
+ </label>
<div class="col-sm-10">
- <textarea
- value={this.state.privateMessageForm.content}
- onInput={linkEvent(this, this.handleContentChange)}
- className={`form-control ${this.state.previewMode && 'd-none'}`}
- rows={4}
- maxLength={10000}
+ <MarkdownTextArea
+ initialContent={this.state.privateMessageForm.content}
+ onContentChange={this.handleContentChange}
/>
- {this.state.previewMode && (
- <div
- className="md-div"
- dangerouslySetInnerHTML={mdToHtml(
- this.state.privateMessageForm.content
- )}
- />
- )}
-
- {this.state.privateMessageForm.content && (
- <button
- className={`mt-1 mr-2 btn btn-sm btn-secondary ${this.state
- .previewMode && 'active'}`}
- onClick={linkEvent(this, this.handlePreviewToggle)}
- >
- {i18n.t('preview')}
- </button>
- )}
- <ul class="float-right list-inline mb-1 text-muted small font-weight-bold">
- <li class="list-inline-item">
- <span
- onClick={linkEvent(this, this.handleShowDisclaimer)}
- class="pointer"
- >
- {i18n.t('disclaimer')}
- </span>
- </li>
- <li class="list-inline-item">
- <a href={markdownHelpUrl} target="_blank" class="text-muted">
- {i18n.t('formatting_help')}
- </a>
- </li>
- </ul>
</div>
</div>
{this.state.showDisclaimer && (
<div class="form-group row">
- <div class="col-sm-10">
+ <div class="offset-sm-2 col-sm-10">
<div class="alert alert-danger" role="alert">
<T i18nKey="private_message_disclaimer">
#
<a
class="alert-link"
target="_blank"
- href="https://about.riot.im/"
+ rel="noopener"
+ href="https://element.io/get-started"
>
#
</a>
</div>
)}
<div class="form-group row">
- <div class="col-sm-10">
- <button type="submit" class="btn btn-secondary mr-2">
+ <div class="offset-sm-2 col-sm-10">
+ <button
+ type="submit"
+ class="btn btn-secondary mr-2"
+ disabled={this.state.loading}
+ >
{this.state.loading ? (
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
{i18n.t('cancel')}
</button>
)}
+ <ul class="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
+ <li class="list-inline-item"></li>
+ </ul>
</div>
</div>
</form>
i.setState(i.state);
}
- handleContentChange(i: PrivateMessageForm, event: any) {
- i.state.privateMessageForm.content = event.target.value;
- i.setState(i.state);
+ handleContentChange(val: string) {
+ this.state.privateMessageForm.content = val;
+ this.setState(this.state);
}
handleCancel(i: PrivateMessageForm) {
i.setState(i.state);
}
- parseMessage(msg: any) {
- let op: UserOperation = msgOp(msg);
+ parseMessage(msg: WebSocketJsonResponse) {
+ let res = wsJsonToRes(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.state.loading = false;
this.setState(this.state);
return;
- } else if (op == UserOperation.EditPrivateMessage) {
+ } else if (
+ res.op == UserOperation.EditPrivateMessage ||
+ res.op == UserOperation.DeletePrivateMessage ||
+ res.op == UserOperation.MarkPrivateMessageAsRead
+ ) {
+ let data = res.data as PrivateMessageResponse;
this.state.loading = false;
- let res: PrivateMessageResponse = msg;
- this.props.onEdit(res.message);
- } else if (op == UserOperation.GetUserDetails) {
- let res: UserDetailsResponse = msg;
- this.state.recipient = res.user;
- this.state.privateMessageForm.recipient_id = res.user.id;
+ this.props.onEdit(data.message);
+ } else if (res.op == UserOperation.GetUserDetails) {
+ let data = res.data as UserDetailsResponse;
+ this.state.recipient = data.user;
+ this.state.privateMessageForm.recipient_id = data.user.id;
this.setState(this.state);
- } else if (op == UserOperation.CreatePrivateMessage) {
+ } else if (res.op == UserOperation.CreatePrivateMessage) {
+ let data = res.data as PrivateMessageResponse;
this.state.loading = false;
- let res: PrivateMessageResponse = msg;
- this.props.onCreate(res.message);
+ this.props.onCreate(data.message);
this.setState(this.state);
}
}