Progress
This commit is contained in:
@@ -253,10 +253,21 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||
<div className={[_s.default, _s.ml5].join(' ')}>
|
||||
|
||||
{/*<Composer
|
||||
/>*/}
|
||||
<Composer
|
||||
inputRef={this.setTextbox}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={autoFocus}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
{ /* <Textarea
|
||||
className={_s.default}
|
||||
inputRef={this.setTextbox}
|
||||
disabled={disabled}
|
||||
@@ -270,8 +281,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
aria-autocomplete='list'
|
||||
/>
|
||||
|
||||
/> */ }
|
||||
|
||||
{ /*
|
||||
<Textarea
|
||||
|
||||
@@ -1,36 +1,315 @@
|
||||
import {
|
||||
Editor,
|
||||
EditorState,
|
||||
CompositeDecorator,
|
||||
RichUtils
|
||||
} from 'draft-js'
|
||||
import { urlRegex } from '../features/compose/util/url_regex'
|
||||
import classNames from 'classnames/bind'
|
||||
import Button from './button'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
const getBlockStyle = (block) => {
|
||||
switch (block.getType()) {
|
||||
case 'blockquote':
|
||||
return 'RichEditor-blockquote'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function handleStrategy(contentBlock, callback, contentState) {
|
||||
findWithRegex(HANDLE_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function hashtagStrategy (contentBlock, callback, contentState) {
|
||||
findWithRegex(HASHTAG_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function urlStrategy (contentBlock, callback, contentState) {
|
||||
findWithRegex(urlRegex, contentBlock, callback)
|
||||
}
|
||||
|
||||
const findWithRegex = (regex, contentBlock, callback) => {
|
||||
const text = contentBlock.getText()
|
||||
let matchArr, start
|
||||
while ((matchArr = regex.exec(text)) !== null) {
|
||||
start = matchArr.index
|
||||
callback(start, start + matchArr[0].length)
|
||||
}
|
||||
}
|
||||
|
||||
const HighlightedSpan = (props) => {
|
||||
console.log("HighlightedSpan:", props)
|
||||
return (
|
||||
<span
|
||||
className={_s.colorBrand}
|
||||
data-offset-key={props.offsetKey}
|
||||
>
|
||||
{props.children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const RTE_ITEMS = [
|
||||
{
|
||||
label: 'Bold',
|
||||
style: 'BOLD',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Italic',
|
||||
style: 'ITALIC',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Underline',
|
||||
style: 'UNDERLINE',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Monospace',
|
||||
style: 'CODE',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'H1',
|
||||
style: 'header-one',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Blockquote',
|
||||
style: 'blockquote',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'UL',
|
||||
style: 'unordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'OL',
|
||||
style: 'ordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Code Block',
|
||||
style: 'code-block',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
]
|
||||
|
||||
const compositeDecorator = new CompositeDecorator([
|
||||
{
|
||||
strategy: handleStrategy,
|
||||
component: HighlightedSpan,
|
||||
},
|
||||
{
|
||||
strategy: hashtagStrategy,
|
||||
component: HighlightedSpan,
|
||||
},
|
||||
{
|
||||
strategy: urlStrategy,
|
||||
component: HighlightedSpan,
|
||||
}
|
||||
])
|
||||
|
||||
const HANDLE_REGEX = /\@[\w]+/g;
|
||||
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g;
|
||||
|
||||
export default class Composer extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
inputRef: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
autoFocus: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onKeyUp: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
onPaste: PropTypes.func,
|
||||
}
|
||||
|
||||
state = {
|
||||
editorState: EditorState.createEmpty(),
|
||||
editorState: EditorState.createEmpty(compositeDecorator),
|
||||
}
|
||||
|
||||
onChange = (editorState) => {
|
||||
this.setState({ editorState })
|
||||
}
|
||||
|
||||
onBoldClick() {
|
||||
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
|
||||
onToggleInlineStyle = (style) => {
|
||||
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, style))
|
||||
}
|
||||
|
||||
focus = () => {
|
||||
this.textbox.editor.focus()
|
||||
}
|
||||
|
||||
handleKeyCommand = (command) => {
|
||||
const { editorState } = this.state
|
||||
const newState = RichUtils.handleKeyCommand(editorState, command)
|
||||
|
||||
if (newState) {
|
||||
this.onChange(newState)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
onTab = (e) => {
|
||||
const maxDepth = 4
|
||||
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth))
|
||||
}
|
||||
|
||||
toggleBlockType = (blockType) => {
|
||||
this.onChange(
|
||||
RichUtils.toggleBlockType(
|
||||
this.state.editorState,
|
||||
blockType
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
toggleInlineStyle = (inlineStyle) => {
|
||||
this.onChange(
|
||||
RichUtils.toggleInlineStyle(
|
||||
this.state.editorState,
|
||||
inlineStyle
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
setRef = (n) => {
|
||||
this.textbox = n
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
inputRef,
|
||||
disabled,
|
||||
placeholder,
|
||||
autoFocus,
|
||||
// value,
|
||||
onChange,
|
||||
onKeyDown,
|
||||
onKeyUp,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onPaste
|
||||
} = this.props
|
||||
const { editorState } = this.state
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
|
||||
{/*<button onClick={this.onBoldClick.bind(this)}>Bold</button>*/}
|
||||
|
||||
<Editor
|
||||
editorState={this.state.editorState}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
<div className={[_s.default, _s.backgroundColorPrimary, _s.borderBottom1PX, _s.borderColorSecondary, _s.py5, _s.px15, _s.alignItemsCenter, _s.flexRow].join(' ')}>
|
||||
{
|
||||
RTE_ITEMS.map((item, i) => (
|
||||
<StyleButton
|
||||
key={`rte-button-${i}`}
|
||||
editorState={editorState}
|
||||
{...item}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
onClick={this.focus}
|
||||
className={[_s.text, _s.fontSize16PX].join(' ')}
|
||||
>
|
||||
<Editor
|
||||
blockStyleFn={getBlockStyle}
|
||||
// customStyleMap={styleMap}
|
||||
editorState={editorState}
|
||||
handleKeyCommand={this.handleKeyCommand}
|
||||
onChange={this.onChange}
|
||||
onTab={this.onTab}
|
||||
placeholder={placeholder}
|
||||
ref={this.setRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StyleButton extends PureComponent {
|
||||
static propTypes = {
|
||||
onToggle: PropTypes.func,
|
||||
label: PropTypes.string,
|
||||
style: PropTypes.string,
|
||||
icon: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
}
|
||||
|
||||
handleOnToggle = (e) => {
|
||||
const { onToggle, style } = this.props
|
||||
e.preventDefault()
|
||||
onToggle(style)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
label,
|
||||
style,
|
||||
type,
|
||||
icon,
|
||||
editorState
|
||||
} = this.props
|
||||
|
||||
const selection = editorState.getSelection()
|
||||
|
||||
const currentStyle = editorState.getCurrentInlineStyle()
|
||||
const blockType = editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType()
|
||||
|
||||
let active
|
||||
// active={type.style === blockType}
|
||||
// active={currentStyle.has(type.style)}
|
||||
|
||||
const btnClasses = cx({
|
||||
px10: 1,
|
||||
mr5: 1,
|
||||
backgroundSubtle2Dark_onHover: 1,
|
||||
backgroundColorBrandLight: active,
|
||||
// py10: !small,
|
||||
// py5: small,
|
||||
// px5: small,
|
||||
})
|
||||
|
||||
const iconClasses = cx({
|
||||
fillColorSecondary: !active,
|
||||
fillColorWhite: active,
|
||||
})
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={btnClasses}
|
||||
backgroundColor='none'
|
||||
onClick={this.handleOnToggle}
|
||||
title={label}
|
||||
icon={'rich-text'}
|
||||
iconClassName={iconClasses}
|
||||
iconWidth='10px'
|
||||
iconHeight='10px'
|
||||
radiusSmall
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,11 @@ class DisplayName extends ImmutablePureComponent {
|
||||
!!large ? '19px' :
|
||||
!!small ? '14px' : '16px'
|
||||
|
||||
const domain = account.get('acct').split('@')[1];
|
||||
const isRemoteUser = !!domain
|
||||
|
||||
console.log("domain, isRemoteUser:", domain, isRemoteUser)
|
||||
|
||||
// : todo :
|
||||
return (
|
||||
<span {...containerOptions} ref={this.setRef}>
|
||||
@@ -117,20 +122,20 @@ class DisplayName extends ImmutablePureComponent {
|
||||
</bdi>
|
||||
{
|
||||
account.get('is_verified') &&
|
||||
<Icon id='verified' width={iconSize} height={iconSize} className={_s.default} title='Verified Account' />
|
||||
<Icon id='verified' width={iconSize} height={iconSize} className={_s.default} />
|
||||
}
|
||||
{ /*
|
||||
{
|
||||
account.get('is_pro') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab PRO' />
|
||||
*/ }
|
||||
{ /*
|
||||
<Icon id='pro' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
{
|
||||
account.get('is_donor') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Donor' />
|
||||
*/ }
|
||||
{ /*
|
||||
<Icon id='donor' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
{
|
||||
account.get('is_investor') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Investor' />
|
||||
*/ }
|
||||
<Icon id='investor' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
</div>
|
||||
{
|
||||
!noUsername &&
|
||||
|
||||
@@ -10,15 +10,18 @@ import CircleIcon from '../assets/circle_icon'
|
||||
import CloseIcon from '../assets/close_icon'
|
||||
import CommentIcon from '../assets/comment_icon'
|
||||
import DissenterIcon from '../assets/dissenter_icon'
|
||||
import DonorIcon from '../assets/donor_icon'
|
||||
import EllipsisIcon from '../assets/ellipsis_icon'
|
||||
import ErrorIcon from '../assets/error_icon'
|
||||
import FullscreenIcon from '../assets/fullscreen_icon'
|
||||
import GabLogoIcon from '../assets/gab_logo'
|
||||
import GifIcon from '../assets/gif_icon'
|
||||
import GlobeIcon from '../assets/globe_icon'
|
||||
import GroupIcon from '../assets/group_icon'
|
||||
import GroupAddIcon from '../assets/group_add_icon'
|
||||
import HappyIcon from '../assets/happy_icon'
|
||||
import HomeIcon from '../assets/home_icon'
|
||||
import InvestorIcon from '../assets/investor_icon'
|
||||
import LikeIcon from '../assets/like_icon'
|
||||
import LinkIcon from '../assets/link_icon'
|
||||
import ListIcon from '../assets/list_icon'
|
||||
@@ -33,6 +36,7 @@ import PauseIcon from '../assets/pause_icon'
|
||||
import PinIcon from '../assets/pin_icon'
|
||||
import PlayIcon from '../assets/play_icon'
|
||||
import PollIcon from '../assets/poll_icon'
|
||||
import ProIcon from '../assets/pro_icon'
|
||||
import RepostIcon from '../assets/repost_icon'
|
||||
import RichTextIcon from '../assets/rich_text_icon'
|
||||
import SearchIcon from '../assets/search_icon'
|
||||
@@ -56,15 +60,18 @@ const ICONS = {
|
||||
'close': CloseIcon,
|
||||
'comment': CommentIcon,
|
||||
'dissenter': DissenterIcon,
|
||||
'donor': DonorIcon,
|
||||
'ellipsis': EllipsisIcon,
|
||||
'error': ErrorIcon,
|
||||
'fullscreen': FullscreenIcon,
|
||||
'gab-logo': GabLogoIcon,
|
||||
'gif': GifIcon,
|
||||
'globe': GlobeIcon,
|
||||
'group': GroupIcon,
|
||||
'group-add': GroupAddIcon,
|
||||
'happy': HappyIcon,
|
||||
'home': HomeIcon,
|
||||
'investor': InvestorIcon,
|
||||
'like': LikeIcon,
|
||||
'link': LinkIcon,
|
||||
'list': ListIcon,
|
||||
@@ -79,6 +86,7 @@ const ICONS = {
|
||||
'pin': PinIcon,
|
||||
'play': PlayIcon,
|
||||
'poll': PollIcon,
|
||||
'pro': ProIcon,
|
||||
'repost': RepostIcon,
|
||||
'rich-text': RichTextIcon,
|
||||
'search': SearchIcon,
|
||||
|
||||
@@ -134,7 +134,7 @@ class LinkFooter extends PureComponent {
|
||||
defaultMessage='Gab Social is open source software. You can contribute or report issues on our self-hosted GitLab at {gitlab}.'
|
||||
values={{
|
||||
gitlab: (
|
||||
<a href={source_url} className={_s.inherit} rel='noopener' target='_blank'>
|
||||
<a href={source_url} className={_s.inherit} rel='noopener noreferrer' target='_blank'>
|
||||
{repository}
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import Button from '../button'
|
||||
import Text from '../text'
|
||||
import ModalLayout from './modal_layout'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class LeavingGabModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout>
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -96,12 +96,12 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
||||
|
||||
{ /* : todo : */}
|
||||
<dd className='verified'>
|
||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener'>
|
||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'>
|
||||
<span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
|
||||
<Icon id='check' className='verified__mark' />
|
||||
</span>
|
||||
</a>
|
||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener'>
|
||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'>
|
||||
<span
|
||||
className={_s.dangerousContent}
|
||||
dangerouslySetInnerHTML={{ __html: ' ' + proof.get('provider_username') }}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { shortNumberFormat } from '../../utils/numbers'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import Avatar from '../avatar'
|
||||
import Button from '../button'
|
||||
import DisplayName from '../display_name'
|
||||
import Text from '../text'
|
||||
|
||||
export default class RemoteUserInfoPopover extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account } = this.props
|
||||
|
||||
const content = !account ? null : { __html: account.get('note_emojified') }
|
||||
|
||||
return (
|
||||
<PopoverLayout>
|
||||
<div className={[_s.default, _s.px15, _s.py15].join(' ')} style={{width: '260px'}}>
|
||||
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||
<Avatar account={account} size={42} />
|
||||
<DisplayName account={account} multiline noHover />
|
||||
</div>
|
||||
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||
<Button
|
||||
color='white'
|
||||
>
|
||||
<Text size='medium' weight='bold' color='inherit'>
|
||||
Following
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.my10].join(' ')}>
|
||||
<div className={_s.dangerousContent} dangerouslySetInnerHTML={content} />
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
<div>
|
||||
<Text size='small'>
|
||||
{shortNumberFormat(account.get('following_count'))}
|
||||
Following
|
||||
</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Text size='small'>
|
||||
{shortNumberFormat(account.get('followers_count'))}
|
||||
Followers
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</PopoverLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.open),
|
||||
title: intl.formatMessage(messages.open),
|
||||
onClick: this.handleOpen
|
||||
});
|
||||
|
||||
@@ -76,13 +76,13 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.copy),
|
||||
title: intl.formatMessage(messages.copy),
|
||||
onClick: this.handleCopy,
|
||||
})
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.embed),
|
||||
title: intl.formatMessage(messages.embed),
|
||||
onClick: this.handleEmbed,
|
||||
})
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
|
||||
title: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
|
||||
onClick: this.handleConversationMuteClick,
|
||||
})
|
||||
}
|
||||
@@ -103,33 +103,33 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(status.get('pinned') ? messages.unpin : messages.pin),
|
||||
title: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin),
|
||||
onClick: this.handlePinClick,
|
||||
})
|
||||
} else {
|
||||
if (status.get('visibility') === 'private') {
|
||||
menu.push({
|
||||
title: formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private),
|
||||
title: intl.formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private),
|
||||
onClick: this.handleRepostClick
|
||||
})
|
||||
}
|
||||
}
|
||||
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||
menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick });
|
||||
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||
menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
|
||||
} else {
|
||||
menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
||||
menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
||||
menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
||||
menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
||||
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
||||
menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
||||
menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
||||
menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
||||
|
||||
if (isStaff) {
|
||||
menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||
menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
||||
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
||||
}
|
||||
|
||||
if (withGroupAdmin) {
|
||||
menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
||||
menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
||||
menu.push({ text: intl.formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
||||
menu.push({ text: intl.formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ class Sidebar extends ImmutablePureComponent {
|
||||
{
|
||||
title: 'Home',
|
||||
icon: 'home',
|
||||
to: '/',
|
||||
to: '/home',
|
||||
count: homeItemsQueueCount,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { me } from '../initial_state'
|
||||
import { makeGetAccount } from '../selectors'
|
||||
import GabLogo from '../assets/gab_logo'
|
||||
import Icon from './icon'
|
||||
import SidebarSectionItem from './sidebar_section_item'
|
||||
import Text from './text'
|
||||
|
||||
@@ -27,14 +27,20 @@ class SidebarHeader extends ImmutablePureComponent {
|
||||
render() {
|
||||
const { account } = this.props
|
||||
|
||||
const isPro = account.get('is_pro')
|
||||
const gabLogoClasses = isPro ? _s.fillColorGabPro : _s.fillColorBrand
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h1 className={[_s.default].join(' ')}>
|
||||
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.flexRow, _s.noSelect, _s.noUnderline, _s.height50PX, _s.cursorPointer, _s.px10].join(' ')}>
|
||||
<GabLogo />
|
||||
<Text weight='bold' color='brand' size='extraSmall' className={[_s.pb5].join(' ')}>
|
||||
BETA
|
||||
</Text>
|
||||
<Icon id='gab-logo' className={gabLogoClasses} />
|
||||
{
|
||||
isPro &&
|
||||
<Text weight='bold' color='pro' size='extraSmall' className={[_s.pb5].join(' ')}>
|
||||
PRO
|
||||
</Text>
|
||||
}
|
||||
</NavLink>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ import Icon from './icon'
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
export default class SidebarSectionItem extends PureComponent {
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
to: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
@@ -46,7 +50,8 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
const { hovering } = this.state
|
||||
|
||||
const iconSize = '16px'
|
||||
const shouldShowActive = hovering || active
|
||||
const currentPathname = this.context.router.route.location.pathname
|
||||
const shouldShowActive = hovering || active || currentPathname === to || currentPathname === href
|
||||
const isNotifications = to === '/notifications'
|
||||
|
||||
const containerClasses = cx({
|
||||
@@ -58,10 +63,12 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
px10: 1,
|
||||
alignItemsCenter: 1,
|
||||
radiusSmall: 1,
|
||||
// border1PX: shouldShowActive,
|
||||
// borderColorSecondary: shouldShowActive,
|
||||
backgroundSubtle2: shouldShowActive,
|
||||
backgroundTransparent: 1,
|
||||
mt2: 1,
|
||||
border1PX: 1,
|
||||
borderColorTransparent: !shouldShowActive,
|
||||
borderColorSecondary: shouldShowActive,
|
||||
backgroundTransparent: !shouldShowActive,
|
||||
backgroundColorPrimary: shouldShowActive,
|
||||
})
|
||||
|
||||
const textClasses = cx({
|
||||
@@ -70,13 +77,13 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
fontSize15PX: 1,
|
||||
text: 1,
|
||||
textOverflowEllipsis: 1,
|
||||
colorSecondary: !hovering && !active && !me && !shouldShowActive,
|
||||
colorPrimary: shouldShowActive || me,
|
||||
colorSecondary: !hovering && !active && !me,
|
||||
})
|
||||
|
||||
const iconClasses = cx({
|
||||
fillColorSecondary: !hovering && !active && !shouldShowActive,
|
||||
fillColorBlack: shouldShowActive,
|
||||
fillColorSecondary: !hovering && !active,
|
||||
})
|
||||
|
||||
const countClasses = cx({
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class StatusActionBarItem extends PureComponent {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.flexGrow1, _s.px10].join(' ')}>
|
||||
<div className={[_s.default, _s.flexGrow1, _s.px5].join(' ')}>
|
||||
<button
|
||||
ref={buttonRef}
|
||||
className={btnClasses}
|
||||
|
||||
@@ -144,7 +144,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
className={[_s.default, _s.displayFlex, _s.text, _s.noUnderline, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fontSize15PX, _s.fontWeightMedium].join(' ')}
|
||||
href={card.get('url')}
|
||||
title={card.get('title')}
|
||||
rel='noopener'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
{card.get('title')}
|
||||
@@ -228,7 +228,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
<a
|
||||
href={card.get('url')}
|
||||
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.backgroundSubtle_onHover, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
rel='noopener'
|
||||
rel='noopener noreferrer'
|
||||
ref={this.setRef}
|
||||
>
|
||||
{embed}
|
||||
|
||||
@@ -49,14 +49,15 @@ class StatusContent extends ImmutablePureComponent {
|
||||
|
||||
const links = node.querySelectorAll('a')
|
||||
|
||||
for (var i = 0; i < links.length; ++i) {
|
||||
let link = links[i]
|
||||
if (link.classList.contains('status-link')) {
|
||||
for (let i = 0; i < links.length; ++i) {
|
||||
const link = links[i]
|
||||
if (link.classList.contains('linked')) {
|
||||
continue
|
||||
}
|
||||
link.classList.add('status-link')
|
||||
link.classList.add('linked')
|
||||
link.classList.add(_s.text, _s.colorBrand, _s.cursorPointer, _s.inherit)
|
||||
|
||||
let mention = this.props.status.get('mentions').find(item => link.href === `${item.get('url')}`)
|
||||
const mention = this.props.status.get('mentions').find(item => link.href === `${item.get('url')}`)
|
||||
|
||||
if (mention) {
|
||||
link.addEventListener('click', this.onMentionClick.bind(this, mention), false)
|
||||
@@ -66,6 +67,20 @@ class StatusContent extends ImmutablePureComponent {
|
||||
} else {
|
||||
link.setAttribute('title', link.href)
|
||||
}
|
||||
|
||||
const descendents = link.getElementsByTagName('*')
|
||||
for (let j = 0; j < descendents.length; j++) {
|
||||
const descendent = descendents[j];
|
||||
|
||||
if (descendent.classList.contains('invisible')) {
|
||||
descendent.classList.remove('invisible')
|
||||
descendent.classList.add(_s.fontSize0, _s.text, _s.inherit)
|
||||
}
|
||||
if (descendent.classList.contains('ellipsis')) {
|
||||
descendent.classList.remove('ellipsis')
|
||||
descendent.classList.add(_s.noSelect, _s.text, _s.inherit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -89,8 +104,8 @@ class StatusContent extends ImmutablePureComponent {
|
||||
|
||||
onMentionClick = (mention, e) => {
|
||||
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
this.context.router.history.push(`/${mention.get('acct')}`)
|
||||
// e.preventDefault()
|
||||
// this.context.router.history.push(`/${mention.get('acct')}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ const COLORS = {
|
||||
error: 'error',
|
||||
white: 'white',
|
||||
inherit: 'inherit',
|
||||
pro: 'pro',
|
||||
}
|
||||
|
||||
const SIZES = {
|
||||
@@ -73,6 +74,7 @@ export default class Text extends PureComponent {
|
||||
colorSecondary: color === COLORS.secondary,
|
||||
colorBrand: color === COLORS.brand,
|
||||
colorWhite: color === COLORS.white,
|
||||
colorGabPro: color === COLORS.pro,
|
||||
inherit: color === COLORS.inherit,
|
||||
|
||||
fontSize19PX: size === SIZES.large,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { me } from '../initial_state'
|
||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||
import Avatar from './avatar'
|
||||
import Block from './block'
|
||||
import Heading from './heading'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
const messages = defineMessages({
|
||||
createPost: { id: 'column_header.create_post', defaultMessage: 'Create Post' },
|
||||
})
|
||||
@@ -57,12 +55,15 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||
return (
|
||||
<section className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Block>
|
||||
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2].join(' ')}>
|
||||
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2, _s.alignItemsCenter, _s.flexRow].join(' ')}>
|
||||
<div className={_s.mr10}>
|
||||
<Avatar account={account} size='20' />
|
||||
</div>
|
||||
<Heading size='h5'>
|
||||
{intl.formatMessage(messages.createPost)}
|
||||
</Heading>
|
||||
</div>
|
||||
<div className={[_s.default, _s.flexRow, _s.px15, _s.py15].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.px15, _s.pt15, _s.pb10].join(' ')}>
|
||||
<ComposeFormContainer {...rest} />
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
@@ -210,7 +210,7 @@ class Video extends PureComponent {
|
||||
const y = 1 - ((e.clientY - rect.top) / this.volHeight)
|
||||
|
||||
if (!isNaN(y)) {
|
||||
var slideamt = y
|
||||
const slideamt = y
|
||||
if (y > 1) {
|
||||
slideamt = 1
|
||||
} else if (y < 0) {
|
||||
|
||||
Reference in New Issue
Block a user