Skip to content

Commit

Permalink
Merge pull request #2848 from ClearlyClaire/glitch-soc/merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream changes up to 3e91c10
  • Loading branch information
ClearlyClaire authored Sep 17, 2024
2 parents 18209d2 + 6bd86fe commit 486e616
Show file tree
Hide file tree
Showing 82 changed files with 148 additions and 292 deletions.
60 changes: 45 additions & 15 deletions CHANGELOG.md

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions app/javascript/flavours/glitch/actions/markers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { debounce } from 'lodash';

import type { MarkerJSON } from 'flavours/glitch/api_types/markers';
import { getAccessToken } from 'flavours/glitch/initial_state';
import { selectUseGroupedNotifications } from 'flavours/glitch/selectors/settings';
import type { AppDispatch, RootState } from 'flavours/glitch/store';
import { createAppAsyncThunk } from 'flavours/glitch/store/typed_functions';

Expand Down Expand Up @@ -76,12 +75,7 @@ interface MarkerParam {
}

function getLastNotificationId(state: RootState): string | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return selectUseGroupedNotifications(state)
? state.notificationGroups.lastReadId
: // @ts-expect-error state.notifications is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
state.getIn(['notifications', 'lastReadId']);
return state.notificationGroups.lastReadId;
}

const buildPostMarkersParams = (state: RootState) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { selectUseGroupedNotifications } from 'flavours/glitch/selectors/settings';
import { createAppAsyncThunk } from 'flavours/glitch/store';

import { fetchNotifications } from './notification_groups';
import { expandNotifications } from './notifications';

export const initializeNotifications = createAppAsyncThunk(
'notifications/initialize',
(_, { dispatch, getState }) => {
if (selectUseGroupedNotifications(getState()))
void dispatch(fetchNotifications());
else void dispatch(expandNotifications({}));
(_, { dispatch }) => {
void dispatch(fetchNotifications());
},
);
28 changes: 8 additions & 20 deletions app/javascript/flavours/glitch/actions/streaming.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// @ts-check

import { selectUseGroupedNotifications } from 'flavours/glitch/selectors/settings';

import { getLocale } from '../locales';
import { connectStream } from '../stream';

Expand Down Expand Up @@ -105,18 +103,14 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const notificationJSON = JSON.parse(data.payload);
dispatch(updateNotifications(notificationJSON, messages, locale));
// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
dispatch(processNewNotificationForGroups(notificationJSON));
}
dispatch(processNewNotificationForGroups(notificationJSON));
break;
}
case 'notifications_merged':
const state = getState();
if (state.notifications.top || !state.notifications.mounted)
dispatch(expandNotifications({ forceLoad: true, maxId: undefined }));
if (selectUseGroupedNotifications(state)) {
dispatch(refreshStaleNotificationGroups());
}
dispatch(refreshStaleNotificationGroups());
break;
case 'conversation':
// @ts-expect-error
Expand All @@ -141,21 +135,15 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti

/**
* @param {Function} dispatch
* @param {Function} getState
*/
async function refreshHomeTimelineAndNotification(dispatch, getState) {
async function refreshHomeTimelineAndNotification(dispatch) {
await dispatch(expandHomeTimeline({ maxId: undefined }));

// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}
} else {
await dispatch(expandNotifications({}));
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}

await dispatch(fetchAnnouncements());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';

import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context';
import { forceGroupedNotifications } from 'flavours/glitch/initial_state';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'flavours/glitch/permissions';

import ClearColumnButton from './clear_column_button';
Expand Down Expand Up @@ -36,7 +35,6 @@ class ColumnSettings extends PureComponent {
const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission } = this.props;

const unreadMarkersShowStr = <FormattedMessage id='notifications.column_settings.unread_notifications.highlight' defaultMessage='Highlight unread notifications' />;
const groupingShowStr = <FormattedMessage id='notifications.column_settings.beta.grouping' defaultMessage='Group notifications' />;
const filterBarShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show_bar' defaultMessage='Show filter bar' />;
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
Expand Down Expand Up @@ -79,18 +77,6 @@ class ColumnSettings extends PureComponent {
</div>
</section>

{!forceGroupedNotifications && (
<section role='group' aria-labelledby='notifications-beta'>
<h3 id='notifications-beta'>
<FormattedMessage id='notifications.column_settings.beta.category' defaultMessage='Experimental features' />
</h3>

<div className='column-settings__row'>
<SettingToggle id='unread-notification-markers' prefix='notifications' settings={settings} settingPath={['groupingBeta']} onChange={onChange} label={groupingShowStr} />
</div>
</section>
)}

<section role='group' aria-labelledby='notifications-unread-markers'>
<h3 id='notifications-unread-markers'>
<FormattedMessage id='notifications.column_settings.unread_notifications.category' defaultMessage='Unread notifications' />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import Notifications from 'flavours/glitch/features/notifications';
import Notifications_v2 from 'flavours/glitch/features/notifications_v2';
import { selectUseGroupedNotifications } from 'flavours/glitch/selectors/settings';
import { useAppSelector } from 'flavours/glitch/store';

export const NotificationsWrapper = (props) => {
const optedInGroupedNotifications = useAppSelector(selectUseGroupedNotifications);

return (
optedInGroupedNotifications ? <Notifications_v2 {...props} /> : <Notifications {...props} />
<Notifications_v2 {...props} />
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export default class ColumnsArea extends ImmutablePureComponent {
openSettings: PropTypes.func,
};

// Corresponds to (max-width: $no-gap-breakpoint + 285px - 1px) in SCSS
mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1174px)');
// Corresponds to (max-width: $no-gap-breakpoint - 1px) in SCSS
mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1206px)');

state = {
renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import { timelinePreview, trendsEnabled } from 'flavours/glitch/initial_state';
import { transientSingleColumn } from 'flavours/glitch/is_mobile';
import { canManageReports, canViewAdminDashboard } from 'flavours/glitch/permissions';
import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications';
import { selectUseGroupedNotifications } from 'flavours/glitch/selectors/settings';
import { preferencesLink } from 'flavours/glitch/utils/backend_links';

import ColumnLink from './column_link';
Expand Down Expand Up @@ -66,19 +65,17 @@ const messages = defineMessages({
});

const NotificationsLink = () => {
const optedInGroupedNotifications = useSelector(selectUseGroupedNotifications);
const count = useSelector(state => state.getIn(['local_settings', 'notifications', 'tab_badge']) ? state.getIn(['notifications', 'unread']) : 0);
const count = useSelector(selectUnreadNotificationGroupsCount);
const showCount = useSelector(state => state.getIn(['local_settings', 'notifications', 'tab_badge']));
const intl = useIntl();

const newCount = useSelector(selectUnreadNotificationGroupsCount);

return (
<ColumnLink
key='notifications'
transparent
to='/notifications'
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={optedInGroupedNotifications ? newCount : count} className='column-link__icon' />}
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={optedInGroupedNotifications ? newCount : count} className='column-link__icon' />}
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={showCount ? count : 0} className='column-link__icon' />}
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={showCount ? count : 0} className='column-link__icon' />}
text={intl.formatMessage(messages.notifications)}
/>
);
Expand Down
2 changes: 0 additions & 2 deletions app/javascript/flavours/glitch/initial_state.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
* @property {boolean=} use_pending_items
* @property {string} version
* @property {string} sso_redirect
* @property {boolean} force_grouped_notifications
* @property {string} status_page_url
* @property {boolean} system_emoji_font
* @property {string} default_content_type
Expand Down Expand Up @@ -138,7 +137,6 @@ export const languages = initialState?.languages;
export const criticalUpdatesPending = initialState?.critical_updates_pending;
export const statusPageUrl = getMeta('status_page_url');
export const sso_redirect = getMeta('sso_redirect');
export const forceGroupedNotifications = getMeta('force_grouped_notifications');

// Glitch-soc-specific settings
export const maxFeedHashtags = (initialState && initialState.max_feed_hashtags) || 4;
Expand Down
35 changes: 20 additions & 15 deletions app/javascript/flavours/glitch/selectors/settings.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { forceGroupedNotifications } from 'flavours/glitch/initial_state';
import { createSelector } from '@reduxjs/toolkit';

import type { RootState } from 'flavours/glitch/store';

/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
// state.settings is not yet typed, so we disable some ESLint checks for those selectors
export const selectSettingsNotificationsShows = (state: RootState) =>
state.settings.getIn(['notifications', 'shows']).toJS() as Record<
string,
boolean
>;

export const selectSettingsNotificationsExcludedTypes = (state: RootState) =>
Object.entries(selectSettingsNotificationsShows(state))
.filter(([_type, enabled]) => !enabled)
.map(([type, _enabled]) => type);
export const selectSettingsNotificationsShows = createSelector(
[
(state) =>
state.settings.getIn(['notifications', 'shows']) as Immutable.Map<
string,
boolean
>,
],
(shows) => shows.toJS() as Record<string, boolean>,
);

export const selectSettingsNotificationsExcludedTypes = createSelector(
[selectSettingsNotificationsShows],
(shows) =>
Object.entries(shows)
.filter(([_type, enabled]) => !enabled)
.map(([type, _enabled]) => type),
);

export const selectSettingsNotificationsQuickFilterShow = (state: RootState) =>
state.settings.getIn(['notifications', 'quickFilter', 'show']) as boolean;
Expand All @@ -26,10 +35,6 @@ export const selectSettingsNotificationsQuickFilterAdvanced = (
) =>
state.settings.getIn(['notifications', 'quickFilter', 'advanced']) as boolean;

export const selectUseGroupedNotifications = (state: RootState) =>
forceGroupedNotifications ||
(state.settings.getIn(['notifications', 'groupingBeta']) as boolean);

export const selectSettingsNotificationsShowUnread = (state: RootState) =>
state.settings.getIn(['notifications', 'showUnread']) as boolean;

Expand Down
2 changes: 1 addition & 1 deletion app/javascript/flavours/glitch/styles/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4108,7 +4108,7 @@ input.glitch-setting-text {
}

&__wrapper {
background: $white;
background: $ui-base-color;
border: 1px solid var(--background-border-color);
margin-bottom: 10px;
border-radius: 4px;
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/flavours/glitch/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ $media-modal-media-max-width: 100%;
// put margins on top and bottom of image to avoid the screen covered by image.
$media-modal-media-max-height: 80%;

$no-gap-breakpoint: 1175px;
$no-gap-breakpoint: 1207px;
$mobile-breakpoint: 630px;

$font-sans-serif: 'mastodon-font-sans-serif' !default;
Expand Down
8 changes: 1 addition & 7 deletions app/javascript/mastodon/actions/markers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { debounce } from 'lodash';

import type { MarkerJSON } from 'mastodon/api_types/markers';
import { getAccessToken } from 'mastodon/initial_state';
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import type { AppDispatch, RootState } from 'mastodon/store';
import { createAppAsyncThunk } from 'mastodon/store/typed_functions';

Expand Down Expand Up @@ -76,12 +75,7 @@ interface MarkerParam {
}

function getLastNotificationId(state: RootState): string | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return selectUseGroupedNotifications(state)
? state.notificationGroups.lastReadId
: // @ts-expect-error state.notifications is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
state.getIn(['notifications', 'lastReadId']);
return state.notificationGroups.lastReadId;
}

const buildPostMarkersParams = (state: RootState) => {
Expand Down
8 changes: 2 additions & 6 deletions app/javascript/mastodon/actions/notifications_migration.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import { createAppAsyncThunk } from 'mastodon/store';

import { fetchNotifications } from './notification_groups';
import { expandNotifications } from './notifications';

export const initializeNotifications = createAppAsyncThunk(
'notifications/initialize',
(_, { dispatch, getState }) => {
if (selectUseGroupedNotifications(getState()))
void dispatch(fetchNotifications());
else void dispatch(expandNotifications({}));
(_, { dispatch }) => {
void dispatch(fetchNotifications());
},
);
28 changes: 8 additions & 20 deletions app/javascript/mastodon/actions/streaming.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// @ts-check

import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';

import { getLocale } from '../locales';
import { connectStream } from '../stream';

Expand Down Expand Up @@ -105,18 +103,14 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const notificationJSON = JSON.parse(data.payload);
dispatch(updateNotifications(notificationJSON, messages, locale));
// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
dispatch(processNewNotificationForGroups(notificationJSON));
}
dispatch(processNewNotificationForGroups(notificationJSON));
break;
}
case 'notifications_merged':
const state = getState();
if (state.notifications.top || !state.notifications.mounted)
dispatch(expandNotifications({ forceLoad: true, maxId: undefined }));
if (selectUseGroupedNotifications(state)) {
dispatch(refreshStaleNotificationGroups());
}
dispatch(refreshStaleNotificationGroups());
break;
case 'conversation':
// @ts-expect-error
Expand All @@ -141,21 +135,15 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti

/**
* @param {Function} dispatch
* @param {Function} getState
*/
async function refreshHomeTimelineAndNotification(dispatch, getState) {
async function refreshHomeTimelineAndNotification(dispatch) {
await dispatch(expandHomeTimeline({ maxId: undefined }));

// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}
} else {
await dispatch(expandNotifications({}));
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}

await dispatch(fetchAnnouncements());
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/mastodon/components/follow_button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ export const FollowButton: React.FC<{
label = <LoadingIndicator />;
} else if (relationship.following && relationship.followed_by) {
label = intl.formatMessage(messages.mutual);
} else if (!relationship.following && relationship.followed_by) {
label = intl.formatMessage(messages.followBack);
} else if (relationship.following || relationship.requested) {
label = intl.formatMessage(messages.unfollow);
} else if (relationship.followed_by) {
label = intl.formatMessage(messages.followBack);
} else {
label = intl.formatMessage(messages.follow);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ const messageForFollowButton = relationship => {

if (relationship.get('following') && relationship.get('followed_by')) {
return messages.mutual;
} else if (!relationship.get('following') && relationship.get('followed_by')) {
return messages.followBack;
} else if (relationship.get('following') || relationship.get('requested')) {
return messages.unfollow;
} else if (relationship.get('followed_by')) {
return messages.followBack;
} else {
return messages.follow;
}
Expand Down
Loading

0 comments on commit 486e616

Please sign in to comment.