diff --git a/.bundler-audit.yml b/.bundler-audit.yml deleted file mode 100644 index 4dae946991..0000000000 --- a/.bundler-audit.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -ignore: - - CVE-2026-45363 diff --git a/.nvmrc b/.nvmrc index a2e33f6e2c..7858245567 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24.15 +24.16 diff --git a/Gemfile b/Gemfile index d4c1008a4f..8576937d2d 100644 --- a/Gemfile +++ b/Gemfile @@ -135,7 +135,7 @@ group :test do # Browser integration testing gem 'capybara', '~> 3.39' gem 'capybara-playwright-driver' - gem 'playwright-ruby-client', '1.59.1', require: false # Pinning the exact version as it needs to be kept in sync with the installed npm package + gem 'playwright-ruby-client', '1.60.0', require: false # Pinning the exact version as it needs to be kept in sync with the installed npm package # Used to reset the database between system tests gem 'database_cleaner-active_record' @@ -223,7 +223,7 @@ gem 'concurrent-ruby', require: false gem 'connection_pool', require: false gem 'xorcist', '~> 1.1' -gem 'net-http', '~> 0.6.0' +gem 'net-http', '~> 0.9.0' gem 'rubyzip', '~> 3.0' gem 'hcaptcha', '~> 7.1' diff --git a/Gemfile.lock b/Gemfile.lock index 333294b836..2a659eb3c2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,8 +99,8 @@ GEM ast (2.4.3) attr_required (1.0.2) aws-eventstream (1.4.0) - aws-partitions (1.1253.0) - aws-sdk-core (3.249.0) + aws-partitions (1.1254.0) + aws-sdk-core (3.250.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -378,7 +378,7 @@ GEM addressable (~> 2.8) bigdecimal (>= 3.1, < 5) jsonapi-renderer (0.2.2) - jwt (2.10.2) + jwt (2.10.3) base64 kaminari (1.2.2) activesupport (>= 4.1.0) @@ -455,8 +455,8 @@ GEM msgpack (1.8.0) multi_json (1.20.1) mutex_m (0.3.0) - net-http (0.6.0) - uri + net-http (0.9.1) + uri (>= 0.11.1) net-imap (0.6.4) date net-protocol @@ -539,7 +539,7 @@ GEM opentelemetry-instrumentation-active_support (~> 0.10) opentelemetry-instrumentation-active_support (0.12.0) opentelemetry-instrumentation-base (~> 0.25) - opentelemetry-instrumentation-base (0.26.0) + opentelemetry-instrumentation-base (0.26.1) opentelemetry-api (~> 1.7) opentelemetry-common (~> 0.21) opentelemetry-registry (~> 0.1) @@ -559,7 +559,7 @@ GEM opentelemetry-helpers-sql opentelemetry-helpers-sql-processor opentelemetry-instrumentation-base (~> 0.25) - opentelemetry-instrumentation-rack (0.31.0) + opentelemetry-instrumentation-rack (0.31.1) opentelemetry-instrumentation-base (~> 0.25) opentelemetry-instrumentation-rails (0.42.0) opentelemetry-instrumentation-action_mailer (~> 0.7) @@ -598,7 +598,7 @@ GEM pg (1.6.3) pghero (3.8.0) activerecord (>= 7.2) - playwright-ruby-client (1.59.1) + playwright-ruby-client (1.60.0) base64 concurrent-ruby (>= 1.1.6) mime-types (>= 3.0) @@ -816,7 +816,7 @@ GEM securerandom (0.4.1) shoulda-matchers (7.0.1) activesupport (>= 7.1) - sidekiq (8.1.5) + sidekiq (8.1.6) connection_pool (>= 3.0.0) json (>= 2.16.0) logger (>= 1.7.0) @@ -827,7 +827,7 @@ GEM sidekiq-scheduler (6.0.2) rufus-scheduler (~> 3.2) sidekiq (>= 7.3, < 9) - sidekiq-unique-jobs (8.0.13) + sidekiq-unique-jobs (8.1.0) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 7.0.0, < 9.0.0) thor (>= 1.0, < 3.0) @@ -1012,7 +1012,7 @@ DEPENDENCIES memory_profiler mime-types (~> 3.7.0) mutex_m - net-http (~> 0.6.0) + net-http (~> 0.9.0) net-ldap (~> 0.18) nokogiri (~> 1.15) omniauth (~> 2.0) @@ -1040,7 +1040,7 @@ DEPENDENCIES parslet pg (~> 1.5) pghero - playwright-ruby-client (= 1.59.1) + playwright-ruby-client (= 1.60.0) premailer-rails prometheus_exporter (~> 2.2) propshaft diff --git a/app/controllers/activitypub/featured_collections_controller.rb b/app/controllers/activitypub/featured_collections_controller.rb index 09de5583cc..12c0648fae 100644 --- a/app/controllers/activitypub/featured_collections_controller.rb +++ b/app/controllers/activitypub/featured_collections_controller.rb @@ -9,7 +9,6 @@ class ActivityPub::FeaturedCollectionsController < ApplicationController vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } - before_action :check_feature_enabled before_action :require_account_signature!, if: -> { authorized_fetch_mode? } before_action :set_collections @@ -72,8 +71,4 @@ class ActivityPub::FeaturedCollectionsController < ApplicationController ) end end - - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end end diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb index 10dbe846e4..03234b0bde 100644 --- a/app/controllers/admin/report_notes_controller.rb +++ b/app/controllers/admin/report_notes_controller.rb @@ -25,6 +25,8 @@ module Admin @action_logs = @report.history.includes(:target) @form = Admin::StatusBatchAction.new @statuses = @report.statuses.with_includes + @collections = @report.collections + @collection_form = Admin::CollectionBatchAction.new render 'admin/reports/show' end diff --git a/app/controllers/api/v1_alpha/collection_items_controller.rb b/app/controllers/api/v1/collection_items_controller.rb similarity index 84% rename from app/controllers/api/v1_alpha/collection_items_controller.rb rename to app/controllers/api/v1/collection_items_controller.rb index 2c46cc4f9f..3ec5e18ed9 100644 --- a/app/controllers/api/v1_alpha/collection_items_controller.rb +++ b/app/controllers/api/v1/collection_items_controller.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -class Api::V1Alpha::CollectionItemsController < Api::BaseController +class Api::V1::CollectionItemsController < Api::BaseController include Authorization - before_action :check_feature_enabled - before_action -> { doorkeeper_authorize! :write, :'write:collections' } before_action :require_user! @@ -55,8 +53,4 @@ class Api::V1Alpha::CollectionItemsController < Api::BaseController def set_collection_item @collection_item = @collection.collection_items.find(params[:id]) end - - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end end diff --git a/app/controllers/api/v1_alpha/collections_controller.rb b/app/controllers/api/v1/collections_controller.rb similarity index 85% rename from app/controllers/api/v1_alpha/collections_controller.rb rename to app/controllers/api/v1/collections_controller.rb index 1ca1cd6923..9acd535f46 100644 --- a/app/controllers/api/v1_alpha/collections_controller.rb +++ b/app/controllers/api/v1/collections_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Api::V1Alpha::CollectionsController < Api::BaseController +class Api::V1::CollectionsController < Api::BaseController include Authorization DEFAULT_COLLECTIONS_LIMIT = 40 @@ -9,8 +9,6 @@ class Api::V1Alpha::CollectionsController < Api::BaseController render json: { error: ValidationErrorFormatter.new(e).as_json }, status: 422 end - before_action :check_feature_enabled - before_action -> { authorize_if_got_token! :read, :'read:collections' }, only: [:index, :show] before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create, :update, :destroy] @@ -91,20 +89,16 @@ class Api::V1Alpha::CollectionsController < Api::BaseController params.permit(:name, :description, :language, :sensitive, :discoverable, :tag_name) end - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end - def next_path return unless records_continue? - api_v1_alpha_account_collections_url(@account, pagination_params(offset: offset_param + limit_param(DEFAULT_COLLECTIONS_LIMIT))) + api_v1_account_collections_url(@account, pagination_params(offset: offset_param + limit_param(DEFAULT_COLLECTIONS_LIMIT))) end def prev_path return if offset_param.zero? - api_v1_alpha_account_collections_url(@account, pagination_params(offset: offset_param - limit_param(DEFAULT_COLLECTIONS_LIMIT))) + api_v1_account_collections_url(@account, pagination_params(offset: offset_param - limit_param(DEFAULT_COLLECTIONS_LIMIT))) end def records_continue? diff --git a/app/controllers/api/v1_alpha/in_collections_controller.rb b/app/controllers/api/v1/in_collections_controller.rb similarity index 70% rename from app/controllers/api/v1_alpha/in_collections_controller.rb rename to app/controllers/api/v1/in_collections_controller.rb index 087464989e..c34845e463 100644 --- a/app/controllers/api/v1_alpha/in_collections_controller.rb +++ b/app/controllers/api/v1/in_collections_controller.rb @@ -1,12 +1,10 @@ # frozen_string_literal: true -class Api::V1Alpha::InCollectionsController < Api::BaseController +class Api::V1::InCollectionsController < Api::BaseController include Authorization DEFAULT_COLLECTIONS_LIMIT = 40 - before_action :check_feature_enabled - before_action -> { authorize_if_got_token! :read, :'read:collections' }, only: [:index] before_action :require_user! @@ -37,20 +35,16 @@ class Api::V1Alpha::InCollectionsController < Api::BaseController .limit(limit_param(DEFAULT_COLLECTIONS_LIMIT)) end - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end - def next_path return unless records_continue? - api_v1_alpha_account_in_collections_url(@account, pagination_params(offset: offset_param + limit_param(DEFAULT_COLLECTIONS_LIMIT))) + api_v1_account_in_collections_url(@account, pagination_params(offset: offset_param + limit_param(DEFAULT_COLLECTIONS_LIMIT))) end def prev_path return if offset_param.zero? - api_v1_alpha_account_in_collections_url(@account, pagination_params(offset: offset_param - limit_param(DEFAULT_COLLECTIONS_LIMIT))) + api_v1_account_in_collections_url(@account, pagination_params(offset: offset_param - limit_param(DEFAULT_COLLECTIONS_LIMIT))) end def records_continue? diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 8e341aa48e..a8653631c2 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -23,10 +23,6 @@ class Api::V1::ReportsController < Api::BaseController end def report_params - if Mastodon::Feature.collections_enabled? - params.permit(:account_id, :comment, :category, :forward, forward_to_domains: [], status_ids: [], collection_ids: [], rule_ids: []) - else - params.permit(:account_id, :comment, :category, :forward, forward_to_domains: [], status_ids: [], rule_ids: []) - end + params.permit(:account_id, :comment, :category, :forward, forward_to_domains: [], status_ids: [], collection_ids: [], rule_ids: []) end end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 0905efd39d..d978501a02 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -175,6 +175,6 @@ class Api::V1::StatusesController < Api::BaseController end def serialized_accounts(accounts) - ActiveModel::Serializer::CollectionSerializer.new(accounts, serializer: REST::AccountSerializer) + ActiveModel::Serializer::CollectionSerializer.new(accounts, serializer: REST::AccountSerializer, scope_name: :current_user, scope: current_user) end end diff --git a/app/controllers/collection_items_controller.rb b/app/controllers/collection_items_controller.rb index 09c1e0e192..51044b5965 100644 --- a/app/controllers/collection_items_controller.rb +++ b/app/controllers/collection_items_controller.rb @@ -7,7 +7,6 @@ class CollectionItemsController < ApplicationController vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } - before_action :check_feature_enabled before_action :require_account_signature!, if: -> { authorized_fetch_mode? } before_action :set_collection_item @@ -35,8 +34,4 @@ class CollectionItemsController < ApplicationController rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError not_found end - - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end end diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 70541433f0..628418557c 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -8,7 +8,6 @@ class CollectionsController < ApplicationController vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } - before_action :check_feature_enabled before_action :require_account_signature!, only: :show, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_collection @@ -51,8 +50,4 @@ class CollectionsController < ApplicationController recently_updated = @collection.updated_at > 15.minutes.ago recently_updated ? 30.seconds : 5.minutes end - - def check_feature_enabled - raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? - end end diff --git a/app/javascript/flavours/glitch/actions/accounts_typed.ts b/app/javascript/flavours/glitch/actions/accounts_typed.ts index e49c3043fb..cb9e89d048 100644 --- a/app/javascript/flavours/glitch/actions/accounts_typed.ts +++ b/app/javascript/flavours/glitch/actions/accounts_typed.ts @@ -3,6 +3,7 @@ import { createAction } from '@reduxjs/toolkit'; import { apiRemoveAccountFromFollowers, apiGetEndorsedAccounts, + apiGetAccounts, } from 'flavours/glitch/api/accounts'; import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships'; import { createDataLoadingThunk } from 'flavours/glitch/store/typed_functions'; @@ -113,3 +114,12 @@ export const fetchEndorsedAccounts = createDataLoadingThunk( return data; }, ); + +export const fetchAccounts = createDataLoadingThunk( + 'accounts/multi_accounts', + ({ accountIds }: { accountIds: string[] }) => apiGetAccounts(accountIds), + (data, { dispatch }) => { + dispatch(importFetchedAccounts(data)); + return data; + }, +); diff --git a/app/javascript/flavours/glitch/actions/notification_groups.ts b/app/javascript/flavours/glitch/actions/notification_groups.ts index b145898494..0e4d291ae0 100644 --- a/app/javascript/flavours/glitch/actions/notification_groups.ts +++ b/app/javascript/flavours/glitch/actions/notification_groups.ts @@ -36,9 +36,18 @@ function notificationTypeForFilter(type: NotificationType) { } function notificationTypeForQuickFilter(type: NotificationType) { - if (type === 'quoted_update') return 'update'; - else if (type === 'quote') return 'mention'; - else return type; + switch (type) { + case 'quoted_update': + return 'update'; + case 'quote': + return 'mention'; + case 'collection_update': + return 'collection'; + case 'added_to_collection': + return 'collection'; + default: + return type; + } } function excludeAllTypesExcept(filter: string) { diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index da0c5f1102..cb4cd1251c 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -86,6 +86,9 @@ export function setupBrowserNotifications() { }; } +/** + * @param {(NotificationPermission) => void} callback + */ export function requestBrowserPermission(callback = noOp) { return dispatch => { requestNotificationPermission((permission) => { diff --git a/app/javascript/flavours/glitch/api/accounts.ts b/app/javascript/flavours/glitch/api/accounts.ts index 0fe4e1d7b5..1a5d3f13e4 100644 --- a/app/javascript/flavours/glitch/api/accounts.ts +++ b/app/javascript/flavours/glitch/api/accounts.ts @@ -19,6 +19,11 @@ import type { ApiProfileUpdateParams, } from '../api_types/profile'; +export const apiGetAccounts = (ids: string[]) => + apiRequestGet('v1/accounts', { + id: ids, + }); + export const apiSubmitAccountNote = (id: string, value: string) => apiRequestPost(`v1/accounts/${id}/note`, { comment: value, diff --git a/app/javascript/flavours/glitch/api/collections.ts b/app/javascript/flavours/glitch/api/collections.ts index 76a29f2d66..521f5bf25a 100644 --- a/app/javascript/flavours/glitch/api/collections.ts +++ b/app/javascript/flavours/glitch/api/collections.ts @@ -15,48 +15,40 @@ import type { } from '../api_types/collections'; export const apiCreateCollection = (collection: ApiCreateCollectionPayload) => - apiRequestPost('v1_alpha/collections', collection); + apiRequestPost('v1/collections', collection); export const apiUpdateCollection = ({ id, ...collection }: ApiUpdateCollectionPayload) => - apiRequestPut( - `v1_alpha/collections/${id}`, - collection, - ); + apiRequestPut(`v1/collections/${id}`, collection); export const apiDeleteCollection = (collectionId: string) => - apiRequestDelete(`v1_alpha/collections/${collectionId}`); + apiRequestDelete(`v1/collections/${collectionId}`); export const apiGetCollection = (collectionId: string) => apiRequestGet( - `v1_alpha/collections/${collectionId}`, + `v1/collections/${collectionId}`, ); export const apiGetCollectionsCreatedByAccount = (accountId: string) => - apiRequestGet( - `v1_alpha/accounts/${accountId}/collections`, - ); + apiRequestGet(`v1/accounts/${accountId}/collections`); export const apiGetCollectionsFeaturingAccount = (accountId: string) => - apiRequestGet( - `v1_alpha/accounts/${accountId}/in_collections`, - ); + apiRequestGet(`v1/accounts/${accountId}/in_collections`); export const apiAddCollectionItem = (collectionId: string, accountId: string) => apiRequestPost( - `v1_alpha/collections/${collectionId}/items`, + `v1/collections/${collectionId}/items`, { account_id: accountId }, ); export const apiRemoveCollectionItem = (collectionId: string, itemId: string) => apiRequestDelete( - `v1_alpha/collections/${collectionId}/items/${itemId}`, + `v1/collections/${collectionId}/items/${itemId}`, ); export const apiRevokeCollectionInclusion = ( collectionId: string, itemId: string, -) => - apiRequestPost(`v1_alpha/collections/${collectionId}/items/${itemId}/revoke`); +) => apiRequestPost(`v1/collections/${collectionId}/items/${itemId}/revoke`); diff --git a/app/javascript/flavours/glitch/api/lists.ts b/app/javascript/flavours/glitch/api/lists.ts index 1b12c558c9..fb05659e76 100644 --- a/app/javascript/flavours/glitch/api/lists.ts +++ b/app/javascript/flavours/glitch/api/lists.ts @@ -15,7 +15,7 @@ export const apiUpdate = (list: Partial) => export const apiGetLists = () => apiRequestGet('v1/lists'); -export const apiGetAccounts = (listId: string) => +export const apiGetListAccounts = (listId: string) => apiRequestGet(`v1/lists/${listId}/accounts`, { limit: 0, }); diff --git a/app/javascript/flavours/glitch/components/account_header/styles.module.scss b/app/javascript/flavours/glitch/components/account_header/styles.module.scss index ab751ce170..4de49f79ae 100644 --- a/app/javascript/flavours/glitch/components/account_header/styles.module.scss +++ b/app/javascript/flavours/glitch/components/account_header/styles.module.scss @@ -110,6 +110,9 @@ word-break: break-all; text-align: left; + /* Allow the handle text to be selected */ + user-select: text; + > svg { width: 16px; height: 16px; diff --git a/app/javascript/flavours/glitch/components/form_fields/combobox_field.tsx b/app/javascript/flavours/glitch/components/form_fields/combobox_field.tsx index 654507fe03..b856c4b32d 100644 --- a/app/javascript/flavours/glitch/components/form_fields/combobox_field.tsx +++ b/app/javascript/flavours/glitch/components/form_fields/combobox_field.tsx @@ -100,6 +100,10 @@ interface ComboboxProps< * Icon to be displayed in the text input */ icon?: TextInputProps['icon'] | null; + /** + * Set to true to open as soon as there is focus + */ + openOnFocus?: boolean; /** * Set to false to keep the menu open when an item is selected */ @@ -217,8 +221,10 @@ const ComboboxWithRef = ( renderGroupTitle, renderItem, onSelectItem, + onFocus, onChange, onKeyDown, + openOnFocus = false, closeOnSelect = true, suppressMenu = false, icon = SearchIcon, @@ -288,6 +294,16 @@ const ComboboxWithRef = ( } }, []); + const handleFocus: React.FocusEventHandler = useCallback( + (e) => { + if (openOnFocus) { + setShouldMenuOpen(true); + } + onFocus?.(e); + }, + [onFocus, openOnFocus], + ); + const handleInputChange = useCallback( (e: React.ChangeEvent) => { onChange(e); @@ -487,6 +503,7 @@ const ComboboxWithRef = ( autoComplete='off' spellCheck='false' value={value} + onFocus={handleFocus} onChange={handleInputChange} onKeyDown={handleInputKeyDown} icon={icon ?? undefined} diff --git a/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx b/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx index 2b29bf4238..4eb367fb14 100644 --- a/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx +++ b/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx @@ -9,7 +9,6 @@ import { Button } from '@/flavours/glitch/components/button'; import { DisplayName } from '@/flavours/glitch/components/display_name'; import { EmptyState } from '@/flavours/glitch/components/empty_state'; import { LimitedAccountHint } from '@/flavours/glitch/components/limited_account_hint'; -import { areCollectionsEnabled } from '@/flavours/glitch/features/collections/utils'; import { useAccount } from '@/flavours/glitch/hooks/useAccount'; import { useCurrentAccountId } from '@/flavours/glitch/hooks/useAccountId'; import { useAppDispatch } from '@/flavours/glitch/store'; @@ -50,56 +49,39 @@ export const EmptyMessage: React.FC = ({ let title: React.ReactNode = null; let message: React.ReactNode = null; - const hasCollections = areCollectionsEnabled(); - if (me === accountId) { - if (hasCollections) { - // Return only here to insert the "Create a collection" button as the action for the empty state. - return ( - + } + message={ + + } + > + {!withoutAddCollectionButton && ( + - } - message={ - - } - > - {!withoutAddCollectionButton && ( - - - - )} - - - ); - } else { - title = ( - - ); - message = ( - - ); - } + + )} + + + ); } else if (suspended) { title = ( = ({ multiColumn, }) => { @@ -98,14 +95,11 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({ ); const hasCollections = - collectionsEnabled && - collectionsLoadStatus === 'idle' && - listedCollections.length > 0; + collectionsLoadStatus === 'idle' && listedCollections.length > 0; const hasFeaturedAccounts = !featuredAccountIds.isEmpty(); - const isLoading = - !accountId || (collectionsEnabled && collectionsLoadStatus !== 'idle'); + const isLoading = !accountId || collectionsLoadStatus !== 'idle'; if (accountId === null) { return ; @@ -165,57 +159,53 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({ )} - {collectionsEnabled && ( - <> - -

- -

- {accountId === me && ( - - - - )} -
- {hasCollections ? ( - - - ), - subtitle: ( - - ), - }} - renderListItem={renderListItem} - /> - - ) : ( -