Add a user setting to show/hide domains on remote usernames (#1254)
Adds a user toggle in the preferences menu: > Show full username (including domain) for remote users It only shortens the username of local accounts. The main reason for this is so that there is a clear visual indicator of who is local on a thread -- this is important for local-only posting reasons. But we've been using it on Friend Camp for 3 years now and it's actually really nice for getting a sense of who is on what server, too. The bulk of this work was done by Callie on Friend Camp in October 2019. Fixes #1247
This commit is contained in:
parent
60746ab437
commit
6281823df0
|
@ -70,6 +70,8 @@ Metrics/AbcSize:
|
||||||
Max: 115
|
Max: 115
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/mastodon/*_cli.rb'
|
- 'lib/mastodon/*_cli.rb'
|
||||||
|
AllowedMethods:
|
||||||
|
- process_update
|
||||||
|
|
||||||
Metrics/BlockLength:
|
Metrics/BlockLength:
|
||||||
Max: 55
|
Max: 55
|
||||||
|
@ -92,6 +94,8 @@ Metrics/CyclomaticComplexity:
|
||||||
Max: 25
|
Max: 25
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/mastodon/*_cli.rb'
|
- 'lib/mastodon/*_cli.rb'
|
||||||
|
AllowedMethods:
|
||||||
|
- process_update
|
||||||
|
|
||||||
Layout/LineLength:
|
Layout/LineLength:
|
||||||
AllowURI: true
|
AllowURI: true
|
||||||
|
@ -113,6 +117,8 @@ Metrics/ParameterLists:
|
||||||
|
|
||||||
Metrics/PerceivedComplexity:
|
Metrics/PerceivedComplexity:
|
||||||
Max: 25
|
Max: 25
|
||||||
|
AllowedMethods:
|
||||||
|
- process_update
|
||||||
|
|
||||||
Naming/MemoizedInstanceVariableName:
|
Naming/MemoizedInstanceVariableName:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
|
@ -57,6 +57,7 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_trends,
|
:setting_trends,
|
||||||
:setting_crop_images,
|
:setting_crop_images,
|
||||||
:setting_always_send_emails,
|
:setting_always_send_emails,
|
||||||
|
:setting_expand_usernames,
|
||||||
notification_emails: %i(follow follow_request reblog favourite mention report pending_account trending_tag appeal),
|
notification_emails: %i(follow follow_request reblog favourite mention report pending_account trending_tag appeal),
|
||||||
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,12 @@ import Permalink from './permalink';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import PollContainer from 'mastodon/containers/poll_container';
|
import PollContainer from 'mastodon/containers/poll_container';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import { autoPlayGif, languages as preloadedLanguages, translationEnabled } from 'mastodon/initial_state';
|
import {
|
||||||
|
autoPlayGif,
|
||||||
|
languages as preloadedLanguages,
|
||||||
|
translationEnabled,
|
||||||
|
expandUsernames,
|
||||||
|
} from 'mastodon/initial_state';
|
||||||
|
|
||||||
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
||||||
|
|
||||||
|
@ -96,6 +101,14 @@ class StatusContent extends React.PureComponent {
|
||||||
if (mention) {
|
if (mention) {
|
||||||
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
|
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
|
||||||
link.setAttribute('title', mention.get('acct'));
|
link.setAttribute('title', mention.get('acct'));
|
||||||
|
// Hometown: make remote usernames
|
||||||
|
if (expandUsernames) {
|
||||||
|
if (mention.get('acct') === mention.get('username')) {
|
||||||
|
link.innerHTML = `@<span class="hometown-mention-local">${mention.get('username')}</span>`;
|
||||||
|
} else {
|
||||||
|
link.innerHTML = `@<span class="hometown-mention-remote">${mention.get('acct')}</span>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
|
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
|
||||||
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
|
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -254,7 +267,9 @@ class StatusContent extends React.PureComponent {
|
||||||
|
|
||||||
const mentionLinks = status.get('mentions').map(item => (
|
const mentionLinks = status.get('mentions').map(item => (
|
||||||
<Permalink to={`/@${item.get('acct')}`} href={item.get('url')} key={item.get('id')} className='status-link mention'>
|
<Permalink to={`/@${item.get('acct')}`} href={item.get('url')} key={item.get('id')} className='status-link mention'>
|
||||||
@<span>{item.get('username')}</span>
|
@<span className={item.get('acct') === item.get('username') ? 'fc_mention_local' : 'fc_mention_remote'}>
|
||||||
|
{expandUsernames ? item.get('acct') : item.get('username')}
|
||||||
|
</span>
|
||||||
</Permalink>
|
</Permalink>
|
||||||
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);
|
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);
|
||||||
|
|
||||||
|
@ -277,7 +292,7 @@ class StatusContent extends React.PureComponent {
|
||||||
<div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''} ${status.get('activity_pub_type') === 'Article' ? 'article-type' : ''} translate`} lang={lang} dangerouslySetInnerHTML={content} />
|
<div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''} ${status.get('activity_pub_type') === 'Article' ? 'article-type' : ''} translate`} lang={lang} dangerouslySetInnerHTML={content} />
|
||||||
{!hidden && poll}
|
{!hidden && poll}
|
||||||
{!hidden && translateButton}
|
{!hidden && translateButton}
|
||||||
</div>
|
</div>,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (status.get('activity_pub_type') === 'Article' && !this.props.expanded) {
|
if (status.get('activity_pub_type') === 'Article' && !this.props.expanded) {
|
||||||
|
|
|
@ -111,6 +111,8 @@ export const disabledAccountId = getMeta('disabled_account_id');
|
||||||
export const displayMedia = getMeta('display_media');
|
export const displayMedia = getMeta('display_media');
|
||||||
export const domain = getMeta('domain');
|
export const domain = getMeta('domain');
|
||||||
export const expandSpoilers = getMeta('expand_spoilers');
|
export const expandSpoilers = getMeta('expand_spoilers');
|
||||||
|
// Hometown: expand usernames
|
||||||
|
export const expandUsernames = getMeta('expand_usernames');
|
||||||
export const forceSingleColumn = !getMeta('advanced_layout');
|
export const forceSingleColumn = !getMeta('advanced_layout');
|
||||||
export const limitedFederationMode = getMeta('limited_federation_mode');
|
export const limitedFederationMode = getMeta('limited_federation_mode');
|
||||||
export const mascot = getMeta('mascot');
|
export const mascot = getMeta('mascot');
|
||||||
|
|
|
@ -25,6 +25,7 @@ class UserSettingsDecorator
|
||||||
user.settings['boost_modal'] = boost_modal_preference if change?('setting_boost_modal')
|
user.settings['boost_modal'] = boost_modal_preference if change?('setting_boost_modal')
|
||||||
user.settings['delete_modal'] = delete_modal_preference if change?('setting_delete_modal')
|
user.settings['delete_modal'] = delete_modal_preference if change?('setting_delete_modal')
|
||||||
user.settings['auto_play_gif'] = auto_play_gif_preference if change?('setting_auto_play_gif')
|
user.settings['auto_play_gif'] = auto_play_gif_preference if change?('setting_auto_play_gif')
|
||||||
|
user.settings['expand_usernames'] = expand_usernames_preference if change?('setting_expand_usernames')
|
||||||
user.settings['display_media'] = display_media_preference if change?('setting_display_media')
|
user.settings['display_media'] = display_media_preference if change?('setting_display_media')
|
||||||
user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers')
|
user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers')
|
||||||
user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion')
|
user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion')
|
||||||
|
@ -83,6 +84,10 @@ class UserSettingsDecorator
|
||||||
boolean_cast_setting 'setting_auto_play_gif'
|
boolean_cast_setting 'setting_auto_play_gif'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def expand_usernames_preference
|
||||||
|
boolean_cast_setting 'setting_expand_usernames'
|
||||||
|
end
|
||||||
|
|
||||||
def display_media_preference
|
def display_media_preference
|
||||||
settings['setting_display_media']
|
settings['setting_display_media']
|
||||||
end
|
end
|
||||||
|
|
|
@ -135,7 +135,7 @@ class User < ApplicationRecord
|
||||||
:reduce_motion, :system_font_ui, :noindex, :norss, :theme, :display_media,
|
:reduce_motion, :system_font_ui, :noindex, :norss, :theme, :display_media,
|
||||||
:expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
|
:expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
|
||||||
:advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images,
|
:advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images,
|
||||||
:disable_swiping, :default_federation, :always_send_emails,
|
:disable_swiping, :default_federation, :always_send_emails, :expand_usernames,
|
||||||
to: :settings, prefix: :setting, allow_nil: false
|
to: :settings, prefix: :setting, allow_nil: false
|
||||||
|
|
||||||
delegate :can?, to: :role
|
delegate :can?, to: :role
|
||||||
|
|
|
@ -44,6 +44,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
store[:boost_modal] = object.current_account.user.setting_boost_modal
|
store[:boost_modal] = object.current_account.user.setting_boost_modal
|
||||||
store[:delete_modal] = object.current_account.user.setting_delete_modal
|
store[:delete_modal] = object.current_account.user.setting_delete_modal
|
||||||
store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif
|
store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif
|
||||||
|
store[:expand_usernames] = object.current_account.user.setting_expand_usernames
|
||||||
store[:display_media] = object.current_account.user.setting_display_media
|
store[:display_media] = object.current_account.user.setting_display_media
|
||||||
store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers
|
store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers
|
||||||
store[:reduce_motion] = object.current_account.user.setting_reduce_motion
|
store[:reduce_motion] = object.current_account.user.setting_reduce_motion
|
||||||
|
@ -76,11 +77,11 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
store = {}
|
store = {}
|
||||||
|
|
||||||
if object.current_account
|
if object.current_account
|
||||||
store[:me] = object.current_account.id.to_s
|
store[:me] = object.current_account.id.to_s
|
||||||
store[:default_privacy] = object.visibility || object.current_account.user.setting_default_privacy
|
store[:default_privacy] = object.visibility || object.current_account.user.setting_default_privacy
|
||||||
store[:default_sensitive] = object.current_account.user.setting_default_sensitive
|
store[:default_sensitive] = object.current_account.user.setting_default_sensitive
|
||||||
store[:default_federation] = object.current_account.user.setting_default_federation
|
store[:default_federation] = object.current_account.user.setting_default_federation
|
||||||
store[:default_language] = object.current_account.user.preferred_posting_language
|
store[:default_language] = object.current_account.user.preferred_posting_language
|
||||||
end
|
end
|
||||||
|
|
||||||
store[:text] = object.text if object.text
|
store[:text] = object.text if object.text
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
= f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label
|
= f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label
|
||||||
= f.input :setting_disable_swiping, as: :boolean, wrapper: :with_label
|
= f.input :setting_disable_swiping, as: :boolean, wrapper: :with_label
|
||||||
= f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
|
= f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
|
||||||
|
= f.input :setting_expand_usernames, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
%h4= t 'appearance.toot_layout'
|
%h4= t 'appearance.toot_layout'
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ en:
|
||||||
setting_display_media_hide_all: Hide all
|
setting_display_media_hide_all: Hide all
|
||||||
setting_display_media_show_all: Show all
|
setting_display_media_show_all: Show all
|
||||||
setting_expand_spoilers: Always expand posts marked with content warnings
|
setting_expand_spoilers: Always expand posts marked with content warnings
|
||||||
|
setting_expand_usernames: Show full username (including domain) for remote users
|
||||||
setting_hide_network: Hide your social graph
|
setting_hide_network: Hide your social graph
|
||||||
setting_noindex: Opt-out of search engine indexing for your profile page
|
setting_noindex: Opt-out of search engine indexing for your profile page
|
||||||
setting_norss: Opt-out of an RSS feed for your public posts
|
setting_norss: Opt-out of an RSS feed for your public posts
|
||||||
|
|
|
@ -24,6 +24,7 @@ defaults: &defaults
|
||||||
auto_play_gif: false
|
auto_play_gif: false
|
||||||
display_media: 'default'
|
display_media: 'default'
|
||||||
expand_spoilers: false
|
expand_spoilers: false
|
||||||
|
expand_usernames: true
|
||||||
preview_sensitive_media: false
|
preview_sensitive_media: false
|
||||||
reduce_motion: false
|
reduce_motion: false
|
||||||
disable_swiping: false
|
disable_swiping: false
|
||||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe Settings::ScopedSettings do
|
||||||
let(:object) { Fabricate(:user) }
|
let(:object) { Fabricate(:user) }
|
||||||
let(:scoped_setting) { described_class.new(object) }
|
let(:scoped_setting) { described_class.new(object) }
|
||||||
let(:val) { 'whatever' }
|
let(:val) { 'whatever' }
|
||||||
let(:methods) { %i(auto_play_gif default_sensitive unfollow_modal boost_modal delete_modal reduce_motion system_font_ui noindex theme) }
|
let(:methods) { %i(auto_play_gif expand_usernames default_sensitive unfollow_modal boost_modal delete_modal reduce_motion system_font_ui noindex theme) }
|
||||||
|
|
||||||
describe '.initialize' do
|
describe '.initialize' do
|
||||||
it 'sets @object' do
|
it 'sets @object' do
|
||||||
|
|
|
@ -63,6 +63,13 @@ describe UserSettingsDecorator do
|
||||||
expect(user.settings['auto_play_gif']).to eq false
|
expect(user.settings['auto_play_gif']).to eq false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'updates the user settings value for username expansion' do
|
||||||
|
values = { 'setting_expand_usernames' => '0'}
|
||||||
|
|
||||||
|
settings.update(values)
|
||||||
|
expect(user.settings['expand_usernames'].to eq false)
|
||||||
|
end
|
||||||
|
|
||||||
it 'updates the user settings value for system font in UI' do
|
it 'updates the user settings value for system font in UI' do
|
||||||
values = { 'setting_system_font_ui' => '0' }
|
values = { 'setting_system_font_ui' => '0' }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue