diff --git a/app/lib/client/defaultTabBars.js b/app/lib/client/defaultTabBars.js index b8c2db62ea00..b75d34376135 100644 --- a/app/lib/client/defaultTabBars.js +++ b/app/lib/client/defaultTabBars.js @@ -1,7 +1,7 @@ import { Session } from 'meteor/session'; -import { TabBar } from '../../ui-utils'; -import { isMobile, shareRoom } from '../../utils'; +import { TabBar, popover } from '../../ui-utils'; +import { share, isShareAvailable } from '../../utils'; import { Rooms } from '../../models'; import { hasAllPermission } from '../../authorization'; @@ -72,13 +72,21 @@ TabBar.addButton({ order: 4, }); -TabBar.addButton({ +// Add Share button in Room +const shareButton = { groups: ['channel', 'group', 'direct'], id: 'share', i18nTitle: 'Share', icon: 'share', template: 'share', order: 500, - condition: () => isMobile(), - action: () => { shareRoom(); }, -}); +}; + +if (isShareAvailable()) { + shareButton.action = () => { + share(); + popover.close(); + }; +} + +TabBar.addButton(shareButton); diff --git a/app/theme/client/imports/components/share.css b/app/theme/client/imports/components/share.css new file mode 100644 index 000000000000..528846c331e1 --- /dev/null +++ b/app/theme/client/imports/components/share.css @@ -0,0 +1,43 @@ +.share-header-container { + display: flex; + flex-wrap: wrap; +} + +.share-icon { + border: none; + display: inline-block; + width: 25%; + min-width: 46px; + box-sizing: border-box; + font-weight: 400; + font-size: 12px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-align: center; + cursor: pointer; + background-color: transparent; + padding: 16px 0; + box-shadow: inset 0 0 20px rgba(0,0,0, 0); + + &:hover { + box-shadow: inset 0 0 20px rgba(0,0,0, .125); + } +} + +.share-svg-icon { + display: block; + margin: auto; + width: 42px; + height: 36px; + + &__header { + width: 24px; + height: 24px; + } +} + +.share-icon-title { + font-size: 14px; + padding-top: 10px; + display: block; +} diff --git a/app/theme/client/main.css b/app/theme/client/main.css index d768ec57c47d..a1ee37595578 100644 --- a/app/theme/client/main.css +++ b/app/theme/client/main.css @@ -48,6 +48,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'; diff --git a/app/ui-share/README.md b/app/ui-share/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/app/ui-share/client/index.js b/app/ui-share/client/index.js new file mode 100644 index 000000000000..c9281cc5bff8 --- /dev/null +++ b/app/ui-share/client/index.js @@ -0,0 +1,2 @@ +import './share.html'; +import './share'; diff --git a/app/ui-share/client/share.html b/app/ui-share/client/share.html new file mode 100644 index 000000000000..482e7fc12c8f --- /dev/null +++ b/app/ui-share/client/share.html @@ -0,0 +1,45 @@ + diff --git a/app/ui-share/client/share.js b/app/ui-share/client/share.js new file mode 100644 index 000000000000..401385366ee9 --- /dev/null +++ b/app/ui-share/client/share.js @@ -0,0 +1,70 @@ +import { Template } from 'meteor/templating'; + +import { getShareData, isMobile } 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"]'() { + window.open(`https://www.facebook.com/sharer/sharer.php?u=${ getShareString() }`); + }, + 'click [data-type="whatsapp"]'() { + window.open((isMobile() ? 'whatsapp://send?text=' : 'https://api.whatsapp.com/send?text=') + 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() }`); + }, + +}); diff --git a/app/ui-share/index.js b/app/ui-share/index.js new file mode 100644 index 000000000000..40a7340d3887 --- /dev/null +++ b/app/ui-share/index.js @@ -0,0 +1 @@ +export * from './client/index'; diff --git a/app/ui-sidenav/client/sidebarHeader.js b/app/ui-sidenav/client/sidebarHeader.js index 760005f69fed..50195750f44b 100644 --- a/app/ui-sidenav/client/sidebarHeader.js +++ b/app/ui-sidenav/client/sidebarHeader.js @@ -4,7 +4,7 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { Template } from 'meteor/templating'; import { popover, AccountBox, menu, SideNav, modal } from '../../ui-utils'; -import { t, getUserPreference, handleError, isMobile, shareApp } from '../../utils'; +import { t, getUserPreference, handleError, isMobile } from '../../utils'; import { callbacks } from '../../callbacks'; import { settings } from '../../settings'; import { hasAtLeastOnePermission } from '../../authorization'; @@ -289,11 +289,7 @@ const toolbarButtons = (user) => [{ const shareOption = { name: t('Share'), icon: 'share', - type: 'open', - action: () => { - shareApp(); - popover.close(); - }, + type: 'share-action', }; const config = { @@ -338,8 +334,9 @@ const toolbarButtons = (user) => [{ offsetVertical: e.currentTarget.clientHeight + 10, }; if (isMobile()) { - config.columns[0].groups[0].items = config.columns[0].groups[0].items.concat([sortOption, shareOption]); + config.columns[0].groups[0].items = config.columns[0].groups[0].items.concat([sortOption]); } + config.columns[0].groups[0].items = config.columns[0].groups[0].items.concat([shareOption]); popover.open(config); }, diff --git a/app/ui-utils/client/lib/popover.js b/app/ui-utils/client/lib/popover.js index b9193e7499ac..f9b7604e764f 100644 --- a/app/ui-utils/client/lib/popover.js +++ b/app/ui-utils/client/lib/popover.js @@ -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'; @@ -191,6 +192,23 @@ Template.popover.events({ }; popover.open(config); }, + '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; diff --git a/app/utils/client/index.js b/app/utils/client/index.js index 8fb848815a91..4dbad333c393 100644 --- a/app/utils/client/index.js +++ b/app/utils/client/index.js @@ -23,4 +23,4 @@ export { SWCache } from './lib/swCache'; export { mime } from '../lib/mimeTypes'; export { isMobile } from './lib/isMobile'; export { hex_sha1 } from './lib/sha1'; -export { share, shareApp, shareRoom } from './lib/share'; +export { share, isShareAvailable, getShareData } from './lib/share'; diff --git a/app/utils/client/lib/share.js b/app/utils/client/lib/share.js index adc3a5460c6e..b8059290a67c 100644 --- a/app/utils/client/lib/share.js +++ b/app/utils/client/lib/share.js @@ -2,59 +2,54 @@ import { Meteor } from 'meteor/meteor'; // TODO: Remove logs -export const share = ({ title, text, url }) => { - const data = { - title: title || 'Viasat Connect', - text: text || '', - url: url || 'https://viasatconnect.com', - }; +export const isShareAvailable = () => { + if (navigator.share) { return true; } + return false; +}; - console.log(`data: ${ JSON.stringify(data) }`); +export const getShareData = () => { + const data = {}; - 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'); - // TODO: Show Custom Share Options - } -}; + data.url = document.location.href || 'https://viasatconnect.com'; + const path = new URL(data.url).pathname; + const roomName = path.substring(path.lastIndexOf('/') + 1); -export const shareApp = () => { - console.log('Share App called'); - const user = Meteor.user(); + data.title = 'Viasat Connect'; + data.text = 'Viasat Connect is a new application that makes it easy for you to chat with friends and family. Open this link to connect.'; - const title = 'Viasat Connect'; - const text = 'Viasat Connect is a new application that makes it easy for me to chat with friends and family. Open this link and connect with me.'; - let url = new URL(document.location.href).origin; + if (path.startsWith('/channel')) { + data.title = `Join #${ roomName } on Viasat Connect`; + data.text = `You are invited to channel #${ roomName } on Viasat Connect. ${ data.text }`; + } else if (path.startsWith('/group')) { + data.title = `Join #${ roomName } on Viasat Connect`; + data.text = `You are invited to private group 🔒${ roomName } on Viasat Connect. ${ data.text }`; + } else if (path.startsWith('/direct')) { + data.title = `Chat with @${ roomName } on Viasat Connect`; + } else { + const user = Meteor.user(); - if (url) { - url = `${ url }/direct/${ user.username }`; + data.title = 'Viasat Connect'; + data.text = 'Viasat Connect is a new application that makes it easy for me to chat with friends and family. 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 }`; + } } - share({ title, text, url }); + return data; }; -export const shareRoom = () => { - console.log('Share Room called'); - - const url = document.location.href; - const path = new URL(url).pathname; - const roomName = path.substring(path.lastIndexOf('/') + 1); +export const share = () => { + const data = getShareData(); - let title = 'Viasat Connect'; - let text = 'Viasat Connect is a new application that makes it easy for you to chat with friends and family. Open this link to connect.'; + console.log(`data: ${ JSON.stringify(data) }`); - if (path.startsWith('/channel')) { - title = `Join #${ roomName } on Viasat Connect`; - text = `You are invited to channel #${ roomName } on Viasat Connect. ${ text }`; - } else if (path.startsWith('/group')) { - title = `Join #${ roomName } on Viasat Connect`; - text = `You are invited to private group 🔒${ roomName } on Viasat Connect. ${ text }`; - } else if (path.startsWith('/direct')) { - title = `Chat with @${ roomName } on Viasat Connect`; + 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'); } - - share({ title, text, url }); }; diff --git a/client/importPackages.js b/client/importPackages.js index 322eb3d767f2..30941c13db55 100644 --- a/client/importPackages.js +++ b/client/importPackages.js @@ -79,6 +79,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';