diff --git a/app/controllers/api/v1/lists/tags_controller.rb b/app/controllers/api/v1/lists/tags_controller.rb index 6d71ee0d13ef42..3dd77aa416b10d 100644 --- a/app/controllers/api/v1/lists/tags_controller.rb +++ b/app/controllers/api/v1/lists/tags_controller.rb @@ -44,13 +44,13 @@ def load_tags end def list_tags - names = tag_ids.select{|t| t !=~ /\A[0-9]+\Z/} - ids = tag_ids.select{|t| t =~ /\A[0-9]+\Z/} - existing_by_name = Tag.where(name: names.map{|n| Tag.normalize(n)}).select(:id, :name) - ids.push(*existing_by_name.map {|t| t.id}) - not_existing_by_name = names.select{|n| !existing_by_name.any? {|e| e.name == Tag.normalize(n)}} + names = tag_ids.reject { |t| t =~ /\A[0-9]+\Z/ } + ids = tag_ids.select { |t| t =~ /\A[0-9]+\Z/ } + existing_by_name = Tag.where(name: names.map { |n| Tag.normalize(n) }).select(:id, :name) + ids.push(*existing_by_name.map { |t| t.id }) + not_existing_by_name = names.reject { |n| existing_by_name.any? { |e| e.name == Tag.normalize(n) }} created = Tag.find_or_create_by_names(not_existing_by_name) - ids.push(*created.map {|t| t.id}) + ids.push(*created.map(&:id) Tag.find(ids) end diff --git a/app/javascript/flavours/glitch/actions/importer/index.js b/app/javascript/flavours/glitch/actions/importer/index.js index 46be1107a22b45..6b1b0b35141ec8 100644 --- a/app/javascript/flavours/glitch/actions/importer/index.js +++ b/app/javascript/flavours/glitch/actions/importer/index.js @@ -55,7 +55,7 @@ export function importFetchedAccounts(accounts) { } export function importFetchedTags(tags) { - return (dispatch, getState) => { + return (dispatch) => { const uniqueTags = []; function processTag(tag) { pushUnique(uniqueTags, tag); diff --git a/app/javascript/flavours/glitch/features/list_editor/components/add_tag.jsx b/app/javascript/flavours/glitch/features/list_editor/components/add_tag.jsx index 490cf3668658de..1bd4a9e965ced8 100644 --- a/app/javascript/flavours/glitch/features/list_editor/components/add_tag.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/components/add_tag.jsx @@ -11,8 +11,7 @@ import CancelIcon from '@/material-icons/400-24px/cancel.svg?react'; import TagIcon from '@/material-icons/400-24px/tag.svg?react'; import { Icon } from 'flavours/glitch/components/icon'; -import { changeListSuggestions } from '../../../actions/lists'; -import { addToListEditor } from '../../../actions/lists'; +import { addToListEditor, changeListSuggestions } from '../../../actions/lists'; const messages = defineMessages({ addtag: { id: 'lists.addtag', defaultMessage: 'Enter a tag you\'d like to follow' }, @@ -33,6 +32,7 @@ class AddTag extends PureComponent { intl: PropTypes.object.isRequired, value: PropTypes.string.isRequired, onSubmit: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, }; handleChange = e => { diff --git a/app/javascript/flavours/glitch/features/list_editor/components/tag.jsx b/app/javascript/flavours/glitch/features/list_editor/components/tag.jsx index 5a8761c5e76461..d7d808a52f37cd 100644 --- a/app/javascript/flavours/glitch/features/list_editor/components/tag.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/components/tag.jsx @@ -5,8 +5,8 @@ import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import TagIcon from '@/material-icons/400-24px/tag.svg?react'; import CloseIcon from '@/material-icons/400-24px/close.svg?react'; +import TagIcon from '@/material-icons/400-24px/tag.svg?react'; import { Icon } from 'flavours/glitch/components/icon'; import { removeFromListEditor, addToListEditor } from '../../../actions/lists'; @@ -18,12 +18,10 @@ const messages = defineMessages({ }); const makeMapStateToProps = () => { - const mapStateToProps = (state, { tag, added }) => { - return { - tag: tag, - added: typeof added === 'undefined' ? state.getIn(['listEditor', 'tags', 'items']).includes(tag) : added, - } - }; + const mapStateToProps = (state, { tag, added }) => ({ + tag: tag, + added: typeof added === 'undefined' ? state.getIn(['listEditor', 'tags', 'items']).includes(tag) : added, + }); return mapStateToProps; }; diff --git a/app/javascript/flavours/glitch/features/list_editor/index.jsx b/app/javascript/flavours/glitch/features/list_editor/index.jsx index cfe947306675ad..5b58e69a145f7c 100644 --- a/app/javascript/flavours/glitch/features/list_editor/index.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/index.jsx @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; -import { injectIntl } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -12,10 +12,15 @@ import { setupListEditor, clearListSuggestions, resetListEditor } from '../../ac import Motion from '../ui/util/optional_motion'; import Account from './components/account'; -import Tag from './components/tag'; +import AddTag from './components/add_tag'; import EditListForm from './components/edit_list_form'; import Search from './components/search'; -import AddTag from './components/add_tag'; +import Tag from './components/tag'; + +const messages = defineMessages({ + account_tab: { id: 'lists.account_tab', defaultMessage: 'Accounts' }, + tag_tab: { id: 'lists.tag_tab', defaultMessage: 'Tags' }, +}); const mapStateToProps = state => ({ tags: state.getIn(['listEditor', 'tags', 'items']), @@ -35,6 +40,7 @@ class ListEditor extends ImmutablePureComponent { }; static propTypes = { + intl: PropTypes.object.isRequired, listId: PropTypes.string.isRequired, onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -46,31 +52,39 @@ class ListEditor extends ImmutablePureComponent { searchAccountIds: ImmutablePropTypes.list.isRequired, }; - componentDidMount () { + componentDidMount() { const { onInitialize, listId } = this.props; onInitialize(listId); } - componentWillUnmount () { + componentWillUnmount() { const { onReset } = this.props; onReset(); } + switchToAccounts() { + this.switchToTab('accounts'); + } + + switchToTags() { + this.switchToTab('tags'); + } + switchToTab(tab) { this.setState({ ...this.state, currentTab: tab }); } - render () { - const { accountIds, tags, searchAccountIds, onClear } = this.props; + render() { + const { accountIds, tags, searchAccountIds, onClear, intl } = this.props; const showSearch = searchAccountIds.size > 0; return (
- this.switchToTab('accounts')} className={'tab ' + ('accounts' == this.state.currentTab ? 'tab__active' : '')}>Accounts ({accountIds.size}) - this.switchToTab('tags')} className={'tab ' + ('tags' == this.state.currentTab ? 'tab__active' : '')}>Tags ({tags.size}) +
{intl.formatMessage(messages.account_tab)} ({accountIds.size})
+
{intl.formatMessage(messages.tag_tab)} ({tags.size})
-
+
@@ -88,7 +102,7 @@ class ListEditor extends ImmutablePureComponent {
-
+
diff --git a/app/javascript/flavours/glitch/locales/en.json b/app/javascript/flavours/glitch/locales/en.json index 8de7059787ed96..0e8750b47c250b 100644 --- a/app/javascript/flavours/glitch/locales/en.json +++ b/app/javascript/flavours/glitch/locales/en.json @@ -53,6 +53,11 @@ "keyboard_shortcuts.bookmark": "to bookmark", "keyboard_shortcuts.secondary_toot": "to send toot using secondary privacy setting", "keyboard_shortcuts.toggle_collapse": "to collapse/uncollapse toots", + "lists.account_tab": "Accounts", + "lists.addtag": "Enter a tag you'd like to follow", + "lists.tag.add": "Add to list", + "lists.tag.remove": "Remove from list", + "lists.tag_tab": "Tags", "moved_to_warning": "This account is marked as moved to {moved_to_link}, and may thus not accept new follows.", "navigation_bar.app_settings": "App settings", "navigation_bar.featured_users": "Featured users", @@ -156,4 +161,4 @@ "status.local_only": "Only visible from your instance", "status.uncollapse": "Uncollapse", "suggestions.dismiss": "Dismiss suggestion" -} +} \ No newline at end of file diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 97224423d6d66c..cf2d5e00557086 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -7783,6 +7783,7 @@ noscript { .tab__container { display: flex; + .tab { flex-grow: 1; flex-basis: 0; @@ -7791,11 +7792,13 @@ noscript { background: $ui-base-color; text-align: center; } + .tab.tab__active { font-weight: bold; background: lighten($ui-base-color, 13%); } } + .tab__inactive { display: none; } @@ -7806,12 +7809,17 @@ noscript { } .list_tag { + padding: 10px; // glitch: reduced padding + border-bottom: 1px solid lighten($ui-base-color, 8%); + gap: 10px; display: flex; justify-content: space-between; align-items: center; + .list_tag__display-name { flex-grow: 1; } + .list_tag__relationship { flex-grow: 0; } diff --git a/app/models/list_tag.rb b/app/models/list_tag.rb index 3b532771729a3a..0397c501cf2d8a 100644 --- a/app/models/list_tag.rb +++ b/app/models/list_tag.rb @@ -14,7 +14,4 @@ class ListTag < ApplicationRecord belongs_to :tag validates :tag_id, uniqueness: { scope: :list_id } - - private - end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 71f39036759a3a..f006ff08983d75 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -114,9 +114,9 @@ def deliver_to_hashtag_followers! def deliver_to_lists! @status.tags.each do |tag| - FeedInsertWorker.push_bulk(tag.lists) do |list| - [@status.id, list.id, 'list', { 'update' => update? }] - end + FeedInsertWorker.push_bulk(tag.lists) do |list| + [@status.id, list.id, 'list', { 'update' => update? }] + end end @account.lists_for_local_distribution.select(:id).reorder(nil).find_in_batches do |lists| FeedInsertWorker.push_bulk(lists) do |list| diff --git a/config/routes/api.rb b/config/routes/api.rb index 77af2519cd927c..5830c21f95c0bb 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -204,8 +204,8 @@ resources :followed_tags, only: [:index] resources :lists, only: [:index, :create, :show, :update, :destroy] do - resource :accounts, only: [:show, :create, :destroy], controller: 'lists/accounts' - resource :tags, only: [:show, :create, :destroy], controller: 'lists/tags' + resource :accounts, only: [:show, :create, :destroy], controller: 'lists/accounts' + resource :tags, only: [:show, :create, :destroy], controller: 'lists/tags' end namespace :featured_tags do diff --git a/db/migrate/20240309162900_list_tags.rb b/db/migrate/20240309162900_list_tags.rb index d6d8033cfce302..eed4753ab46fa9 100644 --- a/db/migrate/20240309162900_list_tags.rb +++ b/db/migrate/20240309162900_list_tags.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + class ListTags < ActiveRecord::Migration[7.1] def change - create_table :list_tags do |t| - t.belongs_to :list, foreign_key: { on_delete: :cascade }, null: false - t.belongs_to :tag, foreign_key: { on_delete: :cascade }, null: false - end - - add_index :list_tags, [:tag_id, :list_id], unique: true - add_index :list_tags, [:list_id, :tag_id] + create_table :list_tags do |t| + t.belongs_to :list, foreign_key: { on_delete: :cascade }, null: false + t.belongs_to :tag, foreign_key: { on_delete: :cascade }, null: false + end + + add_index :list_tags, [:tag_id, :list_id], unique: true + add_index :list_tags, [:list_id, :tag_id] end end