diff --git a/app/javascript/mastodon/api_types/accounts.ts b/app/javascript/mastodon/api_types/accounts.ts
index b5ebf08a228e35..2b1d4f7a738e87 100644
--- a/app/javascript/mastodon/api_types/accounts.ts
+++ b/app/javascript/mastodon/api_types/accounts.ts
@@ -62,6 +62,7 @@ export interface BaseApiAccountJSON {
other_settings: ApiAccountOtherSettingsJSON;
roles?: ApiAccountJSON[];
server_features: ApiServerFeaturesJSON;
+ software: string;
statuses_count: number;
uri: string;
url?: string;
diff --git a/app/javascript/mastodon/features/account/components/domain_pill.tsx b/app/javascript/mastodon/features/account/components/domain_pill.tsx
index c60397448bda2c..6c2a3b0983be18 100644
--- a/app/javascript/mastodon/features/account/components/domain_pill.tsx
+++ b/app/javascript/mastodon/features/account/components/domain_pill.tsx
@@ -14,8 +14,9 @@ import { Icon } from 'mastodon/components/icon';
export const DomainPill: React.FC<{
domain: string;
username: string;
+ software: string;
isSelf: boolean;
-}> = ({ domain, username, isSelf }) => {
+}> = ({ domain, username, software, isSelf }) => {
const accessibilityId = useId();
const [open, setOpen] = useState(false);
const [expanded, setExpanded] = useState(false);
@@ -126,6 +127,11 @@ export const DomainPill: React.FC<{
id='domain_pill.server'
defaultMessage='Server'
/>
+ {!isSelf && software && (
+
+ ({software})
+
+ )}
{isSelf ? (
@@ -134,10 +140,25 @@ export const DomainPill: React.FC<{
defaultMessage='Your digital home, where all of your posts live. Don’t like this one? Transfer servers at any time and bring your followers, too.'
/>
) : (
-
+ <>
+
+ {software && (
+ (
+
+ {software}
+
+ ),
+ }}
+ />
+ )}
+ >
)}
diff --git a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx b/app/javascript/mastodon/features/account_timeline/components/account_header.tsx
index 4f9cf8e412ad0e..16dae8fa06e205 100644
--- a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/account_header.tsx
@@ -926,6 +926,7 @@ export const AccountHeader: React.FC<{
{lockedIcon}
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 673dffebb5d17d..db3d86bd4db9db 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -428,6 +428,7 @@
"domain_pill.server": "Server",
"domain_pill.their_handle": "Their handle:",
"domain_pill.their_server": "Their digital home, where all of their posts live.",
+ "domain_pill.their_server_software": "This server is using unknown software, but you can view posts and participate in conversations just like other users.",
"domain_pill.their_username": "Their unique identifier on their server. It’s possible to find users with the same username on different servers.",
"domain_pill.username": "Username",
"domain_pill.whats_in_a_handle": "What's in a handle?",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index f688aadecb6a64..ede42211dadd2b 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -405,6 +405,7 @@
"domain_pill.server": "サーバー",
"domain_pill.their_handle": "このユーザーのハンドル:",
"domain_pill.their_server": "ユーザーの仮想の住所です。そのユーザーIDによるすべての投稿を保持しています。",
+ "domain_pill.their_server_software": "このサーバーはunknownという名前のソフトウェアを使用していますが、他のサーバーと同様に投稿を表示したり、会話に参加できます。",
"domain_pill.their_username": "ユーザーを識別する名前です。ユーザー名はひとつのサーバー内においては唯一無二の名前ですが、ほかのサーバーには同名のユーザーがいることもあります。",
"domain_pill.username": "ユーザー名",
"domain_pill.whats_in_a_handle": "ユーザーハンドルについて",
diff --git a/app/javascript/mastodon/models/account.ts b/app/javascript/mastodon/models/account.ts
index 199328768aedd9..11f59dd1d11f9b 100644
--- a/app/javascript/mastodon/models/account.ts
+++ b/app/javascript/mastodon/models/account.ts
@@ -101,6 +101,7 @@ export const accountDefaultValues: AccountShape = {
display_name: '',
display_name_html: '',
server_features: AccountServerFeaturesFactory(),
+ software: '',
emojis: ImmutableList(),
fields: ImmutableList(),
group: false,
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index b30a967667f566..2f9a0b5d007098 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -2259,6 +2259,16 @@
font-weight: 500;
color: $primary-text-color;
}
+
+ &__software-name {
+ font-weight: 500;
+ color: $highlight-text-color;
+ }
+
+ &__header-software-name {
+ font-size: 12px;
+ margin-inline-start: 8px;
+ }
}
}
}
diff --git a/app/javascript/testing/factories.ts b/app/javascript/testing/factories.ts
index 22739e7630e930..ec0436dc4dbff9 100644
--- a/app/javascript/testing/factories.ts
+++ b/app/javascript/testing/factories.ts
@@ -48,6 +48,7 @@ export const accountFactory: FactoryFunction = ({
noindex: false,
roles: [],
hide_collections: false,
+ software: 'mastodon',
other_settings: {
hide_followers_count: false,
hide_following_count: false,
diff --git a/app/models/instance_info.rb b/app/models/instance_info.rb
index 335e8f84854745..d1bdf68b2a2dde 100644
--- a/app/models/instance_info.rb
+++ b/app/models/instance_info.rb
@@ -82,6 +82,12 @@ def no_language_flag_software?(domain)
NO_LANGUAGE_FLAG_SOFTWARES.include?(software_name(domain))
end
+ def software_name(domain)
+ return 'kmyblue' unless domain
+
+ Rails.cache.fetch("software_name:#{domain}") { load_software_name(domain) }
+ end
+
private
def load_available_features(domain)
@@ -118,10 +124,6 @@ def metadata_features(info)
info.data['metadata']['features']
end
- def software_name(domain)
- Rails.cache.fetch("software_name:#{domain}") { load_software_name(domain) }
- end
-
def load_software_name(domain)
return 'threads' if domain == 'threads.net'
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index b927ec562a0b7f..68ff439cec38b3 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -9,7 +9,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :indexable, :group, :created_at,
:note, :url, :uri, :avatar, :avatar_static, :header, :header_static, :subscribable,
:followers_count, :following_count, :statuses_count, :last_status_at, :hide_collections, :other_settings, :noindex,
- :server_features
+ :server_features, :software
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
@@ -124,6 +124,10 @@ def server_features
InstanceInfo.available_features(object.domain)
end
+ def software
+ InstanceInfo.software_name(object.domain)
+ end
+
def moved_to_account
object.unavailable? ? nil : AccountDecorator.new(object.moved_to_account)
end
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 2922ee3e636235..a948d8940f474b 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -2,7 +2,7 @@
module Mastodon
module Version
- KMYBLUE_API_VERSION = 4
+ KMYBLUE_API_VERSION = 5
module_function