Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PWA] Add Share Functionality #17649

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion app/lib/client/defaultTabBars.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Session } from 'meteor/session';

import { TabBar } from '../../ui-utils';
import { TabBar, popover } from '../../ui-utils';
import { share, isShareAvailable } from '../../utils';
import { Rooms } from '../../models';
import { hasAllPermission } from '../../authorization';
import { roomTypes } from '../../utils/client';
Expand Down Expand Up @@ -86,3 +87,22 @@ TabBar.addButton({
template: 'keyboardShortcuts',
order: 99,
});

// Add Share button in Room
const shareButton = {
groups: ['channel', 'group', 'direct'],
id: 'share',
i18nTitle: 'Share',
icon: 'share',
template: 'share',
order: 500,
};

if (isShareAvailable()) {
shareButton.action = () => {
share();
popover.close();
};
}

TabBar.addButton(shareButton);
56 changes: 56 additions & 0 deletions app/theme/client/imports/components/share.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.share-header-container {
display: flex;
flex-wrap: wrap;
}

.share-icon {
display: inline-block;

box-sizing: border-box;

width: 25%;
min-width: 46px;

padding: 16px 0;

cursor: pointer;

text-align: center;

border: none;

background-color: transparent;

box-shadow: inset 0 0 20px rgba(0, 0, 0, 0);

font-size: 12px;
font-weight: 400;

-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;

&:hover {
box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.125);
}
}

.share-svg-icon {
display: block;

width: 42px;
height: 36px;
margin: auto;

&__header {
width: 24px;
height: 24px;
}
}

.share-icon-title {
display: block;

padding-top: 10px;

font-size: 14px;
}
1 change: 1 addition & 0 deletions app/theme/client/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
@import 'imports/components/emojiPicker.css';
@import 'imports/components/table.css';
@import 'imports/components/tabs.css';
@import 'imports/components/share.css';

/* Modal */
@import 'imports/components/modal/full-modal.css';
Expand Down
Empty file added app/ui-share/README.md
Empty file.
2 changes: 2 additions & 0 deletions app/ui-share/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './share.html';
import './share';
45 changes: 45 additions & 0 deletions app/ui-share/client/share.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template name="share">
<div class="rc-popover__column">
<div class="share-header-container">
<button class="share-icon" data-type="copy">
<svg class="share-svg-icon__header" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#424242" d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"></path></svg>
<span class="share-icon-title">Copy</span>
</button>
<button class="share-icon" data-type="print">
<svg class="share-svg-icon__header" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#424242" d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
<span class="share-icon-title">Print</span>
</button>
<button class="share-icon" data-type="email">
<svg class="share-svg-icon__header" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path fill="#424242" d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H4V8l8 5 8-5v10zm-8-7L4 6h16l-8 5z"/></svg>
<span class="share-icon-title">Email</span>
</button>
<button class="share-icon" data-type="sms">
<svg class="share-svg-icon__header" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#424242" d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
<span class="share-icon-title">SMS</span>
</button>
</div>

<div class="share-header-container">
<button class="share-icon" data-type="facebook">
<svg class="share-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#3b5998" d="M448 56.7v398.5c0 13.7-11.1 24.7-24.7 24.7H309.1V306.5h58.2l8.7-67.6h-67v-43.2c0-19.6 5.4-32.9 33.5-32.9h35.8v-60.5c-6.2-.8-27.4-2.7-52.2-2.7-51.6 0-87 31.5-87 89.4v49.9h-58.4v67.6h58.4V480H24.7C11.1 480 0 468.9 0 455.3V56.7C0 43.1 11.1 32 24.7 32h398.5c13.7 0 24.8 11.1 24.8 24.7z"></path></svg>
<span class="share-icon-title">Facebook</span>
</button>
<button class="share-icon" data-type="whatsapp">
<svg class="share-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#075e54" d="M224 122.8c-72.7 0-131.8 59.1-131.9 131.8 0 24.9 7 49.2 20.2 70.1l3.1 5-13.3 48.6 49.9-13.1 4.8 2.9c20.2 12 43.4 18.4 67.1 18.4h.1c72.6 0 133.3-59.1 133.3-131.8 0-35.2-15.2-68.3-40.1-93.2-25-25-58-38.7-93.2-38.7zm77.5 188.4c-3.3 9.3-19.1 17.7-26.7 18.8-12.6 1.9-22.4.9-47.5-9.9-39.7-17.2-65.7-57.2-67.7-59.8-2-2.6-16.2-21.5-16.2-41s10.2-29.1 13.9-33.1c3.6-4 7.9-5 10.6-5 2.6 0 5.3 0 7.6.1 2.4.1 5.7-.9 8.9 6.8 3.3 7.9 11.2 27.4 12.2 29.4s1.7 4.3.3 6.9c-7.6 15.2-15.7 14.6-11.6 21.6 15.3 26.3 30.6 35.4 53.9 47.1 4 2 6.3 1.7 8.6-1 2.3-2.6 9.9-11.6 12.5-15.5 2.6-4 5.3-3.3 8.9-2 3.6 1.3 23.1 10.9 27.1 12.9s6.6 3 7.6 4.6c.9 1.9.9 9.9-2.4 19.1zM400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM223.9 413.2c-26.6 0-52.7-6.7-75.8-19.3L64 416l22.5-82.2c-13.9-24-21.2-51.3-21.2-79.3C65.4 167.1 136.5 96 223.9 96c42.4 0 82.2 16.5 112.2 46.5 29.9 30 47.9 69.8 47.9 112.2 0 87.4-72.7 158.5-160.1 158.5z"></path></svg>
<span class="share-icon-title">WhatsApp</span>
</button>
<button class="share-icon" data-type="twitter">
<svg class="share-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#1da1f2" d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg>
<span class="share-icon-title">Twitter</span>
</button>
<button class="share-icon" data-type="linkedin">
<svg class="share-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#0077b5" d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"></path></svg>
<span class="share-icon-title">LinkedIn</span>
</button>
<button class="share-icon" data-type="telegram">
<svg class="share-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="#0088cc" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm121.8 169.9l-40.7 191.8c-3 13.6-11.1 16.9-22.4 10.5l-62-45.7-29.9 28.8c-3.3 3.3-6.1 6.1-12.5 6.1l4.4-63.1 114.9-103.8c5-4.4-1.1-6.9-7.7-2.5l-142 89.4-61.2-19.1c-13.3-4.2-13.6-13.3 2.8-19.7l239.1-92.2c11.1-4 20.8 2.7 17.2 19.5z"></path></svg>
<span class="share-icon-title">Telegram</span>
</button>
</div>
</div>
</template>
71 changes: 71 additions & 0 deletions app/ui-share/client/share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Template } from 'meteor/templating';

import { getShareData } from '../../utils';

function getShareString() {
const data = getShareData();
return `${ data.title } \n${ data.url } \n${ data.text }`;
}

function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed'; // avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();

try {
document.execCommand('copy');
} catch (err) {
console.error('Unable to copy', err);
}

document.body.removeChild(textArea);
}

Template.share.helpers({

});

Template.share.events({
'click [data-type="copy"]'() {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(getShareString());
return;
}
navigator.clipboard.writeText(getShareString());
},
'click [data-type="print"]'() {
self.print();
},
'click [data-type="email"]'() {
const { title } = getShareData();
window.open(`mailto:?subject=${ title }&body=${ getShareString() }`);
},
'click [data-type="sms"]'() {
location.href = `sms:?&body=${ getShareString() }`;
},


'click [data-type="facebook"]'() {
const { url } = getShareData();
window.open(`https://www.facebook.com/sharer/sharer.php?u=${ encodeURIComponent(url) }`);
},
'click [data-type="whatsapp"]'() {
window.open(`https://api.whatsapp.com/send?text=${ encodeURIComponent(getShareString()) }`);
},
'click [data-type="twitter"]'() {
const { url } = getShareData();
window.open(`http://twitter.com/share?text=${ getShareString() }&url=${ url }`);
},
'click [data-type="linkedin"]'() {
const { title, url } = getShareData();
window.open(`https://www.linkedin.com/shareArticle?mini=true&url=${ url }&title=${ title }&summary=${ getShareString() }&source=LinkedIn`);
},
'click [data-type="telegram"]'() {
const { url } = getShareData();
window.open(`https://telegram.me/share/msg?url=${ url }&text=${ getShareString() }`);
},

});
1 change: 1 addition & 0 deletions app/ui-share/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './client/index';
8 changes: 8 additions & 0 deletions app/ui-sidenav/client/sidebarHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ const toolbarButtons = (/* user */) => [{
};
}

const shareOption = {
name: t('Share'),
icon: 'share',
type: 'share-action',
};

const config = {
popoverClass: 'sidebar-header',
columns: [
Expand Down Expand Up @@ -206,6 +212,8 @@ const toolbarButtons = (/* user */) => [{
offsetVertical: e.currentTarget.clientHeight + 10,
};

config.columns[0].groups[0].items = config.columns[0].groups[0].items.concat([shareOption]);

popover.open(config);
},
}];
Expand Down
18 changes: 18 additions & 0 deletions app/ui-utils/client/lib/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import _ from 'underscore';

import { share, isShareAvailable } from '../../../utils';
import { hide, leave } from './ChannelActions';
import { messageBox } from './messageBox';
import { MessageAction } from './MessageAction';
Expand Down Expand Up @@ -179,6 +180,23 @@ Template.popover.events({
return false;
}
},
'click [data-type="share-action"]'(e) {
if (isShareAvailable()) {
share();
} else {
popover.close();
const options = [];
const config = {
template: 'share',
currentTarget: e.target,
data: {
options,
},
offsetVertical: e.target.clientHeight + 10,
};
popover.open(config);
}
},
'click [data-type="sidebar-item"]'(e, instance) {
popover.close();
const { rid, name, template } = instance.data.data;
Expand Down
1 change: 1 addition & 0 deletions app/utils/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ export { APIClient, mountArrayQueryParameters } from './lib/RestApiClient';
export { canDeleteMessage } from './lib/canDeleteMessage';
export { mime } from '../lib/mimeTypes';
export { secondsToHHMMSS } from '../lib/timeConverter';
export { share, isShareAvailable, getShareData } from './lib/share';
59 changes: 59 additions & 0 deletions app/utils/client/lib/share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Meteor } from 'meteor/meteor';

import { settings } from '../../../settings';


export const isShareAvailable = () => {
if (navigator.share) { return true; }
return false;
};

export const getShareData = () => {
const data = {};

const siteName = settings.get('Site_Name') || '';
const siteURL = settings.get('Site_Url') || '';

data.url = document.location.href || siteURL;
const path = new URL(data.url).pathname;
const roomName = path.substring(path.lastIndexOf('/') + 1);

const templateText = `${ siteName } is open source team communication app.`;

data.title = `${ siteName }`;
data.text = `${ templateText } Open this link to connect.`;

if (path.startsWith('/channel')) {
data.title = `Join #${ roomName } on ${ siteName }`;
data.text = `You are invited to channel #${ roomName } on ${ siteName }. ${ data.text }`;
} else if (path.startsWith('/group')) {
data.title = `Join #${ roomName } on ${ siteName }`;
data.text = `You are invited to private group 🔒${ roomName } on ${ siteName }. ${ data.text }`;
} else if (path.startsWith('/direct')) {
data.title = `Chat with @${ roomName } on ${ siteName }`;
} else {
const user = Meteor.user();

data.title = `${ siteName }`;
data.text = `${ templateText } Open this link and connect with me.`;
data.url = new URL(document.location.href).origin;

if (data.url && user) {
data.url = `${ data.url }/direct/${ user.username }`;
}
}

return data;
};

export const share = () => {
const data = getShareData();

if (navigator.share) {
navigator.share(data)
.then(() => console.log('Successfully shared'))
.catch((error) => console.log('Error while sharing', error));
} else {
console.log('Share feature not available');
}
};
1 change: 1 addition & 0 deletions client/importPackages.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import '../app/ui-login';
import '../app/ui-master/client';
import '../app/ui-message';
import '../app/ui-sidenav';
import '../app/ui-share';
import '../app/ui-vrecord/client';
import '../app/videobridge/client';
import '../app/webdav/client';
Expand Down