diff options
Diffstat (limited to 'app')
29 files changed, 142 insertions, 32 deletions
diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb index 8ce413f8a..b7365d5ca 100644 --- a/app/chewy/statuses_index.rb +++ b/app/chewy/statuses_index.rb @@ -51,7 +51,7 @@ class StatusesIndex < Chewy::Index field :id, type: 'long' field :account_id, type: 'long' - field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.media_attachments.map(&:description)).join("\n\n") } do + field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.media_attachments.map(&:description)).concat(status.preloadable_poll ? status.preloadable_poll.options : []).join("\n\n") } do field :stemmed, type: 'text', analyzer: 'content' end diff --git a/app/controllers/api/v1/timelines/direct_controller.rb b/app/controllers/api/v1/timelines/direct_controller.rb index d8a76d153..6e98e9cac 100644 --- a/app/controllers/api/v1/timelines/direct_controller.rb +++ b/app/controllers/api/v1/timelines/direct_controller.rb @@ -27,16 +27,18 @@ class Api::V1::Timelines::DirectController < Api::BaseController end def direct_timeline_statuses - # this query requires built in pagination. - Status.as_direct_timeline( - current_account, + account_direct_feed.get( limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id], - true # returns array of cache_ids object + params[:min_id] ) end + def account_direct_feed + DirectFeed.new(current_account) + end + def insert_pagination_headers set_pagination_headers(next_path, prev_path) end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 333082f68..cef412554 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -161,11 +161,15 @@ class ApplicationController < ActionController::Base end def current_account - @current_account ||= current_user.try(:account) + return @current_account if defined?(@current_account) + + @current_account = current_user&.account end def current_session - @current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id']) + return @current_session if defined?(@current_session) + + @current_session = SessionActivation.find_by(session_id: cookies.signed['_session_id']) if cookies.signed['_session_id'].present? end def current_flavour diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index 5103cc50e..451742d41 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -52,6 +52,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_show_application, :setting_advanced_layout, :setting_default_content_type, + :setting_use_blurhash, notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account), interactions: %i(must_be_follower must_be_following must_be_following_dm) ) diff --git a/app/javascript/flavours/glitch/actions/importer/normalizer.js b/app/javascript/flavours/glitch/actions/importer/normalizer.js index a8c3fe16a..c19ca8265 100644 --- a/app/javascript/flavours/glitch/actions/importer/normalizer.js +++ b/app/javascript/flavours/glitch/actions/importer/normalizer.js @@ -55,7 +55,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml'); } else { const spoilerText = normalStatus.spoiler_text || ''; - const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); + const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); const emojiMap = makeEmojiMap(normalStatus); normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 291caff45..04d3ce751 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -6,7 +6,7 @@ import IconButton from './icon_button'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { isIOS } from 'flavours/glitch/util/is_mobile'; import classNames from 'classnames'; -import { autoPlayGif, displayMedia } from 'flavours/glitch/util/initial_state'; +import { autoPlayGif, displayMedia, useBlurhash } from 'flavours/glitch/util/initial_state'; import { decode } from 'blurhash'; const messages = defineMessages({ @@ -101,6 +101,8 @@ class Item extends React.PureComponent { } _decode () { + if (!useBlurhash) return; + const hash = this.props.attachment.get('blurhash'); const pixels = decode(hash, 32, 32); diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index b73ea0b07..112f9d101 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -5,7 +5,7 @@ import { fromJS, is } from 'immutable'; import { throttle } from 'lodash'; import classNames from 'classnames'; import { isFullscreen, requestFullscreen, exitFullscreen } from 'flavours/glitch/util/fullscreen'; -import { displayMedia } from 'flavours/glitch/util/initial_state'; +import { displayMedia, useBlurhash } from 'flavours/glitch/util/initial_state'; import { decode } from 'blurhash'; const messages = defineMessages({ @@ -312,7 +312,7 @@ export default class Video extends React.PureComponent { } _decode () { - if (!this.canvas) return; + if (!this.canvas || !useBlurhash) return; const hash = this.props.blurhash; const pixels = decode(hash, 32, 32); diff --git a/app/javascript/flavours/glitch/util/emoji/emoji_mart_search_light.js b/app/javascript/flavours/glitch/util/emoji/emoji_mart_search_light.js index 164fdcc0b..e4519a13e 100644 --- a/app/javascript/flavours/glitch/util/emoji/emoji_mart_search_light.js +++ b/app/javascript/flavours/glitch/util/emoji/emoji_mart_search_light.js @@ -74,7 +74,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo return [emojisList['-1']]; } - let values = value.toLowerCase().split(/[\s|,|\-|_]+/), + let values = value.toLowerCase().split(/[\s|,\-_]+/), allResults = []; if (values.length > 2) { diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index f42c06a3a..e8811a6ce 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -29,5 +29,6 @@ export const mascot = getMeta('mascot'); export const isStaff = getMeta('is_staff'); export const defaultContentType = getMeta('default_content_type'); export const forceSingleColumn = getMeta('advanced_layout') === false; +export const useBlurhash = getMeta('use_blurhash'); export default initialState; diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index 5badb0c49..b250ee076 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -56,7 +56,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.hidden = normalOldStatus.get('hidden'); } else { const spoilerText = normalStatus.spoiler_text || ''; - const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); + const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); const emojiMap = makeEmojiMap(normalStatus); normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js index 77bac61ee..9cd71b7c9 100644 --- a/app/javascript/mastodon/components/media_gallery.js +++ b/app/javascript/mastodon/components/media_gallery.js @@ -6,7 +6,7 @@ import IconButton from './icon_button'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { isIOS } from '../is_mobile'; import classNames from 'classnames'; -import { autoPlayGif, displayMedia } from '../initial_state'; +import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state'; import { decode } from 'blurhash'; const messages = defineMessages({ @@ -81,6 +81,8 @@ class Item extends React.PureComponent { } _decode () { + if (!useBlurhash) return; + const hash = this.props.attachment.get('blurhash'); const pixels = decode(hash, 32, 32); diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index b3a04e421..c529c8f7c 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -189,12 +189,12 @@ class ComposeForm extends ImmutablePureComponent { } return ( - <div className='compose-form' ref={this.setRef}> + <div className='compose-form'> <WarningContainer /> <ReplyIndicatorContainer /> - <div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}> + <div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`} ref={this.setRef}> <AutosuggestInput placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoilerText} diff --git a/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js b/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js index 164fdcc0b..e4519a13e 100644 --- a/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js +++ b/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js @@ -74,7 +74,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo return [emojisList['-1']]; } - let values = value.toLowerCase().split(/[\s|,|\-|_]+/), + let values = value.toLowerCase().split(/[\s|,\-_]+/), allResults = []; if (values.length > 2) { diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index b0c408527..0acdd198d 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -5,7 +5,7 @@ import { fromJS, is } from 'immutable'; import { throttle } from 'lodash'; import classNames from 'classnames'; import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen'; -import { displayMedia } from '../../initial_state'; +import { displayMedia, useBlurhash } from '../../initial_state'; import Icon from 'mastodon/components/icon'; import { decode } from 'blurhash'; @@ -298,6 +298,8 @@ class Video extends React.PureComponent { } _decode () { + if (!useBlurhash) return; + const hash = this.props.blurhash; const pixels = decode(hash, 32, 32); diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 4e0ecef94..7df2a90bc 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -21,5 +21,6 @@ export const mascot = getMeta('mascot'); export const profile_directory = getMeta('profile_directory'); export const isStaff = getMeta('is_staff'); export const forceSingleColumn = !getMeta('advanced_layout'); +export const useBlurhash = getMeta('use_blurhash'); export default initialState; diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 66b5763a9..a4a9baaee 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -5,7 +5,7 @@ class ActivityPub::Activity include Redisable SUPPORTED_TYPES = %w(Note Question).freeze - CONVERTED_TYPES = %w(Image Video Article Page).freeze + CONVERTED_TYPES = %w(Image Audio Video Article Page).freeze def initialize(json, account, **options) @json = json diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 4bc75dae8..59767cdfe 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -22,6 +22,8 @@ class FeedManager filter_from_home?(status, receiver_id) elsif timeline_type == :mentions filter_from_mentions?(status, receiver_id) + elsif timeline_type == :direct + filter_from_direct?(status, receiver_id) else false end @@ -59,6 +61,18 @@ class FeedManager true end + def push_to_direct(account, status) + return false unless add_to_feed(:direct, account.id, status) + trim(:direct, account.id) + PushUpdateWorker.perform_async(account.id, status.id, "timeline:direct:#{account.id}") + true + end + + def unpush_from_direct(account, status) + return false unless remove_from_feed(:direct, account.id, status) + redis.publish("timeline:direct:#{account.id}", Oj.dump(event: :delete, payload: status.id.to_s)) + end + def trim(type, account_id) timeline_key = key(type, account_id) reblog_key = key(type, account_id, 'reblogs') @@ -142,6 +156,27 @@ class FeedManager end end + def populate_direct_feed(account) + added = 0 + limit = FeedManager::MAX_ITEMS / 2 + max_id = nil + + loop do + statuses = Status.as_direct_timeline(account, limit, max_id) + + break if statuses.empty? + + statuses.each do |status| + next if filter_from_direct?(status, account) + added += 1 if add_to_feed(:direct, account.id, status) + end + + break unless added.zero? + + max_id = statuses.last.id + end + end + private def push_update_required?(timeline_id) @@ -199,6 +234,11 @@ class FeedManager should_filter end + def filter_from_direct?(status, receiver_id) + return false if receiver_id == status.account_id + filter_from_mentions?(status, receiver_id) + end + def phrase_filtered?(status, receiver_id, context) active_filters = Rails.cache.fetch("filters:#{receiver_id}") { CustomFilter.where(account_id: receiver_id).active_irreversible.to_a }.to_a @@ -221,7 +261,8 @@ class FeedManager status = status.reblog if status.reblog? !combined_regex.match(Formatter.instance.plaintext(status)).nil? || - (status.spoiler_text.present? && !combined_regex.match(status.spoiler_text).nil?) + (status.spoiler_text.present? && !combined_regex.match(status.spoiler_text).nil?) || + (status.preloadable_poll && !combined_regex.match(status.preloadable_poll.options.join("\n\n")).nil?) end # Adds a status to an account's feed, returning true if a status was diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index a95d09c5c..ac35fd005 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -38,6 +38,7 @@ class UserSettingsDecorator user.settings['show_application'] = show_application_preference if change?('setting_show_application') user.settings['advanced_layout'] = advanced_layout_preference if change?('setting_advanced_layout') user.settings['default_content_type']= default_content_type_preference if change?('setting_default_content_type') + user.settings['use_blurhash'] = use_blurhash_preference if change?('setting_use_blurhash') end def merged_notification_emails @@ -132,6 +133,10 @@ class UserSettingsDecorator settings['setting_default_content_type'] end + def use_blurhash_preference + boolean_cast_setting 'setting_use_blurhash' + end + def boolean_cast_setting(key) ActiveModel::Type::Boolean.new.cast(settings[key]) end diff --git a/app/models/direct_feed.rb b/app/models/direct_feed.rb new file mode 100644 index 000000000..c0b8a0a35 --- /dev/null +++ b/app/models/direct_feed.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class DirectFeed < Feed + include Redisable + + def initialize(account) + @type = :direct + @id = account.id + @account = account + end + + def get(limit, max_id = nil, since_id = nil, min_id = nil) + unless redis.exists("account:#{@account.id}:regeneration") + statuses = super + return statuses unless statuses.empty? + end + from_database(limit, max_id, since_id, min_id) + end + + private + + def from_database(limit, max_id, since_id, min_id) + loop do + statuses = Status.as_direct_timeline(@account, limit, max_id, since_id, min_id) + return statuses if statuses.empty? + max_id = statuses.last.id + statuses = statuses.reject { |status| FeedManager.instance.filter?(:direct, status, @account.id) } + return statuses unless statuses.empty? + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index f6936cb9d..9bc3dd608 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -106,7 +106,7 @@ class User < ApplicationRecord delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal, :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count, :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, - :advanced_layout, :default_content_type, to: :settings, prefix: :setting, allow_nil: false + :advanced_layout, :default_content_type, :use_blurhash, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code attr_writer :external diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index c46caa28e..e3e2775fb 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -47,6 +47,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers store[:reduce_motion] = object.current_account.user.setting_reduce_motion store[:advanced_layout] = object.current_account.user.setting_advanced_layout + store[:use_blurhash] = object.current_account.user.setting_use_blurhash store[:is_staff] = object.current_account.user.staff? store[:default_content_type] = object.current_account.user.setting_default_content_type end diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index 02f7076f7..2fe009c91 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -107,9 +107,9 @@ class BatchedRemoveStatusService < BaseService payload = @json_payloads[status.id] redis.pipelined do @mentions[status.id].each do |mention| - redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local? + FeedManager.instance.unpush_from_direct(mention.account, status) if mention.account.local? end - redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local? + FeedManager.instance.unpush_from_direct(status.account, status) if status.account.local? end end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index b66dc342e..cf433d8a6 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -37,6 +37,7 @@ class FanOutOnWriteService < BaseService def deliver_to_self(status) Rails.logger.debug "Delivering status #{status.id} to author" FeedManager.instance.push_to_home(status.account, status) + FeedManager.instance.push_to_direct(status.account, status) if status.direct_visibility? end def deliver_to_followers(status) @@ -98,11 +99,9 @@ class FanOutOnWriteService < BaseService def deliver_to_direct_timelines(status) Rails.logger.debug "Delivering status #{status.id} to direct timelines" - status.mentions.includes(:account).each do |mention| - Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? + FeedInsertWorker.push_bulk(status.mentions.includes(:account).map(&:account).select { |mentioned_account| mentioned_account.local? }) do |account| + [status.id, account.id, :direct] end - - Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local? end def deliver_to_own_conversation(status) diff --git a/app/services/precompute_feed_service.rb b/app/services/precompute_feed_service.rb index 076dedaca..029c2f6e5 100644 --- a/app/services/precompute_feed_service.rb +++ b/app/services/precompute_feed_service.rb @@ -3,6 +3,7 @@ class PrecomputeFeedService < BaseService def call(account) FeedManager.instance.populate_feed(account) + FeedManager.instance.populate_direct_feed(account) ensure Redis.current.del("account:#{account.id}:regeneration") end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 98972fc70..9d5d0fc14 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -48,6 +48,7 @@ class RemoveStatusService < BaseService def remove_from_self FeedManager.instance.unpush_from_home(@account, @status) + FeedManager.instance.unpush_from_direct(@account, @status) if @status.direct_visibility? end def remove_from_followers @@ -159,9 +160,8 @@ class RemoveStatusService < BaseService def remove_from_direct @mentions.each do |mention| - Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? + FeedManager.instance.unpush_from_direct(mention.account, @status) if mention.account.local? end - Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local? end def lock_options diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb index b98759bf6..bbdc0a595 100644 --- a/app/services/resolve_url_service.rb +++ b/app/services/resolve_url_service.rb @@ -18,9 +18,9 @@ class ResolveURLService < BaseService private def process_url - if equals_or_includes_any?(type, %w(Application Group Organization Person Service)) + if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) FetchRemoteAccountService.new.call(atom_url, body, protocol) - elsif equals_or_includes_any?(type, %w(Note Article Image Video Page Question)) + elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES) FetchRemoteStatusService.new.call(atom_url, body, protocol) end end diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 9577c10b5..1709c9c84 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -33,6 +33,9 @@ = f.input :setting_display_media, collection: ['default', 'show_all', 'hide_all'],label_method: lambda { |item| t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label .fields-group + = f.input :setting_use_blurhash, as: :boolean, wrapper: :with_label + + .fields-group = f.input :setting_expand_spoilers, as: :boolean, wrapper: :with_label .actions diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb index 1ae3c877b..546f5c0c2 100644 --- a/app/workers/feed_insert_worker.rb +++ b/app/workers/feed_insert_worker.rb @@ -13,6 +13,8 @@ class FeedInsertWorker when :list @list = List.find(id) @follower = @list.account + when :direct + @account = Account.find(id) end check_and_insert @@ -29,7 +31,12 @@ class FeedInsertWorker def feed_filtered? # Note: Lists are a variation of home, so the filtering rules # of home apply to both - FeedManager.instance.filter?(:home, @status, @follower.id) + case @type + when :home, :list + FeedManager.instance.filter?(:home, @status, @follower.id) + when :direct + FeedManager.instance.filter?(:direct, @status, @account.id) + end end def perform_push @@ -38,6 +45,8 @@ class FeedInsertWorker FeedManager.instance.push_to_home(@follower, @status) when :list FeedManager.instance.push_to_list(@list, @status) + when :direct + FeedManager.instance.push_to_direct(@account, @status) end end end diff --git a/app/workers/scheduler/feed_cleanup_scheduler.rb b/app/workers/scheduler/feed_cleanup_scheduler.rb index bf5e20757..4933f1753 100644 --- a/app/workers/scheduler/feed_cleanup_scheduler.rb +++ b/app/workers/scheduler/feed_cleanup_scheduler.rb @@ -9,6 +9,7 @@ class Scheduler::FeedCleanupScheduler def perform clean_home_feeds! clean_list_feeds! + clean_direct_feeds! end private @@ -21,6 +22,10 @@ class Scheduler::FeedCleanupScheduler clean_feeds!(inactive_list_ids, :list) end + def clean_direct_feeds! + clean_feeds!(inactive_account_ids, :direct) + end + def clean_feeds!(ids, type) reblogged_id_sets = {} |