[Glitch] Fix error when visiting non-public hashtag timelines

Port f01e80bed3 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
diondiondion
2025-11-20 11:08:00 +01:00
committed by Claire
parent 8e70c54d0e
commit aec23fd4a2
3 changed files with 35 additions and 15 deletions

View File

@@ -197,13 +197,16 @@ export const HashtagHeader: React.FC<{
/> />
)} )}
{signedIn && (
<Button <Button
onClick={handleFollow} onClick={handleFollow}
text={intl.formatMessage( text={intl.formatMessage(
tag.following ? messages.unfollowHashtag : messages.followHashtag, tag.following
? messages.unfollowHashtag
: messages.followHashtag,
)} )}
disabled={!signedIn}
/> />
)}
</div> </div>
</div> </div>

View File

@@ -16,7 +16,7 @@ import { expandHashtagTimeline, clearTimeline } from 'flavours/glitch/actions/ti
import Column from 'flavours/glitch/components/column'; import Column from 'flavours/glitch/components/column';
import ColumnHeader from 'flavours/glitch/components/column_header'; import ColumnHeader from 'flavours/glitch/components/column_header';
import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context';
import { remoteTopicFeedAccess, me } from 'flavours/glitch/initial_state'; import { remoteTopicFeedAccess, me, localTopicFeedAccess } from 'flavours/glitch/initial_state';
import StatusListContainer from '../ui/containers/status_list_container'; import StatusListContainer from '../ui/containers/status_list_container';
@@ -25,9 +25,11 @@ import ColumnSettingsContainer from './containers/column_settings_container';
const mapStateToProps = (state, props) => { const mapStateToProps = (state, props) => {
const local = props.params.local || (!me && remoteTopicFeedAccess !== 'public'); const local = props.params.local || (!me && remoteTopicFeedAccess !== 'public');
const hasFeedAccess = !!me || localTopicFeedAccess === 'public';
return ({ return ({
local, local,
hasFeedAccess,
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${local ? ':local' : ''}`, 'unread']) > 0, hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${local ? ':local' : ''}`, 'unread']) > 0,
}); });
}; };
@@ -127,12 +129,14 @@ class HashtagTimeline extends PureComponent {
} }
_load() { _load() {
const { dispatch, local } = this.props; const { dispatch, local, hasFeedAccess } = this.props;
const { id, tags } = this.props.params; const { id, tags } = this.props.params;
if (hasFeedAccess) {
this._subscribe(dispatch, id, tags, local); this._subscribe(dispatch, id, tags, local);
dispatch(expandHashtagTimeline(id, { tags, local })); dispatch(expandHashtagTimeline(id, { tags, local }));
} }
}
componentDidMount () { componentDidMount () {
this._load(); this._load();
@@ -164,7 +168,7 @@ class HashtagTimeline extends PureComponent {
}; };
render () { render () {
const { hasUnread, columnId, multiColumn, local } = this.props; const { hasUnread, columnId, multiColumn, local, hasFeedAccess } = this.props;
const { id } = this.props.params; const { id } = this.props.params;
const pinned = !!columnId; const pinned = !!columnId;
@@ -192,7 +196,20 @@ class HashtagTimeline extends PureComponent {
scrollKey={`hashtag_timeline-${columnId}`} scrollKey={`hashtag_timeline-${columnId}`}
timelineId={`hashtag:${id}${local ? ':local' : ''}`} timelineId={`hashtag:${id}${local ? ':local' : ''}`}
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />} initialLoadingState={hasFeedAccess}
emptyMessage={
hasFeedAccess ? (
<FormattedMessage
id='empty_column.hashtag'
defaultMessage='There is nothing in this hashtag yet.'
/>
) : (
<FormattedMessage
id='error.no_hashtag_feed_access'
defaultMessage='Join or log in to view and follow this hashtag.'
/>
)
}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
/> />

View File

@@ -63,10 +63,10 @@ const makeMapStateToProps = () => {
const getStatusIds = makeGetStatusIds(); const getStatusIds = makeGetStatusIds();
const getPendingStatusIds = makeGetStatusIds(true); const getPendingStatusIds = makeGetStatusIds(true);
const mapStateToProps = (state, { timelineId, regex }) => ({ const mapStateToProps = (state, { timelineId, regex, initialLoadingState = true }) => ({
statusIds: getStatusIds(state, { type: timelineId, regex }), statusIds: getStatusIds(state, { type: timelineId, regex }),
lastId: state.getIn(['timelines', timelineId, 'items'])?.last(), lastId: state.getIn(['timelines', timelineId, 'items'])?.last(),
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true), isLoading: state.getIn(['timelines', timelineId, 'isLoading'], initialLoadingState),
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
hasMore: state.getIn(['timelines', timelineId, 'hasMore']), hasMore: state.getIn(['timelines', timelineId, 'hasMore']),
numPending: getPendingStatusIds(state, { type: timelineId }).size, numPending: getPendingStatusIds(state, { type: timelineId }).size,