Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream changes up to 53c183f899b5382f1eebd72e34a090c30f8eba6a #2817

Merged
merged 17 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d640471
Update eslint (non-major) (#31490)
renovate[bot] Aug 19, 2024
d57ee31
Update devDependencies (non-major) (#31489)
renovate[bot] Aug 19, 2024
9cda8c0
Update dependency use-debounce to v10.0.3 (#31468)
renovate[bot] Aug 19, 2024
c4e0a7d
New Crowdin Translations (automated) (#31463)
github-actions[bot] Aug 19, 2024
3db3e3d
Update dependency postcss-preset-env to v10.0.2 (#31488)
renovate[bot] Aug 19, 2024
31d374e
Update opentelemetry-ruby (non-major) (#31451)
renovate[bot] Aug 19, 2024
71f257d
Disable rule selector in ReportReasonSelector if instance has no rule…
ThisIsMissEm Aug 19, 2024
9905147
Fix Trending Tags pending review having an unstable sort order (#31473)
ThisIsMissEm Aug 19, 2024
40f6631
Fix Husky git hooks not being installed anymore (#31435)
renchap Aug 19, 2024
1e612c5
Refactor some actions to be proper async actions instead of passing a…
ClearlyClaire Aug 19, 2024
d2e4be0
Hopefully fix notifications pagination flaky test (#31494)
ClearlyClaire Aug 19, 2024
d4f135b
Fix in memoriam accounts appearing in follow recommendations (#31474)
wheatear-dev Aug 19, 2024
53c183f
Reload notifications when accepted notifications are merged (streamin…
ClearlyClaire Aug 19, 2024
1760f84
Merge commit '53c183f899b5382f1eebd72e34a090c30f8eba6a' into glitch-s…
ClearlyClaire Aug 19, 2024
a7751d2
[Glitch] Disable rule selector in ReportReasonSelector if instance ha…
ThisIsMissEm Aug 19, 2024
99ffae7
[Glitch] Refactor some actions to be proper async actions instead of …
ClearlyClaire Aug 19, 2024
bfd0111
[Glitch] Reload notifications when accepted notifications are merged …
ClearlyClaire Aug 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -514,17 +514,17 @@ GEM
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rack (~> 0.21)
opentelemetry-instrumentation-action_view (0.7.1)
opentelemetry-instrumentation-action_view (0.7.2)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.1)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_job (0.7.4)
opentelemetry-instrumentation-active_job (0.7.6)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_model_serializers (0.20.2)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_record (0.7.2)
opentelemetry-instrumentation-active_record (0.7.3)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_support (0.6.0)
Expand Down Expand Up @@ -558,7 +558,7 @@ GEM
opentelemetry-instrumentation-rack (0.24.6)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rails (0.31.1)
opentelemetry-instrumentation-rails (0.31.2)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-action_mailer (~> 0.1.0)
opentelemetry-instrumentation-action_pack (~> 0.9.0)
Expand Down
10 changes: 8 additions & 2 deletions app/controllers/api/v1/notifications/requests_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# frozen_string_literal: true

class Api::V1::Notifications::RequestsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: :index
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, except: :index
include Redisable

before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: [:index, :show, :merged?]
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, except: [:index, :show, :merged?]

before_action :require_user!
before_action :set_request, only: [:show, :accept, :dismiss]
Expand All @@ -19,6 +21,10 @@ def index
render json: @requests, each_serializer: REST::NotificationRequestSerializer, relationships: @relationships
end

def merged?
render json: { merged: redis.get("notification_unfilter_jobs:#{current_account.id}").to_i <= 0 }
end

def show
render json: @request, serializer: REST::NotificationRequestSerializer
end
Expand Down
43 changes: 41 additions & 2 deletions app/javascript/flavours/glitch/actions/notification_groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,18 @@ export const processNewNotificationForGroups = createAppAsyncThunk(

export const loadPending = createAction('notificationGroups/loadPending');

export const updateScrollPosition = createAction<{ top: boolean }>(
export const updateScrollPosition = createAppAsyncThunk(
'notificationGroups/updateScrollPosition',
({ top }: { top: boolean }, { dispatch, getState }) => {
if (
top &&
getState().notificationGroups.mergedNotifications === 'needs-reload'
) {
void dispatch(fetchNotifications());
}

return { top };
},
);

export const setNotificationsFilter = createAppAsyncThunk(
Expand All @@ -165,5 +175,34 @@ export const markNotificationsAsRead = createAction(
'notificationGroups/markAsRead',
);

export const mountNotifications = createAction('notificationGroups/mount');
export const mountNotifications = createAppAsyncThunk(
'notificationGroups/mount',
(_, { dispatch, getState }) => {
const state = getState();

if (
state.notificationGroups.mounted === 0 &&
state.notificationGroups.mergedNotifications === 'needs-reload'
) {
void dispatch(fetchNotifications());
}
},
);

export const unmountNotifications = createAction('notificationGroups/unmount');

export const refreshStaleNotificationGroups = createAppAsyncThunk<{
deferredRefresh: boolean;
}>('notificationGroups/refreshStale', (_, { dispatch, getState }) => {
const state = getState();

if (
state.notificationGroups.scrolledToTop ||
!state.notificationGroups.mounted
) {
void dispatch(fetchNotifications());
return { deferredRefresh: false };
}

return { deferredRefresh: true };
});
14 changes: 6 additions & 8 deletions app/javascript/flavours/glitch/actions/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ const noOp = () => {};

let expandNotificationsController = new AbortController();

export function expandNotifications({ maxId, forceLoad = false } = {}, done = noOp) {
return (dispatch, getState) => {
export function expandNotifications({ maxId = undefined, forceLoad = false }) {
return async (dispatch, getState) => {
const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
const notifications = getState().get('notifications');
const isLoadingMore = !!maxId;
Expand All @@ -211,7 +211,6 @@ export function expandNotifications({ maxId, forceLoad = false } = {}, done = no
expandNotificationsController.abort();
expandNotificationsController = new AbortController();
} else {
done();
return;
}
}
Expand All @@ -238,7 +237,8 @@ export function expandNotifications({ maxId, forceLoad = false } = {}, done = no

dispatch(expandNotificationsRequest(isLoadingMore));

api().get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
try {
const response = await api().get('/api/v1/notifications', { params, signal: expandNotificationsController.signal });
const next = getLinks(response).refs.find(link => link.rel === 'next');

dispatch(importFetchedAccounts(response.data.map(item => item.account)));
Expand All @@ -248,11 +248,9 @@ export function expandNotifications({ maxId, forceLoad = false } = {}, done = no
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems));
fetchRelatedRelationships(dispatch, response.data);
dispatch(submitMarkers());
}).catch(error => {
} catch(error) {
dispatch(expandNotificationsFail(error, isLoadingMore));
}).finally(() => {
done();
});
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ export const initializeNotifications = createAppAsyncThunk(
) as boolean;

if (enableBeta) void dispatch(fetchNotifications());
else dispatch(expandNotifications());
else void dispatch(expandNotifications());
},
);
37 changes: 20 additions & 17 deletions app/javascript/flavours/glitch/actions/streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
deleteAnnouncement,
} from './announcements';
import { updateConversations } from './conversations';
import { processNewNotificationForGroups } from './notification_groups';
import { processNewNotificationForGroups, refreshStaleNotificationGroups } from './notification_groups';
import { updateNotifications, expandNotifications } from './notifications';
import { updateStatus } from './statuses';
import {
Expand All @@ -37,7 +37,7 @@ const randomUpTo = max =>
* @param {string} channelName
* @param {Object.<string, string>} params
* @param {Object} options
* @param {function(Function, Function): void} [options.fallback]
* @param {function(Function): Promise<void>} [options.fallback]
* @param {function(): void} [options.fillGaps]
* @param {function(object): boolean} [options.accept]
* @returns {function(): void}
Expand All @@ -52,14 +52,13 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
let pollingId;

/**
* @param {function(Function, Function): void} fallback
* @param {function(Function): Promise<void>} fallback
*/

const useFallback = fallback => {
fallback(dispatch, () => {
// eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
});
const useFallback = async fallback => {
await fallback(dispatch);
// eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
};

return {
Expand Down Expand Up @@ -109,6 +108,14 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
}
break;
}
case 'notifications_merged':
const state = getState();
if (state.notifications.top || !state.notifications.mounted)
dispatch(expandNotifications({ forceLoad: true, maxId: undefined }));
if(state.settings.getIn(['notifications', 'groupingBeta'], false)) {
dispatch(refreshStaleNotificationGroups());
}
break;
case 'conversation':
// @ts-expect-error
dispatch(updateConversations(JSON.parse(data.payload)));
Expand All @@ -132,21 +139,17 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti

/**
* @param {Function} dispatch
* @param {function(): void} done
*/
const refreshHomeTimelineAndNotification = (dispatch, done) => {
// @ts-expect-error
dispatch(expandHomeTimeline({}, () =>
// @ts-expect-error
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
};
async function refreshHomeTimelineAndNotification(dispatch) {
await dispatch(expandHomeTimeline({ maxId: undefined }));
await dispatch(expandNotifications({}));
await dispatch(fetchAnnouncements());
}

/**
* @returns {function(): void}
*/
export const connectUserStream = () =>
// @ts-expect-error
connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });

/**
Expand Down
52 changes: 23 additions & 29 deletions app/javascript/flavours/glitch/actions/timelines.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,18 @@ export function clearTimeline(timeline) {
};
}

const noOp = () => {};

const parseTags = (tags = {}, mode) => {
return (tags[mode] || []).map((tag) => {
return tag.value;
});
};

export function expandTimeline(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => {
export function expandTimeline(timelineId, path, params = {}) {
return async (dispatch, getState) => {
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const isLoadingMore = !!params.max_id;

if (timeline.get('isLoading')) {
done();
return;
}

Expand All @@ -120,7 +117,8 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {

dispatch(expandTimelineRequest(timelineId, isLoadingMore));

api().get(path, { params }).then(response => {
try {
const response = await api().get(path, { params });
const next = getLinks(response).refs.find(link => link.rel === 'next');

dispatch(importFetchedStatuses(response.data));
Expand All @@ -138,53 +136,49 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
if (timelineId === 'home') {
dispatch(submitMarkers());
}
}).catch(error => {
} catch(error) {
dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
}).finally(() => {
done();
});
}
};
}

export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => {
export function fillTimelineGaps(timelineId, path, params = {}) {
return async (dispatch, getState) => {
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const items = timeline.get('items');
const nullIndexes = items.map((statusId, index) => statusId === null ? index : null);
const gaps = nullIndexes.map(index => index > 0 ? items.get(index - 1) : null);

// Only expand at most two gaps to avoid doing too many requests
done = gaps.take(2).reduce((done, maxId) => {
return (() => dispatch(expandTimeline(timelineId, path, { ...params, maxId }, done)));
}, done);

done();
for (const maxId of gaps.take(2)) {
await dispatch(expandTimeline(timelineId, path, { ...params, maxId }));
}
};
}

export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
export const expandHomeTimeline = ({ maxId } = {}) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId });
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia });
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia });
export const expandDirectTimeline = ({ maxId } = {}) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId });
export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: withReplies, tagged, max_id: maxId });
export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
export const expandLinkTimeline = (url, { maxId } = {}, done = noOp) => expandTimeline(`link:${url}`, `/api/v1/timelines/link`, { url, max_id: maxId }, done);
export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
export const expandListTimeline = (id, { maxId } = {}) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId });
export const expandLinkTimeline = (url, { maxId } = {}) => expandTimeline(`link:${url}`, `/api/v1/timelines/link`, { url, max_id: maxId });
export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}) => {
return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
max_id: maxId,
any: parseTags(tags, 'any'),
all: parseTags(tags, 'all'),
none: parseTags(tags, 'none'),
local: local,
}, done);
});
};

export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps('home', '/api/v1/timelines/home', {}, done);
export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done);
export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, only_media: !!onlyMedia }, done);
export const fillListTimelineGaps = (id, done = noOp) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {}, done);
export const fillHomeTimelineGaps = () => fillTimelineGaps('home', '/api/v1/timelines/home', {});
export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}) => fillTimelineGaps(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly });
export const fillCommunityTimelineGaps = ({ onlyMedia } = {}) => fillTimelineGaps(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, only_media: !!onlyMedia });
export const fillListTimelineGaps = (id) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {});

export function expandTimelineRequest(timeline, isLoadingMore) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class ReportReasonSelector extends PureComponent {
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}>
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled || rules.length === 0}>
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}
</Category>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ export const LinkTimeline: React.FC<{

const handleLoadMore = useCallback(
(maxId: string) => {
dispatch(expandLinkTimeline(decodedUrl, { maxId }));
void dispatch(expandLinkTimeline(decodedUrl, { maxId }));
},
[dispatch, decodedUrl],
);

useEffect(() => {
dispatch(expandLinkTimeline(decodedUrl));
void dispatch(expandLinkTimeline(decodedUrl));
}, [dispatch, decodedUrl]);

return (
Expand Down
Loading
Loading