Updated StatusSharePopover -> SharePopover, Added group, account share

• Updated:
- StatusSharePopover -> SharePopover

• Added:
- group, account share
- group url in routes.rb
- group url in GroupSerializer.rb
- share buttons in ProfileOptionsPopover, GroupOptionsPopover
This commit is contained in:
mgabdev 2020-12-24 13:27:55 -05:00
parent 0ceccce04a
commit 7dd71a06ca
11 changed files with 119 additions and 49 deletions

View File

@ -8,7 +8,11 @@ import {
addShortcut,
removeShortcut,
} from '../../actions/shortcuts'
import { closePopover } from '../../actions/popover'
import {
openPopover,
closePopover,
} from '../../actions/popover'
import { POPOVER_SHARE } from '../../constants'
import PopoverLayout from './popover_layout'
import List from '../list'
@ -27,6 +31,10 @@ class GroupOptionsPopover extends ImmutablePureComponent {
}
}
handleOnShare = () => {
this.props.onShare(this.props.group)
}
render() {
const {
group,
@ -66,8 +74,16 @@ class GroupOptionsPopover extends ImmutablePureComponent {
to: `/groups/${groupId}/edit`,
isHidden: !isAdmin,
})
listItems.push({})
}
listItems.push({
hideArrow: true,
icon: 'share',
title: 'Share group',
onClick: this.handleOnShare,
})
listItems.push({})
listItems.push({
hideArrow: true,
icon: 'star',
@ -109,7 +125,7 @@ const mapStateToProps = (state, { group }) => {
return { isShortcut }
}
const mapDispatchToProps = (dispatch) => ({
const mapDispatchToProps = (dispatch, { innerRef }) => ({
onClosePopover: () => dispatch(closePopover()),
onAddShortcut(groupId) {
dispatch(addShortcut('group', groupId))
@ -117,6 +133,13 @@ const mapDispatchToProps = (dispatch) => ({
onRemoveShortcut(groupId) {
dispatch(removeShortcut(null, 'group', groupId))
},
onShare(group) {
dispatch(openPopover(POPOVER_SHARE, {
innerRef,
group,
position: 'top',
}))
},
})
GroupOptionsPopover.defaultProps = {

View File

@ -18,7 +18,7 @@ import {
POPOVER_SIDEBAR_MORE,
POPOVER_STATUS_OPTIONS,
POPOVER_STATUS_EXPIRATION_OPTIONS,
POPOVER_STATUS_SHARE,
POPOVER_SHARE,
POPOVER_STATUS_VISIBILITY,
POPOVER_TIMELINE_INJECTION_OPTIONS,
POPOVER_USER_INFO,
@ -43,7 +43,7 @@ import {
SidebarMorePopover,
StatusExpirationOptionsPopover,
StatusOptionsPopover,
StatusSharePopover,
SharePopover,
StatusVisibilityPopover,
TimelineInjectionOptionsPopover,
UserInfoPopover,
@ -82,7 +82,7 @@ const POPOVER_COMPONENTS = {
[POPOVER_SIDEBAR_MORE]: SidebarMorePopover,
[POPOVER_STATUS_OPTIONS]: StatusOptionsPopover,
[POPOVER_STATUS_EXPIRATION_OPTIONS]: StatusExpirationOptionsPopover,
[POPOVER_STATUS_SHARE]: StatusSharePopover,
[POPOVER_SHARE]: SharePopover,
[POPOVER_STATUS_VISIBILITY]: StatusVisibilityPopover,
[POPOVER_TIMELINE_INJECTION_OPTIONS]: TimelineInjectionOptionsPopover,
[POPOVER_USER_INFO]: UserInfoPopover,
@ -135,6 +135,10 @@ class PopoverRoot extends React.PureComponent {
return <ErrorPopover isXS={isXS} onClose={this.props.onClose} />
}
setRef = () => {
// : todo : ?
}
render() {
const { type, props, onClose } = this.props
const { width } = this.state

View File

@ -17,7 +17,11 @@ import {
} from '../../actions/shortcuts'
import { initReport } from '../../actions/reports'
import { openModal } from '../../actions/modal'
import { closePopover } from '../../actions/popover'
import {
openPopover,
closePopover,
} from '../../actions/popover'
import { POPOVER_SHARE } from '../../constants'
import { unfollowModal, me, isStaff } from '../../initial_state'
import { makeGetAccount } from '../../selectors'
import PopoverLayout from './popover_layout'
@ -37,14 +41,12 @@ class ProfileOptionsPopover extends React.PureComponent {
if (!account) return menu
if (account.get('id') === me) return menu
if ('share' in navigator) {
menu.push({
hideArrow: true,
icon: 'share',
title: intl.formatMessage(messages.share, { name: account.get('username') }),
onClick: this.handleShare
});
}
menu.push({
hideArrow: true,
@ -119,7 +121,7 @@ class ProfileOptionsPopover extends React.PureComponent {
}
handleShare = () => {
// : todo :
this.props.onShare(this.props.account)
}
handleFollow = () => {
@ -225,7 +227,7 @@ const mapStateToProps = (state, { account }) => {
}
}
const mapDispatchToProps = (dispatch, { intl }) => ({
const mapDispatchToProps = (dispatch, { intl, innerRef }) => ({
onFollow(account) {
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
if (unfollowModal) {
@ -291,6 +293,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(closePopover())
dispatch(removeShortcut(null, 'account', accountId))
},
onShare(account) {
dispatch(openPopover(POPOVER_SHARE, {
innerRef,
account,
position: 'top',
}))
},
})
ProfileOptionsPopover.defaultProps = {

View File

@ -3,20 +3,51 @@ import PropTypes from 'prop-types'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import { openModal } from '../../actions/modal'
import { showToast } from '../../actions/toasts'
import { closePopover } from '../../actions/popover'
import { TOAST_TYPE_SUCCESS } from '../../constants'
import PopoverLayout from './popover_layout'
import Button from '../button'
import Heading from '../heading'
import Text from '../text'
import List from '../list'
class StatusSharePopover extends ImmutablePureComponent {
class SharePopover extends ImmutablePureComponent {
state = {
url: '',
type: '',
}
componentDidMount() {
this._setUrl()
}
componentDidUpdate() {
this._setUrl()
}
_setUrl = () => {
const { account, group, status } = this.props
let url, type
if (!!account) {
type = 'account'
url = account.get('url')
} else if (!!group) {
type = 'group'
url = group.get('url')
} else if (!!status) {
type = 'status'
url = status.get('url')
}
this.setState({ url, type })
}
handleCopy = () => {
const url = this.props.status.get('url')
const { url } = this.state
const textarea = document.createElement('textarea')
textarea.textContent = url
@ -41,13 +72,12 @@ class StatusSharePopover extends ImmutablePureComponent {
}
render() {
const { intl, status } = this.props
const { url, type } = this.state
if (!status) return <div />
if (!url) return <div />
const encodedStatusUrl = encodeURIComponent(status.get('url'))
const mailToHref = `mailto:?subject=Gab&body=${encodedStatusUrl}`
const content = status.get('contentHtml')
const encodedUrl = encodeURIComponent(url)
const mailToHref = `mailto:?subject=Gab&body=${encodedUrl}`
const iconSize = '18px'
return (
@ -56,7 +86,7 @@ class StatusSharePopover extends ImmutablePureComponent {
>
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.jcCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.h53PX, _s.px15].join(' ')}>
<Heading size='h3'>
Share Gab
Share Gab {type}
</Heading>
</div>
<div className={[_s.d, _s.w100PC, _s.px15, _s.py15, _s.flexRow, _s.noScrollbar, _s.aiCenter, _s.overflowXScroll, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
@ -67,7 +97,7 @@ class StatusSharePopover extends ImmutablePureComponent {
color='primary'
backgroundColor='secondary'
onClick={this.handleCopy}
title={intl.formatMessage(messages.copy)}
title={`Copy this ${type}`}
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10].join(' ')}
/>
<Button
@ -76,7 +106,7 @@ class StatusSharePopover extends ImmutablePureComponent {
iconClassName={_s.inheritFill}
color='white'
backgroundColor='none'
href={`sms:+&body=${encodedStatusUrl}`}
href={`sms:+&body=${encodedUrl}`}
target='_blank'
title='Share via text message'
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10, _s.bgSMS].join(' ')}
@ -87,7 +117,7 @@ class StatusSharePopover extends ImmutablePureComponent {
iconClassName={_s.inheritFill}
color='white'
backgroundColor='none'
href={`https://www.facebook.com/sharer/sharer.php?u=${encodedStatusUrl}`}
href={`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`}
target='_blank'
title='Share on Facebook'
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10, _s.bgFacebook].join(' ')}
@ -98,7 +128,7 @@ class StatusSharePopover extends ImmutablePureComponent {
iconClassName={_s.inheritFill}
color='white'
backgroundColor='none'
href={`https://twitter.com/intent/tweet?url=${encodedStatusUrl}`}
href={`https://twitter.com/intent/tweet?url=${encodedUrl}`}
target='_blank'
title='Share on Twitter'
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10, _s.bgTwitter].join(' ')}
@ -109,7 +139,7 @@ class StatusSharePopover extends ImmutablePureComponent {
iconClassName={_s.inheritFill}
color='white'
backgroundColor='none'
href={`https://telegram.me/share/?url=${encodedStatusUrl}`}
href={`https://telegram.me/share/?url=${encodedUrl}`}
target='_blank'
title='Share on Telegram'
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10, _s.bgTelegram].join(' ')}
@ -120,7 +150,7 @@ class StatusSharePopover extends ImmutablePureComponent {
iconClassName={_s.inheritFill}
color='white'
backgroundColor='none'
href={`http://www.reddit.com/submit?url=${encodedStatusUrl}&title=Gab`}
href={`http://www.reddit.com/submit?url=${encodedUrl}&title=Gab`}
title='Share on Reddit'
target='_blank'
className={[_s.jcCenter, _s.aiCenter, _s.px10, _s.mr10, _s.bgReddit].join(' ')}
@ -152,22 +182,20 @@ class StatusSharePopover extends ImmutablePureComponent {
}
}
const messages = defineMessages({
email: { id: 'status.email', defaultMessage: 'Email this gab' },
copy: { id: 'status.copy', defaultMessage: 'Copy link to status' },
})
const mapDispatchToProps = (dispatch) => ({
onClosePopover: () => dispatch(closePopover()),
onShowCopyToast() {
dispatch(showToast())
dispatch(showToast(TOAST_TYPE_SUCCESS, {
type: "SUCCESSFULLY_COPIED_TO_CLIPBOARD"
}))
},
})
StatusSharePopover.propTypes = {
intl: PropTypes.object.isRequired,
SharePopover.propTypes = {
onClosePopover: PropTypes.func.isRequired,
status: ImmutablePropTypes.map.isRequired,
account: ImmutablePropTypes.map,
group: ImmutablePropTypes.map,
status: ImmutablePropTypes.map,
}
export default injectIntl(connect(null, mapDispatchToProps)(StatusSharePopover))
export default connect(null, mapDispatchToProps)(SharePopover)

View File

@ -45,7 +45,7 @@ import {
} from '../../actions/popover'
import {
MODAL_PRO_UPGRADE,
POPOVER_STATUS_SHARE,
POPOVER_SHARE,
} from '../../constants'
import PopoverLayout from './popover_layout'
import Button from '../button'
@ -529,7 +529,7 @@ const mapDispatchToProps = (dispatch) => ({
onOpenSharePopover(targetRef, status) {
dispatch(closePopover())
dispatch(openPopover(POPOVER_STATUS_SHARE, {
dispatch(openPopover(POPOVER_SHARE, {
targetRef,
status,
position: 'top',

View File

@ -42,7 +42,7 @@ export const POPOVER_PROFILE_OPTIONS = 'PROFILE_OPTIONS'
export const POPOVER_SIDEBAR_MORE = 'SIDEBAR_MORE'
export const POPOVER_STATUS_OPTIONS = 'STATUS_OPTIONS'
export const POPOVER_STATUS_EXPIRATION_OPTIONS = 'STATUS_EXPIRATION_OPTIONS'
export const POPOVER_STATUS_SHARE = 'STATUS_SHARE'
export const POPOVER_SHARE = 'POPOVER_SHARE'
export const POPOVER_STATUS_VISIBILITY = 'STATUS_VISIBILITY'
export const POPOVER_TIMELINE_INJECTION_OPTIONS = 'TIMELINE_INJECTION_OPTIONS'
export const POPOVER_USER_INFO = 'USER_INFO'

View File

@ -35,7 +35,7 @@ import {
MODAL_STATUS,
MODAL_PRO_UPGRADE,
POPOVER_COMMENT_SORTING_OPTIONS,
POPOVER_STATUS_SHARE,
POPOVER_SHARE,
COMMENT_SORTING_TYPE_OLDEST,
COMMENT_SORTING_TYPE_NEWEST,
COMMENT_SORTING_TYPE_TOP,
@ -323,7 +323,7 @@ const mapDispatchToProps = (dispatch) => ({
}
}
dispatch(openPopover(POPOVER_STATUS_SHARE, {
dispatch(openPopover(POPOVER_SHARE, {
targetRef,
status,
position: 'top',

View File

@ -136,7 +136,7 @@ export function SignUpPanel() { return import(/* webpackChunkName: "components/s
export function StatusExpirationOptionsPopover() { return import(/* webpackChunkName: "components/status_expiration_options_popover" */'../../../components/popover/status_expiration_options_popover') }
export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') }
export function StatusOptionsPopover() { return import(/* webpackChunkName: "components/status_options_popover" */'../../../components/popover/status_options_popover') }
export function StatusSharePopover() { return import(/* webpackChunkName: "components/status_share_popover" */'../../../components/popover/status_share_popover') }
export function SharePopover() { return import(/* webpackChunkName: "components/share_popover" */'../../../components/popover/share_popover') }
export function StatusPromotionPanel() { return import(/* webpackChunkName: "components/status_promotion_panel" */'../../../components/panel/status_promotion_panel') }
export function StatusReposts() { return import(/* webpackChunkName: "features/status_reposts" */'../../status_reposts') }
export function StatusModal() { return import(/* webpackChunkName: "modals/status_modal" */'../../../components/modal/status_modal') }

View File

@ -45,7 +45,7 @@ class TagManager
case target.object_type
when :person
"/#{target.username}"
short_account_with_replies_url(target)
when :note, :comment, :activity
short_account_status_url(target.account, target)
end

View File

@ -5,7 +5,7 @@ class REST::GroupSerializer < ActiveModel::Serializer
attributes :id, :title, :description, :description_html,
:cover_image_url, :is_archived, :member_count,
:created_at, :is_private, :is_visible, :slug,
:created_at, :is_private, :is_visible, :slug, :url,
:tags, :group_category, :password, :has_password
def id
@ -59,4 +59,9 @@ class REST::GroupSerializer < ActiveModel::Serializer
full_asset_url(object.cover_image.url)
end
def url
group_show_page_url(object)
end
end

View File

@ -408,6 +408,7 @@ Rails.application.routes.draw do
get '/(*any)', to: 'react#react', as: :web
get '/:username', to: 'react#account_show', username: username_regex, as: :short_account_with_replies
get '/groups/:groupId', to: 'react#group_show', as: :group_show_page
root 'react#react'
get '/', to: 'react#react', as: :homepage