diff --git a/Gemfile.lock b/Gemfile.lock index 41fc86c8af..1f8645a59e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -702,7 +702,7 @@ GEM rqrcode_core (1.2.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-github (2.4.0) @@ -710,7 +710,7 @@ GEM rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (6.1.2) + rspec-rails (6.1.3) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) @@ -891,7 +891,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.15) + zeitwerk (2.6.16) PLATFORMS ruby diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index aa05887d65..c4c084d98e 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -32,7 +32,7 @@ "account.featured_tags.last_status_never": "게시물 없음", "account.featured_tags.title": "{name} 님의 추천 해시태그", "account.follow": "팔로우", - "account.follow_back": "맞팔로우", + "account.follow_back": "맞팔로우 하기", "account.followers": "팔로워", "account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.", "account.followers_counter": "{counter} 팔로워", @@ -53,7 +53,7 @@ "account.mute_notifications_short": "알림 뮤트", "account.mute_short": "뮤트", "account.muted": "뮤트됨", - "account.mutual": "상호 팔로우", + "account.mutual": "맞팔로우 중", "account.no_bio": "제공된 설명이 없습니다.", "account.open_original_page": "원본 페이지 열기", "account.posts": "게시물", diff --git a/app/javascript/mastodon/store/typed_functions.ts b/app/javascript/mastodon/store/typed_functions.ts index dae37e6225..e5820149db 100644 --- a/app/javascript/mastodon/store/typed_functions.ts +++ b/app/javascript/mastodon/store/typed_functions.ts @@ -82,13 +82,19 @@ export function createThunk( const discardLoadDataInPayload = Symbol('discardLoadDataInPayload'); type DiscardLoadData = typeof discardLoadDataInPayload; -type OnData = ( +type OnData = ( data: LoadDataResult, api: AppThunkApi & { + actionArg: ActionArg; discardLoadData: DiscardLoadData; }, ) => ReturnedData | DiscardLoadData | Promise; +type LoadData = ( + args: Args, + api: AppThunkApi, +) => Promise; + type ArgsType = Record | undefined; // Overload when there is no `onData` method, the payload is the `onData` result @@ -101,18 +107,18 @@ export function createDataLoadingThunk( // Overload when the `onData` method returns discardLoadDataInPayload, then the payload is empty export function createDataLoadingThunk( name: string, - loadData: (args: Args) => Promise, + loadData: LoadData, onDataOrThunkOptions?: | AppThunkOptions - | OnData, + | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; // Overload when the `onData` method returns nothing, then the mayload is the `onData` result export function createDataLoadingThunk( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: AppThunkOptions | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; @@ -123,8 +129,10 @@ export function createDataLoadingThunk< Returned, >( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: + | AppThunkOptions + | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; @@ -159,11 +167,13 @@ export function createDataLoadingThunk< Returned, >( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: + | AppThunkOptions + | OnData, maybeThunkOptions?: AppThunkOptions, ) { - let onData: OnData | undefined; + let onData: OnData | undefined; let thunkOptions: AppThunkOptions | undefined; if (typeof onDataOrThunkOptions === 'function') onData = onDataOrThunkOptions; @@ -177,7 +187,10 @@ export function createDataLoadingThunk< return createThunk( name, async (arg, { getState, dispatch }) => { - const data = await loadData(arg); + const data = await loadData(arg, { + dispatch, + getState, + }); if (!onData) return data as Returned; @@ -185,6 +198,7 @@ export function createDataLoadingThunk< dispatch, getState, discardLoadData: discardLoadDataInPayload, + actionArg: arg, }); // if there is no return in `onData`, we return the `onData` result diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 417245d19d..966819585f 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::NotificationSerializer < ActiveModel::Serializer - attributes :id, :type, :created_at + attributes :id, :type, :created_at, :group_key belongs_to :from_account, key: :account, serializer: REST::AccountSerializer belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer @@ -13,6 +13,10 @@ class REST::NotificationSerializer < ActiveModel::Serializer object.id.to_s end + def group_key + object.group_key || "ungrouped-#{object.id}" + end + def status_type? [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type) end