add a ShareDialog for sharing users,groups and rooms
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/21833/head
|
@ -80,6 +80,7 @@
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"pako": "^1.0.5",
|
"pako": "^1.0.5",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
"qrcode-react": "^0.1.16",
|
||||||
"querystring": "^0.2.0",
|
"querystring": "^0.2.0",
|
||||||
"react": "^15.6.0",
|
"react": "^15.6.0",
|
||||||
"react-addons-css-transition-group": "15.3.2",
|
"react-addons-css-transition-group": "15.3.2",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 481.6 481.6" style="enable-background:new 0 0 481.6 481.6;" xml:space="preserve" width="16px" height="16px">
|
||||||
|
<g>
|
||||||
|
<path stroke="#76CFA6" stroke-width="5" d="M381.6,309.4c-27.7,0-52.4,13.2-68.2,33.6l-132.3-73.9c3.1-8.9,4.8-18.5,4.8-28.4c0-10-1.7-19.5-4.9-28.5l132.2-73.8 c15.7,20.5,40.5,33.8,68.3,33.8c47.4,0,86.1-38.6,86.1-86.1S429,0,381.5,0s-86.1,38.6-86.1,86.1c0,10,1.7,19.6,4.9,28.5 l-132.1,73.8c-15.7-20.6-40.5-33.8-68.3-33.8c-47.4,0-86.1,38.6-86.1,86.1s38.7,86.1,86.2,86.1c27.8,0,52.6-13.3,68.4-33.9 l132.2,73.9c-3.2,9-5,18.7-5,28.7c0,47.4,38.6,86.1,86.1,86.1s86.1-38.6,86.1-86.1S429.1,309.4,381.6,309.4z M381.6,27.1 c32.6,0,59.1,26.5,59.1,59.1s-26.5,59.1-59.1,59.1s-59.1-26.5-59.1-59.1S349.1,27.1,381.6,27.1z M100,299.8 c-32.6,0-59.1-26.5-59.1-59.1s26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1S132.5,299.8,100,299.8z M381.6,454.5 c-32.6,0-59.1-26.5-59.1-59.1c0-32.6,26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1C440.7,428,414.2,454.5,381.6,454.5z" fill="#76cfa6"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 520 520" style="enable-background:new 0 0 520 520;" xml:space="preserve">
|
||||||
|
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||||
|
<path d="M13.7,11.9v496.2h35.7V520H0V0h49.4v11.9H13.7z"/>
|
||||||
|
<path d="M166.3,169.2v25.1h0.7c6.7-9.6,14.8-17,24.2-22.2c9.4-5.3,20.3-7.9,32.5-7.9c11.7,0,22.4,2.3,32.1,6.8
|
||||||
|
c9.7,4.5,17,12.6,22.1,24c5.5-8.1,13-15.3,22.4-21.5c9.4-6.2,20.6-9.3,33.5-9.3c9.8,0,18.9,1.2,27.3,3.6c8.4,2.4,15.5,6.2,21.5,11.5
|
||||||
|
c6,5.3,10.6,12.1,14,20.6c3.3,8.5,5,18.7,5,30.7v124.1h-50.9V249.6c0-6.2-0.2-12.1-0.7-17.6c-0.5-5.5-1.8-10.3-3.9-14.3
|
||||||
|
c-2.2-4.1-5.3-7.3-9.5-9.7c-4.2-2.4-9.9-3.6-17-3.6c-7.2,0-13,1.4-17.4,4.1c-4.4,2.8-7.9,6.3-10.4,10.8c-2.5,4.4-4.2,9.4-5,15.1
|
||||||
|
c-0.8,5.6-1.3,11.3-1.3,17v103.3h-50.9v-104c0-5.5-0.1-10.9-0.4-16.3c-0.2-5.4-1.3-10.3-3.1-14.9c-1.8-4.5-4.8-8.2-9-10.9
|
||||||
|
c-4.2-2.7-10.3-4.1-18.5-4.1c-2.4,0-5.6,0.5-9.5,1.6c-3.9,1.1-7.8,3.1-11.5,6.1c-3.7,3-6.9,7.3-9.5,12.9c-2.6,5.6-3.9,13-3.9,22.1
|
||||||
|
v107.6h-50.9V169.2H166.3z"/>
|
||||||
|
<path d="M506.3,508.1V11.9h-35.7V0H520v520h-49.4v-11.9H506.3z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Vector Creations Ltd
|
||||||
|
|
||||||
|
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 from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {Room, User, Group, RoomMember} from 'matrix-js-sdk';
|
||||||
|
import sdk from '../../../index';
|
||||||
|
import { _t } from '../../../languageHandler';
|
||||||
|
import QRCode from 'qrcode-react';
|
||||||
|
import {makeEventPermalink, makeGroupPermalink, makeRoomPermalink, makeUserPermalink} from "../../../matrix-to";
|
||||||
|
import * as ContextualMenu from "../../structures/ContextualMenu";
|
||||||
|
|
||||||
|
const socials = [
|
||||||
|
{
|
||||||
|
name: 'Facebook',
|
||||||
|
img: 'img/social/facebook.png',
|
||||||
|
url: (url) => `https://www.facebook.com/sharer/sharer.php?u=${url}`,
|
||||||
|
}, {
|
||||||
|
name: 'Twitter',
|
||||||
|
img: 'img/social/twitter-2.png',
|
||||||
|
url: (url) => `https://twitter.com/home?status=${url}`,
|
||||||
|
}, /* // icon missing
|
||||||
|
name: 'Google Plus',
|
||||||
|
img: 'img/social/',
|
||||||
|
url: (url) => `https://plus.google.com/share?url=${url}`,
|
||||||
|
},*/ {
|
||||||
|
name: 'Linked In',
|
||||||
|
img: 'img/social/linkedin.png',
|
||||||
|
url: (url) => `https://www.linkedin.com/shareArticle?mini=true&url=${url}`,
|
||||||
|
}, {
|
||||||
|
name: 'Reddit',
|
||||||
|
img: 'img/social/reddit.png',
|
||||||
|
url: (url) => `http://www.reddit.com/submit?url=${url}`,
|
||||||
|
}, {
|
||||||
|
name: 'email',
|
||||||
|
img: 'img/social/email-1.png',
|
||||||
|
url: (url) => `mailto:?body=${url}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default class ShareDialog extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
onFinished: PropTypes.func.isRequired,
|
||||||
|
target: PropTypes.oneOfType([
|
||||||
|
PropTypes.instanceOf(Room),
|
||||||
|
PropTypes.instanceOf(User),
|
||||||
|
PropTypes.instanceOf(Group),
|
||||||
|
PropTypes.instanceOf(RoomMember),
|
||||||
|
// PropTypes.instanceOf(MatrixEvent),
|
||||||
|
]).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.onCopyClick = this.onCopyClick.bind(this);
|
||||||
|
this.onCheckboxClick = this.onCheckboxClick.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
ticked: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static _selectText(target) {
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(target);
|
||||||
|
|
||||||
|
const selection = window.getSelection();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
static onLinkClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const {target} = e;
|
||||||
|
ShareDialog._selectText(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCopyClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
ShareDialog._selectText(this.refs.link);
|
||||||
|
|
||||||
|
let successful;
|
||||||
|
try {
|
||||||
|
successful = document.execCommand('copy');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy: ', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||||
|
const buttonRect = e.target.getBoundingClientRect();
|
||||||
|
|
||||||
|
// The window X and Y offsets are to adjust position when zoomed in to page
|
||||||
|
const x = buttonRect.right + window.pageXOffset;
|
||||||
|
const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19;
|
||||||
|
const {close} = ContextualMenu.createMenu(GenericTextContextMenu, {
|
||||||
|
chevronOffset: 10,
|
||||||
|
left: x,
|
||||||
|
top: y,
|
||||||
|
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
||||||
|
}, false);
|
||||||
|
e.target.onmouseleave = close;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCheckboxClick() {
|
||||||
|
this.setState({
|
||||||
|
ticked: !this.state.ticked,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let title;
|
||||||
|
let matrixToUrl;
|
||||||
|
|
||||||
|
let checkbox;
|
||||||
|
|
||||||
|
if (this.props.target instanceof Room) {
|
||||||
|
title = _t('Share Room');
|
||||||
|
|
||||||
|
const events = this.props.target.getLiveTimeline().getEvents();
|
||||||
|
if (events.length > 0) {
|
||||||
|
checkbox = <div>
|
||||||
|
<input type="checkbox"
|
||||||
|
value={this.state.ticked}
|
||||||
|
id="mx_ShareDialog_checkbox"
|
||||||
|
onClick={this.onCheckboxClick} />
|
||||||
|
<label htmlFor="mx_ShareDialog_checkbox">
|
||||||
|
{ _t('Link to most recent message') }
|
||||||
|
</label>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.ticked) {
|
||||||
|
matrixToUrl = makeEventPermalink(this.props.target.roomId, events[events.length - 1].getId());
|
||||||
|
} else {
|
||||||
|
matrixToUrl = makeRoomPermalink(this.props.target.roomId);
|
||||||
|
}
|
||||||
|
} else if (this.props.target instanceof User || this.props.target instanceof RoomMember) {
|
||||||
|
title = _t('Share User');
|
||||||
|
matrixToUrl = makeUserPermalink(this.props.target.userId);
|
||||||
|
} else if (this.props.target instanceof Group) {
|
||||||
|
title = _t('Share Community');
|
||||||
|
matrixToUrl = makeGroupPermalink(this.props.target.groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const encodedUrl = encodeURIComponent(matrixToUrl);
|
||||||
|
|
||||||
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
|
return <BaseDialog title={title}
|
||||||
|
className='mx_ShareDialog'
|
||||||
|
contentId='mx_Dialog_content'
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
>
|
||||||
|
<div className="mx_ShareDialog_content">
|
||||||
|
<div className="mx_ShareDialog_matrixto">
|
||||||
|
<a ref="link"
|
||||||
|
href={matrixToUrl}
|
||||||
|
onClick={ShareDialog.onLinkClick}
|
||||||
|
className="mx_ShareDialog_matrixto_link"
|
||||||
|
>
|
||||||
|
{ matrixToUrl }
|
||||||
|
</a>
|
||||||
|
<a href={matrixToUrl} className="mx_ShareDialog_matrixto_copy" onClick={this.onCopyClick}>
|
||||||
|
{ _t('COPY') }
|
||||||
|
<div> </div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{ checkbox }
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div className="mx_ShareDialog_split">
|
||||||
|
<div className="mx_ShareDialog_left">
|
||||||
|
<h3>QR Code</h3>
|
||||||
|
<div className="mx_ShareDialog_qrcode_container">
|
||||||
|
<QRCode value={matrixToUrl} size={256} logo="img/matrix-m.svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mx_ShareDialog_right">
|
||||||
|
<h3>Social</h3>
|
||||||
|
<div className="mx_ShareDialog_social_container">
|
||||||
|
{
|
||||||
|
socials.map((social) => <a target="_blank"
|
||||||
|
key={social.name}
|
||||||
|
name={social.name}
|
||||||
|
href={social.url(encodedUrl)}
|
||||||
|
className="mx_ShareDialog_social_icon"
|
||||||
|
>
|
||||||
|
<img src={social.img} height={64} width={64} />
|
||||||
|
</a>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BaseDialog>;
|
||||||
|
}
|
||||||
|
}
|