Skip to content

Commit

Permalink
Add a 'default' network option that changes modal into split dropdown (
Browse files Browse the repository at this point in the history
…#39)

* Add a 'default' network option that changes modal into split dropdown
* Use 'getNetworkButtons' in ShareModal
* Remove unused imports
  • Loading branch information
dsevillamartin authored Feb 2, 2024
1 parent 66c5f89 commit 418af9f
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 93 deletions.
3 changes: 2 additions & 1 deletion extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@

(new Extend\Settings())
->default('fof-share-social.plain-copy', true)
->serializeToForum('fof-share-social.plain-copy', 'fof-share-social.plain-copy'),
->serializeToForum('fof-share-social.plain-copy', 'fof-share-social.plain-copy')
->serializeToForum('fof-share-social.default', 'fof-share-social.default-option'),

(new Extend\ApiSerializer(ForumSerializer::class))
->attributes(ForumAttributes::class),
Expand Down
14 changes: 14 additions & 0 deletions js/src/admin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import app from 'flarum/admin/app';
import type { SelectSettingComponentOptions } from 'flarum/admin/components/AdminPage';

const networks = [
'facebook',
Expand Down Expand Up @@ -29,6 +30,19 @@ app.initializers.add('fof/share-social', () => {
setting: 'fof-share-social.plain-copy',
type: 'boolean',
})
.registerSetting({
label: app.translator.trans('fof-share-social.admin.settings.default-option'),
help: app.translator.trans('fof-share-social.admin.settings.default-option-help'),
setting: 'fof-share-social.default-option',
type: 'select',
options: networks.reduce(
(o, network) => {
o[network] = app.translator.trans(`fof-share-social.lib.networks.${network}`);
return o;
},
{ '': '' } as SelectSettingComponentOptions['options']
),
})
.registerSetting(function () {
return <hr />;
});
Expand Down
77 changes: 3 additions & 74 deletions js/src/forum/components/ShareModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,8 @@ import app from 'flarum/forum/app';
import Modal from 'flarum/common/components/Modal';
import Button from 'flarum/common/components/Button';
import icon from 'flarum/common/helpers/icon';
import { truncate, getPlainContent } from 'flarum/common/utils/string';

import pupa from 'pupa';
import ItemList from 'flarum/common/utils/ItemList';

const navigatorData = ({ title, description, url }) => ({ title, text: description, url });

const share = {
facebook: '//facebook.com/sharer/sharer.php?u={url}',
twitter: '//twitter.com/share?url={url}&text={title}',
linkedin: '//linkedin.com/shareArticle?mini=true&url={url}&title={title}&summary={description}',
reddit: '//www.reddit.com/submit?url={url}&title={title}',
whatsapp: '//api.whatsapp.com/send/?phone&text={title}%20{url}',
telegram: '//telegram.me/share/url?url={url}&text={title}',

vkontakte: '//vk.com/share.php?url={url}&title={title}&description={description}',
odnoklassniki: '//connect.ok.ru/offer?url={url}',
my_mail: '//connect.mail.ru/share?url={url}&title={title}&description={description}',
qq: '//connect.qq.com/widget/shareqq/iframe_index.html?url={url}&title={title}',
qzone: '//sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={url}&summary={description}&title={title}',

native: (data) => navigator.share(navigatorData(data)),
};

const shareIcons = {
vkontakte: 'fab fa-vk',
my_mail: 'fas fa-at',
qq: 'fab fa-qq',
qzone: 'fas fa-star',
native: 'fas fa-share-square',
};
import { getNetworkButtons } from '../util/networks';

export default class ShareModal extends Modal {
oninit(vdom) {
Expand Down Expand Up @@ -61,26 +32,9 @@ export default class ShareModal extends Modal {
}

shareItems() {
const items = new ItemList();
const items = getNetworkButtons(this.discussion, true);
const plainCopy = app.forum.attribute('fof-share-social.plain-copy');

{
this.networks
.filter((name) => name !== 'native' || navigator.canShare?.(navigatorData(this.data())))
.map((network) =>
items.add(
`network-${network}`,
<Button
className={`Button Button--rounded Button--block Share--${network}`}
icon={`${shareIcons[network] || `fab fa-${network}`} fa-lg fa-fw`}
onclick={this.onclick.bind(this, network)}
>
{app.translator.trans(`fof-share-social.lib.networks.${network}`)}
</Button>
)
);
}

if (plainCopy) {
items.add(
'plain-copy',
Expand All @@ -101,32 +55,7 @@ export default class ShareModal extends Modal {
}

onclick(network) {
const data = this.data();
const action = share[network];

if (typeof action === 'function') {
return action(data);
}

const width = 1000;
const height = 500;
const top = $(window).height() / 2 - height / 2;
const left = $(window).width() / 2 - width / 2;
const windowParams = `width=${width}, height= ${height}, top=${top}, left=${left}, status=no, scrollbars=no, resizable=no`;

for (const dataKey in data) {
data[dataKey] = encodeURIComponent(data[dataKey]);
}

window.open(pupa(action, data), app.title, windowParams);
}

data() {
const url = this.discussion.shareUrl();
const title = app.title;
const description = (this.discussion.firstPost() && truncate(getPlainContent(this.discussion.firstPost()?.contentHtml()), 150, 0)) || '';

return { url, title, description };
return share(network);
}

copy() {
Expand Down
82 changes: 64 additions & 18 deletions js/src/forum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,78 @@ import DiscussionPage from 'flarum/forum/components/DiscussionPage';
import Button from 'flarum/common/components/Button';
import Model from 'flarum/common/Model';
import Discussion from 'flarum/common/models/Discussion';
import SplitDropdown from 'flarum/common/components/SplitDropdown';

import ShareModal from './components/ShareModal';
import { getNativeData } from './util/share';
import { getNetworkButtons } from './util/networks';

const getNetworks = () => {
let cache = null;

return (networks, def) => {
if (cache) return cache;

cache = [...networks];
const index = cache.indexOf(def);

if (index !== -1) {
cache.splice(index, 1);
cache.unshift(def);
}

return cache;
};
};

app.initializers.add('fof/share-social', () => {
Discussion.prototype.shareUrl = Model.attribute('shareUrl');

extend(DiscussionPage.prototype, 'sidebarItems', function (items) {
const networks = app.forum.attribute('fof-share-social.networks');
const def = app.forum.attribute('fof-share-social.default');

const isNativeShare = def === 'native';
const canNativeShare = isNativeShare && navigator.canShare?.(getNativeData(this.discussion));

if (def && (!isNativeShare || canNativeShare)) {
const list = getNetworkButtons(this.discussion);

// Use default share button text for native sharing
if (isNativeShare) {
list.get('native').children = app.translator.trans('fof-share-social.forum.discussion.share_button');
}

if (list.isEmpty()) return;

if (!networks.length) return;

items.add(
'share-social',
<Button
class="Button Button-icon Button--share"
icon="fas fa-share-alt"
onclick={() =>
app.modal.show(ShareModal, {
networks,
discussion: this.discussion,
})
}
>
{app.translator.trans('fof-share-social.forum.discussion.share_button')}
</Button>,
-1
);
items.add(
'share-social',
<SplitDropdown
icon="fas fa-share-alt"
buttonClassName="Button--share"
accessibleToggleLabel={app.translator.trans('fof-share-social.forum.discussion.share_dropdown_accessible_label')}
lazyDraw={true}
>
{list.toArray()}
</SplitDropdown>
);
} else {
items.add(
'share-social',
<Button
class="Button Button-icon Button--share"
icon="fas fa-share-alt"
onclick={() =>
app.modal.show(ShareModal, {
networks,
discussion: this.discussion,
})
}
>
{app.translator.trans('fof-share-social.forum.discussion.share_button')}
</Button>,
-1
);
}
});
});
58 changes: 58 additions & 0 deletions js/src/forum/util/networks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import app from 'flarum/forum/app';
import ItemList from 'flarum/common/utils/ItemList';
import Button from 'flarum/common/components/Button';
import classList from 'flarum/common/utils/classList';
import { data, networkIcons, networks } from './share';
import pupa from 'pupa';

export const getNetworkButton = ({ network, discussion, isRounded = false }) => {
return (
<Button
className={classList(`Button Button--block Share--${network}`, isRounded && 'Button--rounded')}
icon={`${networkIcons[network] || `fab fa-${network}`} fa-lg fa-fw`}
onclick={onNetworkButtonClick.bind(this, network, discussion)}
>
{app.translator.trans(`fof-share-social.lib.networks.${network}`)}
</Button>
);
};

export const onNetworkButtonClick = (network, discussion) => {
const payload = data(discussion);
const action = networks[network];

if (typeof action === 'function') {
return action(payload);
}

const width = 1000;
const height = 500;
const top = $(window).height() / 2 - height / 2;
const left = $(window).width() / 2 - width / 2;
const windowParams = `width=${width}, height= ${height}, top=${top}, left=${left}, status=no, scrollbars=no, resizable=no`;

for (const dataKey in payload) {
payload[dataKey] = encodeURIComponent(payload[dataKey]);
}

window.open(pupa(action, payload), app.title, windowParams);
};

export const getNetworkButtons = (discussion, isRounded) => {
const list = new ItemList();
const networks = app.forum.attribute('fof-share-social.networks');
const def = app.forum.attribute('fof-share-social.default');

for (const network of networks) {
// Do not add native share option if not supported
if (network === 'native' && !navigator.canShare?.(data(discussion))) continue;

list.add(network, getNetworkButton({ network, discussion, isRounded }));
}

if (list.has(def)) {
list.setPriority(def, 1000);
}

return list;
};
41 changes: 41 additions & 0 deletions js/src/forum/util/share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import app from 'flarum/forum/app';
import { getPlainContent, truncate } from 'flarum/common/utils/string';
import pupa from 'pupa';

export const networks = {
facebook: '//facebook.com/sharer/sharer.php?u={url}',
twitter: '//twitter.com/share?url={url}&text={title}',
linkedin: '//linkedin.com/shareArticle?mini=true&url={url}&title={title}&summary={description}',
reddit: '//www.reddit.com/submit?url={url}&title={title}',
whatsapp: '//api.whatsapp.com/send/?phone&text={title}%20{url}',
telegram: '//telegram.me/share/url?url={url}&text={title}',

vkontakte: '//vk.com/share.php?url={url}&title={title}&description={description}',
odnoklassniki: '//connect.ok.ru/offer?url={url}',
my_mail: '//connect.mail.ru/share?url={url}&title={title}&description={description}',
qq: '//connect.qq.com/widget/shareqq/iframe_index.html?url={url}&title={title}',
qzone: '//sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={url}&summary={description}&title={title}',

native: (data) => navigator.share(getNativeData(data)),
};
export const networkIcons = {
vkontakte: 'fab fa-vk',
my_mail: 'fas fa-at',
qq: 'fab fa-qq',
qzone: 'fas fa-star',
native: 'fas fa-share-square',
};

export const data = (discussion) => {
const url = discussion.shareUrl();
const title = app.title;
const description = (discussion.firstPost() && truncate(getPlainContent(discussion.firstPost()?.contentHtml()), 150, 0)) || '';

return { url, title, description };
};

export const getNativeData = ({ title, description, url }) => ({ title, text: description, url });

export const canNativeShare = (discussion) => {
return navigator.canShare?.(getNativeData(discussion));
};
44 changes: 44 additions & 0 deletions resources/less/forum.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,51 @@
border-radius: @border-radius;
margin-top: 10px !important;
}
}

.item-share-social .Dropdown {
&:not(.itemCount1) {
.SplitDropdown-button {
width: unset;
}
}

.Dropdown-menu {
.Button {
width: 100% !important;
color: var(--button-color);
background: var(--button-bg);

.icon {
margin-top: 4px;
}

&:hover,
&:focus,
&.focus {
background-color: var(--button-bg-hover);
}

&:active,
&.active,
.open > .Dropdown-toggle& {
background-color: var(--button-bg-active);
}
}

@media @tablet-up {
padding: 0;

.Button {
margin: 4px 4px;
border-radius: @border-radius;
width: ~"calc(100% - 8px)" !important;
}
}
}
}

.item-share-social, .FofShareSocialModal {
.Share--facebook {
.Button--color(#fff, #3B5998);
}
Expand Down
Loading

0 comments on commit 418af9f

Please sign in to comment.