From 2e93f87c9fd42f382d428e2d3902deb2b125c5fb Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 1 Feb 2019 16:15:44 +0100 Subject: [Glitch] Replace unlock-alt icon with unlock Port 6513f6c953cdaad9118ea24a21f22fd2978bed28 to glitch-soc --- app/javascript/flavours/glitch/components/account.js | 2 +- app/javascript/flavours/glitch/components/domain.js | 2 +- app/javascript/flavours/glitch/components/status_visibility_icon.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js index 072c601e0..4fcafc509 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.js @@ -85,7 +85,7 @@ export default class Account extends ImmutablePureComponent { if (requested) { buttons = ; } else if (blocking) { - buttons = ; + buttons = ; } else if (muting) { let hidingNotificationsButton; if (account.getIn(['relationship', 'muting_notifications'])) { diff --git a/app/javascript/flavours/glitch/components/domain.js b/app/javascript/flavours/glitch/components/domain.js index f657cb8d2..74174f83d 100644 --- a/app/javascript/flavours/glitch/components/domain.js +++ b/app/javascript/flavours/glitch/components/domain.js @@ -32,7 +32,7 @@ export default class Account extends ImmutablePureComponent {
- +
diff --git a/app/javascript/flavours/glitch/components/status_visibility_icon.js b/app/javascript/flavours/glitch/components/status_visibility_icon.js index 017b69cbb..5e7b8ed00 100644 --- a/app/javascript/flavours/glitch/components/status_visibility_icon.js +++ b/app/javascript/flavours/glitch/components/status_visibility_icon.js @@ -25,7 +25,7 @@ export default class VisibilityIcon extends ImmutablePureComponent { const visibilityClass = { public: 'globe', - unlisted: 'unlock-alt', + unlisted: 'unlock', private: 'lock', direct: 'envelope', }[visibility]; -- cgit From 1a70fca168bec82e3521c2039bbdecc256f328af Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 6 Feb 2019 15:11:46 +0100 Subject: Fix CW unfolding not triggering re-layout in public hashtag page --- app/javascript/flavours/glitch/components/status_content.js | 2 ++ .../flavours/glitch/features/status/components/detailed_status.js | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status_content.js b/app/javascript/flavours/glitch/components/status_content.js index 6542df65b..c60d63f9a 100644 --- a/app/javascript/flavours/glitch/components/status_content.js +++ b/app/javascript/flavours/glitch/components/status_content.js @@ -17,6 +17,7 @@ export default class StatusContent extends React.PureComponent { mediaIcon: PropTypes.string, parseClick: PropTypes.func, disabled: PropTypes.bool, + onUpdate: PropTypes.func, }; state = { @@ -62,6 +63,7 @@ export default class StatusContent extends React.PureComponent { componentDidUpdate () { this._updateStatusLinks(); + if (this.props.onUpdate) this.props.onUpdate(); } onLinkClick = (e) => { diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js index a114e2158..8f49a9a30 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js @@ -79,6 +79,10 @@ export default class DetailedStatus extends ImmutablePureComponent { this._measureHeight(prevState.height !== this.state.height); } + handleChildUpdate = () => { + this._measureHeight(); + } + handleModalLink = e => { e.preventDefault(); @@ -218,6 +222,7 @@ export default class DetailedStatus extends ImmutablePureComponent { collapsed={false} onExpandedToggle={onToggleHidden} parseClick={this.parseClick} + onUpdate={this.handleChildUpdate} />
-- cgit From 405ef5ad3763ebf948dff61fff8af59a3937a9f9 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 6 Feb 2019 18:59:28 +0100 Subject: Hide items rendered out-of-frame (once they have been rendered at least once) --- .../flavours/glitch/components/intersection_observer_article.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/intersection_observer_article.js b/app/javascript/flavours/glitch/components/intersection_observer_article.js index 6eeca5598..03d8f17c6 100644 --- a/app/javascript/flavours/glitch/components/intersection_observer_article.js +++ b/app/javascript/flavours/glitch/components/intersection_observer_article.js @@ -63,7 +63,7 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent } updateStateAfterIntersection = (prevState) => { - if (prevState.isIntersecting && !this.entry.isIntersecting) { + if (prevState.isIntersecting !== false && !this.entry.isIntersecting) { scheduleIdleTask(this.hideIfNotIntersecting); } return { @@ -109,7 +109,7 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent ref={this.handleRef} aria-posinset={index + 1} aria-setsize={listLength} - style={{ height: `${this.height || cachedHeight}px`, opacity: 0, overflow: 'hidden' }} + style={{ height: `${this.height || cachedHeight || 150}px`, opacity: 0, overflow: 'hidden' }} data-id={id} tabIndex='0' > -- cgit From e49e54a5ffb3c5304a42c12be9dba6cc47384250 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 6 Feb 2019 19:48:28 +0100 Subject: Cleanup redundant markup for hidden statuses --- app/javascript/flavours/glitch/components/status.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 9ff53485e..80cd0f42e 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -384,15 +384,7 @@ export default class Status extends ImmutablePureComponent { if (hidden) { return ( -
+
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} {' '} {status.get('content')} -- cgit From 68f3d003d6e841c864330fd5e7bcecadcc9b9178 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 6 Feb 2019 20:04:39 +0100 Subject: Refactor intersection observer article code --- .../components/intersection_observer_article.js | 27 +++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/intersection_observer_article.js b/app/javascript/flavours/glitch/components/intersection_observer_article.js index 03d8f17c6..900c98638 100644 --- a/app/javascript/flavours/glitch/components/intersection_observer_article.js +++ b/app/javascript/flavours/glitch/components/intersection_observer_article.js @@ -103,24 +103,23 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent const { children, id, index, listLength, cachedHeight } = this.props; const { isIntersecting, isHidden } = this.state; + const style = {}; + if (!isIntersecting && (isHidden || cachedHeight)) { - return ( -
- {children && React.cloneElement(children, { hidden: true })} -
- ); + style.height = `${this.height || cachedHeight || 150}px`; + style.opacity = 0; + style.overflow = 'hidden'; } return ( -
- {children && React.cloneElement(children, { hidden: false })} +
+ {children && React.cloneElement(children, { hidden: !isIntersecting && (isHidden || cachedHeight) })}
); } -- cgit From 049c9a3b9711ed203855d18a9a549e65e164ec59 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 9 Feb 2019 20:54:11 +0100 Subject: Avoid two-step rendering of statuses as much as possible Cache width shared by Video player, MediaGallery and Cards at the ScrollableList level, pass it down through StatusList and Notifications. --- app/javascript/flavours/glitch/components/media_gallery.js | 10 ++++++++-- app/javascript/flavours/glitch/components/scrollable_list.js | 12 +++++++++++- app/javascript/flavours/glitch/components/status.js | 8 ++++++++ .../glitch/features/notifications/components/notification.js | 12 ++++++++++++ .../flavours/glitch/features/status/components/card.js | 7 +++++-- app/javascript/flavours/glitch/features/video/index.js | 5 ++++- 6 files changed, 48 insertions(+), 6 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index d0226bbbb..1fa25ee4e 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -224,6 +224,8 @@ export default class MediaGallery extends React.PureComponent { size: PropTypes.object, onOpenMedia: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + defaultWidth: PropTypes.number, + cacheWidth: PropTypes.func, }; static defaultProps = { @@ -232,6 +234,7 @@ export default class MediaGallery extends React.PureComponent { state = { visible: this.props.revealed === undefined ? (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all') : this.props.revealed, + width: this.props.defaultWidth, }; componentWillReceiveProps (nextProps) { @@ -259,6 +262,7 @@ export default class MediaGallery extends React.PureComponent { handleRef = (node) => { this.node = node; if (node && node.offsetWidth && node.offsetWidth != this.state.width) { + if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth); this.setState({ width: node.offsetWidth, }); @@ -271,10 +275,12 @@ export default class MediaGallery extends React.PureComponent { } render () { - const { media, intl, sensitive, letterbox, fullwidth } = this.props; - const { width, visible } = this.state; + const { media, intl, sensitive, letterbox, fullwidth, defaultWidth } = this.props; + const { visible } = this.state; const size = media.take(4).size; + const width = this.state.width || defaultWidth; + let children; const style = {}; diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 7cd0774a9..2e7c9fd6e 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -40,6 +40,7 @@ export default class ScrollableList extends PureComponent { state = { fullscreen: null, + cachedMediaWidth: 300, }; intersectionObserverWrapper = new IntersectionObserverWrapper(); @@ -141,6 +142,10 @@ export default class ScrollableList extends PureComponent { this.setScrollTop(newScrollTop); } + cacheMediaWidth = (width) => { + if (width && this.state.cachedMediaWidth != width) this.setState({ cachedMediaWidth: width }); + } + getSnapshotBeforeUpdate (prevProps, prevState) { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && @@ -252,7 +257,12 @@ export default class ScrollableList extends PureComponent { intersectionObserverWrapper={this.intersectionObserverWrapper} saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null} > - {React.cloneElement(child, {getScrollPosition: this.getScrollPosition, updateScrollBottom: this.updateScrollBottom})} + {React.cloneElement(child, { + getScrollPosition: this.getScrollPosition, + updateScrollBottom: this.updateScrollBottom, + cachedMediaWidth: this.state.cachedMediaWidth, + cacheMediaWidth: this.cacheMediaWidth, + })} ))} diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 80cd0f42e..68788451b 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -72,6 +72,8 @@ export default class Status extends ImmutablePureComponent { updateScrollBottom: PropTypes.func, expanded: PropTypes.bool, intl: PropTypes.object.isRequired, + cacheMediaWidth: PropTypes.func, + cachedMediaWidth: PropTypes.number, }; state = { @@ -445,6 +447,8 @@ export default class Status extends ImmutablePureComponent { fullwidth={settings.getIn(['media', 'fullwidth'])} preventPlayback={isCollapsed || !isExpanded} onOpenVideo={this.handleOpenVideo} + width={this.props.cachedMediaWidth} + cacheWidth={this.props.cacheMediaWidth} />)} ); @@ -460,6 +464,8 @@ export default class Status extends ImmutablePureComponent { fullwidth={settings.getIn(['media', 'fullwidth'])} hidden={isCollapsed || !isExpanded} onOpenMedia={this.props.onOpenMedia} + cacheWidth={this.props.cacheMediaWidth} + defaultWidth={this.props.cachedMediaWidth} /> )} @@ -476,6 +482,8 @@ export default class Status extends ImmutablePureComponent { onOpenMedia={this.props.onOpenMedia} card={status.get('card')} compact + cacheWidth={this.props.cacheMediaWidth} + defaultWidth={this.props.cachedMediaWidth} /> ); mediaIcon = 'link'; diff --git a/app/javascript/flavours/glitch/features/notifications/components/notification.js b/app/javascript/flavours/glitch/features/notifications/components/notification.js index 21c55accc..daafe3507 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/notification.js +++ b/app/javascript/flavours/glitch/features/notifications/components/notification.js @@ -18,6 +18,9 @@ export default class Notification extends ImmutablePureComponent { onMention: PropTypes.func.isRequired, getScrollPosition: PropTypes.func, updateScrollBottom: PropTypes.func, + cacheMediaWidth: PropTypes.func, + cachedMediaWidth: PropTypes.number, + onUnmount: PropTypes.func, }; render () { @@ -57,6 +60,9 @@ export default class Notification extends ImmutablePureComponent { contextType='notifications' getScrollPosition={getScrollPosition} updateScrollBottom={updateScrollBottom} + cachedMediaWidth={this.props.cachedMediaWidth} + cacheMediaWidth={this.props.cacheMediaWidth} + onUnmount={this.props.onUnmount} withDismiss /> ); @@ -75,6 +81,9 @@ export default class Notification extends ImmutablePureComponent { onMention={onMention} getScrollPosition={getScrollPosition} updateScrollBottom={updateScrollBottom} + cachedMediaWidth={this.props.cachedMediaWidth} + cacheMediaWidth={this.props.cacheMediaWidth} + onUnmount={this.props.onUnmount} withDismiss /> ); @@ -93,6 +102,9 @@ export default class Notification extends ImmutablePureComponent { onMention={onMention} getScrollPosition={getScrollPosition} updateScrollBottom={updateScrollBottom} + cachedMediaWidth={this.props.cachedMediaWidth} + cacheMediaWidth={this.props.cacheMediaWidth} + onUnmount={this.props.onUnmount} withDismiss /> ); diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index 1e1604d5c..e405a5ef0 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -60,6 +60,8 @@ export default class Card extends React.PureComponent { maxDescription: PropTypes.number, onOpenMedia: PropTypes.func.isRequired, compact: PropTypes.bool, + defaultWidth: PropTypes.number, + cacheWidth: PropTypes.func, }; static defaultProps = { @@ -68,7 +70,7 @@ export default class Card extends React.PureComponent { }; state = { - width: 280, + width: this.props.defaultWidth || 280, embedded: false, }; @@ -111,6 +113,7 @@ export default class Card extends React.PureComponent { setRef = c => { if (c) { + if (this.props.cacheWidth) this.props.cacheWidth(c.offsetWidth); this.setState({ width: c.offsetWidth }); } } @@ -133,7 +136,7 @@ export default class Card extends React.PureComponent { } render () { - const { card, maxDescription, compact } = this.props; + const { card, maxDescription, compact, defaultWidth } = this.props; const { width, embedded } = this.state; if (card === null) { diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index d8e8791a7..a6f651db6 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -103,6 +103,7 @@ export default class Video extends React.PureComponent { inline: PropTypes.bool, preventPlayback: PropTypes.bool, intl: PropTypes.object.isRequired, + cacheWidth: PropTypes.func, }; state = { @@ -111,7 +112,7 @@ export default class Video extends React.PureComponent { volume: 0.5, paused: true, dragging: false, - containerWidth: false, + containerWidth: this.props.width, fullscreen: false, hovered: false, muted: false, @@ -131,6 +132,7 @@ export default class Video extends React.PureComponent { this.player = c; if (c && c.offsetWidth && c.offsetWidth != this.state.containerWidth) { + if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth); this.setState({ containerWidth: c.offsetWidth, }); @@ -275,6 +277,7 @@ export default class Video extends React.PureComponent { componentDidUpdate (prevProps) { if (this.player && this.player.offsetWidth && this.player.offsetWidth != this.state.containerWidth && !this.state.fullscreen) { + if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth); this.setState({ containerWidth: this.player.offsetWidth, }); -- cgit From 0b91322762e845acc76966da448eeccd1ad78047 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 9 Feb 2019 21:24:43 +0100 Subject: Adjust scroll if previewCard appeared --- app/javascript/flavours/glitch/components/status.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 68788451b..1a5cb4a97 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -216,6 +216,8 @@ export default class Status extends ImmutablePureComponent { // Hack to fix timeline jumps on second rendering when auto-collapsing this.setState({ autoCollapsed: true }); } + + this.didShowCard = !this.props.muted && !this.props.hidden && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); } getSnapshotBeforeUpdate (prevProps, prevState) { @@ -228,8 +230,10 @@ export default class Status extends ImmutablePureComponent { // Hack to fix timeline jumps on second rendering when auto-collapsing componentDidUpdate (prevProps, prevState, snapshot) { - if (this.state.autoCollapsed) { - this.setState({ autoCollapsed: false }); + const doShowCard = !this.props.muted && !this.props.hidden && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); + if (this.state.autoCollapsed || (doShowCard && !this.didShowCard)) { + if (doShowCard) this.didShowCard = true; + if (this.state.autoCollapsed) this.setState({ autoCollapsed: false }); if (snapshot !== null && this.props.updateScrollBottom) { if (this.node.offsetTop < snapshot.top) { this.props.updateScrollBottom(snapshot.height - snapshot.top); -- cgit From dfe1d548a58154c988b98cab313496292bdc62e2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 9 Feb 2019 22:08:57 +0100 Subject: Adjust scroll when statuses above the current scroll position are deleted --- app/javascript/flavours/glitch/components/status.js | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 1a5cb4a97..9d987dc9c 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -242,6 +242,15 @@ export default class Status extends ImmutablePureComponent { } } + componentWillUnmount() { + if (this.node && this.props.getScrollPosition) { + const position = this.props.getScrollPosition(); + if (position !== null && this.node.offsetTop < position.top) { + requestAnimationFrame(() => { this.props.updateScrollBottom(position.height - position.top); }); + } + } + } + // `setCollapsed()` sets the value of `isCollapsed` in our state, that is, // whether the toot is collapsed or not. -- cgit From 7c0728c7764e1e851eb0174b37767029c1061f2d Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 9 Feb 2019 22:32:09 +0100 Subject: Minor fix to timeline jump avoiding behavior --- app/javascript/flavours/glitch/components/scrollable_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 2e7c9fd6e..462185bbc 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -129,7 +129,7 @@ export default class ScrollableList extends PureComponent { } getScrollPosition = () => { - if (this.node && this.node.scrollTop > 0) { + if (this.node && (this.node.scrollTop > 0 || this.mouseMovedRecently)) { return {height: this.node.scrollHeight, top: this.node.scrollTop}; } else { return null; -- cgit From b89e003c4d049d64d2d4015357b8b931370bc5f0 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 10 Feb 2019 11:50:31 +0100 Subject: Handle deletion of filtered toots --- app/javascript/flavours/glitch/components/status.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 9d987dc9c..51fee0eec 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -415,7 +415,7 @@ export default class Status extends ImmutablePureComponent { return ( -
+
-- cgit From 614ea184bb911a5b86804e05350997bafc605580 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 13 Feb 2019 07:29:57 +0100 Subject: [Glitch] Add "copy link" item to status action bars Port 3cfadd875cc91b3fb893681ed7c2ef86148b3f85 to glitch-soc --- .../glitch/components/status_action_bar.js | 22 ++++++++++++++++++++++ .../features/status/components/action_bar.js | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 16abcab4e..7fb84bd1e 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -34,6 +34,7 @@ const messages = defineMessages({ embed: { id: 'status.embed', defaultMessage: 'Embed' }, admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, + copy: { id: 'status.copy', defaultMessage: 'Copy link to status' }, }); const obfuscatedCount = count => { @@ -148,6 +149,25 @@ export default class StatusActionBar extends ImmutablePureComponent { this.props.onMuteConversation(this.props.status); } + handleCopy = () => { + const url = this.props.status.get('url'); + const textarea = document.createElement('textarea'); + + textarea.textContent = url; + textarea.style.position = 'fixed'; + + document.body.appendChild(textarea); + + try { + textarea.select(); + document.execCommand('copy'); + } catch (e) { + + } finally { + document.body.removeChild(textarea); + } + } + render () { const { status, intl, withDismiss, showReplyCount } = this.props; @@ -165,6 +185,7 @@ export default class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen }); if (publicStatus) { + menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy }); menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); } @@ -189,6 +210,7 @@ export default class StatusActionBar extends ImmutablePureComponent { 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 && (accountAdminLink || statusAdminLink)) { menu.push(null); if (accountAdminLink !== undefined) { diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index be82bca5b..66cc10d78 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -29,6 +29,7 @@ const messages = defineMessages({ embed: { id: 'status.embed', defaultMessage: 'Embed' }, admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, + copy: { id: 'status.copy', defaultMessage: 'Copy link to status' }, }); @injectIntl @@ -119,6 +120,25 @@ export default class ActionBar extends React.PureComponent { this.props.onEmbed(this.props.status); } + handleCopy = () => { + const url = this.props.status.get('url'); + const textarea = document.createElement('textarea'); + + textarea.textContent = url; + textarea.style.position = 'fixed'; + + document.body.appendChild(textarea); + + try { + textarea.select(); + document.execCommand('copy'); + } catch (e) { + + } finally { + document.body.removeChild(textarea); + } + } + render () { const { status, intl } = this.props; @@ -128,6 +148,7 @@ export default class ActionBar extends React.PureComponent { let menu = []; if (publicStatus) { + menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy }); menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); menu.push(null); } -- cgit From 2769b5446681898e8332cb505f499dac2a6e5717 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 15 Feb 2019 17:13:32 +0100 Subject: [Glitch] Fix occasional crash in detailed toot view Port f9a338b473e181dd725f9185d09394624088efac to glitch-soc --- app/javascript/flavours/glitch/components/status.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 51fee0eec..349f9c6cc 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -217,7 +217,7 @@ export default class Status extends ImmutablePureComponent { this.setState({ autoCollapsed: true }); } - this.didShowCard = !this.props.muted && !this.props.hidden && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); + this.didShowCard = !this.props.muted && !this.props.hidden && this.props.status && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); } getSnapshotBeforeUpdate (prevProps, prevState) { @@ -230,7 +230,7 @@ export default class Status extends ImmutablePureComponent { // Hack to fix timeline jumps on second rendering when auto-collapsing componentDidUpdate (prevProps, prevState, snapshot) { - const doShowCard = !this.props.muted && !this.props.hidden && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); + const doShowCard = !this.props.muted && !this.props.hidden && this.props.status && this.props.status.get('card') && this.props.settings.get('inline_preview_cards'); if (this.state.autoCollapsed || (doShowCard && !this.didShowCard)) { if (doShowCard) this.didShowCard = true; if (this.state.autoCollapsed) this.setState({ autoCollapsed: false }); -- cgit From 91c9cb602215a8feb2e171fadd580dfe4dd75830 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 17 Feb 2019 12:39:44 +0100 Subject: [Glitch] Change buttons on timeline preview to open the interaction dialog Port 71e28ba39993d6eb3c5966e20214214c9d81b173 to glitch-soc --- .../glitch/components/status_action_bar.js | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 7fb84bd1e..1d3130604 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -83,7 +83,11 @@ export default class StatusActionBar extends ImmutablePureComponent { ] handleReplyClick = () => { - this.props.onReply(this.props.status, this.context.router.history); + if (me) { + this.props.onReply(this.props.status, this.context.router.history); + } else { + this._openInteractionDialog('reply'); + } } handleShareClick = () => { @@ -94,17 +98,29 @@ export default class StatusActionBar extends ImmutablePureComponent { } handleFavouriteClick = (e) => { - this.props.onFavourite(this.props.status, e); + if (me) { + this.props.onFavourite(this.props.status, e); + } else { + this._openInteractionDialog('favourite'); + } } handleBookmarkClick = (e) => { this.props.onBookmark(this.props.status, e); } - handleReblogClick = (e) => { - this.props.onReblog(this.props.status, e); + handleReblogClick = e => { + if (me) { + this.props.onReblog(this.props.status, e); + } else { + this._openInteractionDialog('reblog'); + } } + _openInteractionDialog = type => { + window.open(`/interact/${this.props.status.get('id')}?type=${type}`, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); + } + handleDeleteClick = () => { this.props.onDelete(this.props.status, this.context.router.history); } @@ -174,7 +190,7 @@ export default class StatusActionBar extends ImmutablePureComponent { const mutingConversation = status.get('muted'); const anonymousAccess = !me; const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); - const reblogDisabled = anonymousAccess || (status.get('visibility') === 'direct' || (status.get('visibility') === 'private' && me !== status.getIn(['account', 'id']))); + const reblogDisabled = status.get('visibility') === 'direct' || (status.get('visibility') === 'private' && me !== status.getIn(['account', 'id'])); const reblogMessage = status.get('visibility') === 'private' ? messages.reblog_private : messages.reblog; let menu = []; @@ -243,7 +259,6 @@ export default class StatusActionBar extends ImmutablePureComponent { let replyButton = ( {replyButton} - + {shareButton} -- cgit From d82de360c13894746d3974d11c9505c8937ebdee Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 21 Feb 2019 21:13:12 +0100 Subject: Fix non-numeric account identifiers leading to /web/accounts/NaN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not sure what purpose these “+” served?! --- app/javascript/flavours/glitch/components/status_header.js | 2 +- app/javascript/flavours/glitch/components/status_prepend.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/status_header.js b/app/javascript/flavours/glitch/components/status_header.js index 65458e3f0..f9321904c 100644 --- a/app/javascript/flavours/glitch/components/status_header.js +++ b/app/javascript/flavours/glitch/components/status_header.js @@ -19,7 +19,7 @@ export default class StatusHeader extends React.PureComponent { // Handles clicks on account name/image handleAccountClick = (e) => { const { status, parseClick } = this.props; - parseClick(e, `/accounts/${+status.getIn(['account', 'id'])}`); + parseClick(e, `/accounts/${status.getIn(['account', 'id'])}`); } // Rendering. diff --git a/app/javascript/flavours/glitch/components/status_prepend.js b/app/javascript/flavours/glitch/components/status_prepend.js index f4ef83135..4e329f546 100644 --- a/app/javascript/flavours/glitch/components/status_prepend.js +++ b/app/javascript/flavours/glitch/components/status_prepend.js @@ -15,7 +15,7 @@ export default class StatusPrepend extends React.PureComponent { handleClick = (e) => { const { account, parseClick } = this.props; - parseClick(e, `/accounts/${+account.get('id')}`); + parseClick(e, `/accounts/${account.get('id')}`); } Message = () => { -- cgit