Add Misskey location, birthday, and isCat
This commit is contained in:
parent
1128e473c6
commit
1e6fbdea3a
41 changed files with 320 additions and 57 deletions
|
@ -21,7 +21,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
|
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, :birthday, :location, fields_attributes: [:name, :value])
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_settings_params
|
def user_settings_params
|
||||||
|
|
|
@ -76,6 +76,7 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_hide_statuses_count,
|
:setting_hide_statuses_count,
|
||||||
:setting_hide_following_count,
|
:setting_hide_following_count,
|
||||||
:setting_hide_followers_count,
|
:setting_hide_followers_count,
|
||||||
|
:setting_disable_joke_appearance,
|
||||||
notification_emails: %i(follow follow_request reblog favourite emoji_reaction mention digest report pending_account trending_tag),
|
notification_emails: %i(follow follow_request reblog favourite emoji_reaction mention digest report pending_account trending_tag),
|
||||||
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Settings::ProfilesController < Settings::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
|
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, :birthday, :location, fields_attributes: [:name, :value])
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_account
|
def set_account
|
||||||
|
|
|
@ -98,6 +98,26 @@ module AccountsHelper
|
||||||
[prepend_str, account.note].join(' · ')
|
[prepend_str, account.note].join(' · ')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def account_cat_params(account, **options)
|
||||||
|
result = options || {}
|
||||||
|
result.merge!({ 'data-acct': account.acct })
|
||||||
|
|
||||||
|
return result unless !current_user&.setting_disable_joke_appearance && account.other_settings['is_cat']
|
||||||
|
|
||||||
|
@cat_inline_styles ||= {}
|
||||||
|
@cat_inline_styles[account.acct] = account.cat_ears_color if account.cat_ears_color
|
||||||
|
|
||||||
|
result.merge!({ class: [options[:class], 'cat'].compact.join(' ') })
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_cat_styles
|
||||||
|
return if @cat_inline_styles.nil?
|
||||||
|
|
||||||
|
@cat_inline_styles.map do |acct, color|
|
||||||
|
".cat[data-acct=\"#{h(acct)}\"] { --cat-ears-color: #{h(color)}; }"
|
||||||
|
end.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
def svg_logo
|
def svg_logo
|
||||||
content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976')
|
content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976')
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,6 +27,8 @@ module ContextHelper
|
||||||
quote_uri: { 'fedibird' => 'http://fedibird.com/ns#', 'quoteUri' => 'fedibird:quoteUri' },
|
quote_uri: { 'fedibird' => 'http://fedibird.com/ns#', 'quoteUri' => 'fedibird:quoteUri' },
|
||||||
expiry: { 'fedibird' => 'http://fedibird.com/ns#', 'expiry' => 'fedibird:expiry' },
|
expiry: { 'fedibird' => 'http://fedibird.com/ns#', 'expiry' => 'fedibird:expiry' },
|
||||||
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
|
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
|
||||||
|
is_cat: { 'misskey' => 'https://misskey-hub.net/ns#', 'isCat' => 'misskey:isCat' },
|
||||||
|
vcard: { 'vcard' => 'http://www.w3.org/2006/vcard/ns#' },
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def full_context
|
def full_context
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { autoPlayGif } from '../initial_state';
|
import classNames from 'classnames';
|
||||||
|
import { autoPlayGif, disable_joke_appearance } from '../initial_state';
|
||||||
|
|
||||||
export default class Avatar extends React.PureComponent {
|
export default class Avatar extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -38,19 +39,18 @@ export default class Avatar extends React.PureComponent {
|
||||||
const { hovering } = this.state;
|
const { hovering } = this.state;
|
||||||
|
|
||||||
const src = account.get('avatar');
|
const src = account.get('avatar');
|
||||||
|
const isCat = !disable_joke_appearance && account.getIn(['other_settings', 'is_cat']);
|
||||||
|
const catEarsColor = !disable_joke_appearance && account.getIn(['other_settings', 'cat_ears_color']);
|
||||||
const staticSrc = account.get('avatar_static');
|
const staticSrc = account.get('avatar_static');
|
||||||
|
|
||||||
let className = 'account__avatar';
|
const catEarsColorStyle = catEarsColor ? { '--cat-ears-color': catEarsColor } : {};
|
||||||
|
|
||||||
if (inline) {
|
|
||||||
className = className + ' account__avatar-inline';
|
|
||||||
}
|
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
...this.props.style,
|
...this.props.style,
|
||||||
width: `${size}px`,
|
width: `${size}px`,
|
||||||
height: `${size}px`,
|
height: `${size}px`,
|
||||||
backgroundSize: `${size}px ${size}px`,
|
backgroundSize: `${size}px ${size}px`,
|
||||||
|
...catEarsColorStyle,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hovering || animate) {
|
if (hovering || animate) {
|
||||||
|
@ -61,7 +61,8 @@ export default class Avatar extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className}
|
className={classNames('account__avatar', { 'account__avatar-inline': inline, 'account__avatar-cat': isCat })}
|
||||||
|
data-cat-ears-color={catEarsColor}
|
||||||
onMouseEnter={this.handleMouseEnter}
|
onMouseEnter={this.handleMouseEnter}
|
||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
style={style}
|
style={style}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
|
||||||
import Button from 'mastodon/components/button';
|
import Button from 'mastodon/components/button';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { autoPlayGif, me, isStaff, show_followed_by, follow_button_to_list_adder } from 'mastodon/initial_state';
|
import { autoPlayGif, me, isStaff, show_followed_by, follow_button_to_list_adder } from 'mastodon/initial_state';
|
||||||
|
@ -14,6 +14,7 @@ import ShortNumber from 'mastodon/components/short_number';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||||
import AccountNoteContainer from '../containers/account_note_container';
|
import AccountNoteContainer from '../containers/account_note_container';
|
||||||
|
import age from 's-age';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
|
@ -338,6 +339,10 @@ class Header extends ImmutablePureComponent {
|
||||||
const hide_following_count = account.getIn(['other_settings', 'hide_following_count'], false);
|
const hide_following_count = account.getIn(['other_settings', 'hide_following_count'], false);
|
||||||
const hide_followers_count = account.getIn(['other_settings', 'hide_followers_count'], false);
|
const hide_followers_count = account.getIn(['other_settings', 'hide_followers_count'], false);
|
||||||
|
|
||||||
|
const location = account.getIn(['other_settings', 'location']);
|
||||||
|
const birthday = account.getIn(['other_settings', 'birthday']);
|
||||||
|
const joined = account.get('created_at');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('account__header', { inactive: !!account.get('moved') })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
<div className={classNames('account__header', { inactive: !!account.get('moved') })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||||
<div className='account__header__image'>
|
<div className='account__header__image'>
|
||||||
|
@ -408,7 +413,24 @@ class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
|
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
|
||||||
|
|
||||||
<div className='account__header__joined'><FormattedMessage id='account.joined' defaultMessage='Joined {date}' values={{ date: intl.formatDate(account.get('created_at'), { year: 'numeric', month: 'short', day: '2-digit' }) }} /></div>
|
<div className='account__header__personal--wrapper'>
|
||||||
|
<table className='account__header__personal'>
|
||||||
|
<tbody>
|
||||||
|
{location && <tr>
|
||||||
|
<th><Icon id='map-marker' fixedWidth aria-hidden='true' /> <FormattedMessage id='account.location' defaultMessage='Location' /></th>
|
||||||
|
<td>{location}</td>
|
||||||
|
</tr>}
|
||||||
|
{birthday && <tr>
|
||||||
|
<th><Icon id='birthday-cake' fixedWidth aria-hidden='true' /> <FormattedMessage id='account.birthday' defaultMessage='Birthday' /></th>
|
||||||
|
<td><FormattedDate value={birthday} hour12={false} year='numeric' month='short' day='2-digit' />(<FormattedMessage id='account.age' defaultMessage='{age} years old}' values={{age: age(birthday)}} />)</td>
|
||||||
|
</tr>}
|
||||||
|
<tr>
|
||||||
|
<th><Icon id='calendar' fixedWidth aria-hidden='true' /> <FormattedMessage id='account.joined' defaultMessage='Joined' /></th>
|
||||||
|
<td><FormattedDate value={joined} hour12={false} year='numeric' month='short' day='2-digit' /></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!suspended && (
|
{!suspended && (
|
||||||
|
|
|
@ -41,5 +41,6 @@ export const show_tab_bar_label = getMeta('show_tab_bar_label');
|
||||||
export const enable_limited_timeline = getMeta('enable_limited_timeline');
|
export const enable_limited_timeline = getMeta('enable_limited_timeline');
|
||||||
export const enableReaction = getMeta('enable_reaction');
|
export const enableReaction = getMeta('enable_reaction');
|
||||||
export const show_reply_tree_button = getMeta('show_reply_tree_button');
|
export const show_reply_tree_button = getMeta('show_reply_tree_button');
|
||||||
|
export const disable_joke_appearance = getMeta('disable_joke_appearance');
|
||||||
|
|
||||||
export default initialState;
|
export default initialState;
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
"account.account_note_header": "Note",
|
"account.account_note_header": "Note",
|
||||||
"account.add_or_remove_from_circle": "Add or Remove from circles",
|
"account.add_or_remove_from_circle": "Add or Remove from circles",
|
||||||
"account.add_or_remove_from_list": "Add or Remove from lists",
|
"account.add_or_remove_from_list": "Add or Remove from lists",
|
||||||
|
"account.age": "{age} years old",
|
||||||
"account.badges.bot": "Bot",
|
"account.badges.bot": "Bot",
|
||||||
"account.badges.group": "Group",
|
"account.badges.group": "Group",
|
||||||
|
"account.birthday": "Birthday",
|
||||||
"account.block": "Block @{name}",
|
"account.block": "Block @{name}",
|
||||||
"account.block_domain": "Block domain {domain}",
|
"account.block_domain": "Block domain {domain}",
|
||||||
"account.blocked": "Blocked",
|
"account.blocked": "Blocked",
|
||||||
|
@ -24,9 +26,10 @@
|
||||||
"account.follows.empty": "This user doesn't follow anyone yet.",
|
"account.follows.empty": "This user doesn't follow anyone yet.",
|
||||||
"account.follows_you": "Follows you",
|
"account.follows_you": "Follows you",
|
||||||
"account.hide_reblogs": "Hide boosts from @{name}",
|
"account.hide_reblogs": "Hide boosts from @{name}",
|
||||||
"account.joined": "Joined {date}",
|
"account.joined": "Joined",
|
||||||
"account.last_status": "Last active",
|
"account.last_status": "Last active",
|
||||||
"account.link_verified_on": "Ownership of this link was checked on {date}",
|
"account.link_verified_on": "Ownership of this link was checked on {date}",
|
||||||
|
"account.location": "Location",
|
||||||
"account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
|
"account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
|
||||||
"account.media": "Media",
|
"account.media": "Media",
|
||||||
"account.members": "Members",
|
"account.members": "Members",
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
"account.account_note_header": "メモ",
|
"account.account_note_header": "メモ",
|
||||||
"account.add_or_remove_from_circle": "サークルから追加または外す",
|
"account.add_or_remove_from_circle": "サークルから追加または外す",
|
||||||
"account.add_or_remove_from_list": "リストから追加または外す",
|
"account.add_or_remove_from_list": "リストから追加または外す",
|
||||||
|
"account.age": "{age}歳",
|
||||||
"account.badges.bot": "Bot",
|
"account.badges.bot": "Bot",
|
||||||
"account.badges.group": "Group",
|
"account.badges.group": "Group",
|
||||||
|
"account.birthday": "誕生日",
|
||||||
"account.block": "@{name}さんをブロック",
|
"account.block": "@{name}さんをブロック",
|
||||||
"account.block_domain": "{domain}全体をブロック",
|
"account.block_domain": "{domain}全体をブロック",
|
||||||
"account.blocked": "ブロック済み",
|
"account.blocked": "ブロック済み",
|
||||||
|
@ -24,9 +26,10 @@
|
||||||
"account.follows.empty": "まだ誰もフォローしていません。",
|
"account.follows.empty": "まだ誰もフォローしていません。",
|
||||||
"account.follows_you": "フォローされています",
|
"account.follows_you": "フォローされています",
|
||||||
"account.hide_reblogs": "@{name}さんからのブーストを非表示",
|
"account.hide_reblogs": "@{name}さんからのブーストを非表示",
|
||||||
"account.joined": "{date} に登録",
|
"account.joined": "登録日",
|
||||||
"account.last_status": "最後の活動",
|
"account.last_status": "最後の活動",
|
||||||
"account.link_verified_on": "このリンクの所有権は{date}に確認されました",
|
"account.link_verified_on": "このリンクの所有権は{date}に確認されました",
|
||||||
|
"account.location": "場所",
|
||||||
"account.locked_info": "このアカウントは承認制アカウントです。相手が承認するまでフォローは完了しません。",
|
"account.locked_info": "このアカウントは承認制アカウントです。相手が承認するまでフォローは完了しません。",
|
||||||
"account.media": "メディア",
|
"account.media": "メディア",
|
||||||
"account.members": "参加者",
|
"account.members": "参加者",
|
||||||
|
|
|
@ -7447,6 +7447,24 @@ noscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.account__header__personal {
|
||||||
|
font-size: 14px;
|
||||||
|
color: $darker-text-color;
|
||||||
|
margin: 5px auto;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 10px 3px;
|
||||||
|
|
||||||
|
th {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--wrapper {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-top: 1px solid lighten($ui-base-color, 12%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.account__header__fields {
|
.account__header__fields {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
border-top: 1px solid lighten($ui-base-color, 12%);
|
||||||
|
@ -7472,6 +7490,7 @@ noscript {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
border-top: 1px solid lighten($ui-base-color, 12%);
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -296,6 +296,10 @@ code {
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-8 {
|
||||||
|
max-width: 66.67%;
|
||||||
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
margin-top: 27px;
|
margin-top: 27px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,15 @@ module ActivityPub::CaseTransform
|
||||||
@camel_lower_cache ||= {}
|
@camel_lower_cache ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
NON_CONVERSIONS = %w(
|
||||||
|
_misskey_content
|
||||||
|
_misskey_quote
|
||||||
|
_misskey_reaction
|
||||||
|
_misskey_votes
|
||||||
|
_misskey_talk
|
||||||
|
vcard:Address
|
||||||
|
).freeze
|
||||||
|
|
||||||
def camel_lower(value)
|
def camel_lower(value)
|
||||||
case value
|
case value
|
||||||
when Array then value.map { |item| camel_lower(item) }
|
when Array then value.map { |item| camel_lower(item) }
|
||||||
|
@ -14,7 +23,7 @@ module ActivityPub::CaseTransform
|
||||||
when String
|
when String
|
||||||
camel_lower_cache[value] ||= if value.start_with?('_:')
|
camel_lower_cache[value] ||= if value.start_with?('_:')
|
||||||
'_:' + value.gsub(/\A_:/, '').underscore.camelize(:lower)
|
'_:' + value.gsub(/\A_:/, '').underscore.camelize(:lower)
|
||||||
elsif value.start_with?('_')
|
elsif NON_CONVERSIONS.include? value
|
||||||
value
|
value
|
||||||
else
|
else
|
||||||
value.underscore.camelize(:lower)
|
value.underscore.camelize(:lower)
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Formatter
|
||||||
html = reformat(raw_content)
|
html = reformat(raw_content)
|
||||||
html = apply_inner_link(html)
|
html = apply_inner_link(html)
|
||||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
||||||
|
html = nyaize_html(html) if options[:nyaize]
|
||||||
return html.html_safe # rubocop:disable Rails/OutputSafety
|
return html.html_safe # rubocop:disable Rails/OutputSafety
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ class Formatter
|
||||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
||||||
html = simple_format(html, {}, sanitize: false)
|
html = simple_format(html, {}, sanitize: false)
|
||||||
html = quotify(html, status) if status.quote? && !options[:escape_quotify]
|
html = quotify(html, status) if status.quote? && !options[:escape_quotify]
|
||||||
|
html = nyaize_html(html) if options[:nyaize]
|
||||||
html = html.delete("\n")
|
html = html.delete("\n")
|
||||||
|
|
||||||
html.html_safe # rubocop:disable Rails/OutputSafety
|
html.html_safe # rubocop:disable Rails/OutputSafety
|
||||||
|
@ -210,6 +212,44 @@ class Formatter
|
||||||
html.sub(/(<[^>]+>)\z/, "<span class=\"quote-inline\"><br/>QT: #{link}</span>\\1")
|
html.sub(/(<[^>]+>)\z/, "<span class=\"quote-inline\"><br/>QT: #{link}</span>\\1")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def nyaize_html(html)
|
||||||
|
inside_anchor = false
|
||||||
|
|
||||||
|
html.split(/(<.+?>)/).compact.map do |x|
|
||||||
|
if x.match(/^<a/)
|
||||||
|
inside_anchor = true
|
||||||
|
elsif x == '</a>'
|
||||||
|
inside_anchor = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if inside_anchor || x[0] == '<'
|
||||||
|
x
|
||||||
|
else
|
||||||
|
x.split(/(:.+?:)/).compact.map do |x|
|
||||||
|
if x[0] == ':'
|
||||||
|
x
|
||||||
|
else
|
||||||
|
nyaize(x)
|
||||||
|
end
|
||||||
|
end.join
|
||||||
|
end
|
||||||
|
end.join
|
||||||
|
end
|
||||||
|
|
||||||
|
def nyaize(text)
|
||||||
|
text
|
||||||
|
# ja-JP
|
||||||
|
.gsub(/な/, "にゃ").gsub(/ナ/, "ニャ").gsub(/ナ/, "ニャ")
|
||||||
|
# en-US
|
||||||
|
.gsub(/(?<=n)a/i) { |x| x == 'A' ? 'YA' : 'ya' }
|
||||||
|
.gsub(/(?<=morn)ing/i) { |x| x == 'ING' ? 'YAN' : 'yan' }
|
||||||
|
.gsub(/(?<=every)one/i) { |x| x == 'ONE' ? 'NYAN' : 'nyan' }
|
||||||
|
# vko-KR
|
||||||
|
.gsub(/[나-낳]/) { |c| (c.ord + '냐'.ord - '나'.ord).chr }
|
||||||
|
.gsub(/(다)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/m, '다냥')
|
||||||
|
.gsub(/(야(?=\?))|(야$)|(야(?= ))/m, '냥')
|
||||||
|
end
|
||||||
|
|
||||||
def rewrite(text, entities)
|
def rewrite(text, entities)
|
||||||
text = text.to_s
|
text = text.to_s
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ class UserSettingsDecorator
|
||||||
user.settings['hide_statuses_count'] = hide_statuses_count_preference if change?('setting_hide_statuses_count')
|
user.settings['hide_statuses_count'] = hide_statuses_count_preference if change?('setting_hide_statuses_count')
|
||||||
user.settings['hide_following_count'] = hide_following_count_preference if change?('setting_hide_following_count')
|
user.settings['hide_following_count'] = hide_following_count_preference if change?('setting_hide_following_count')
|
||||||
user.settings['hide_followers_count'] = hide_followers_count_preference if change?('setting_hide_followers_count')
|
user.settings['hide_followers_count'] = hide_followers_count_preference if change?('setting_hide_followers_count')
|
||||||
|
user.settings['disable_joke_appearance'] = disable_joke_appearance_preference if change?('setting_disable_joke_appearance')
|
||||||
end
|
end
|
||||||
|
|
||||||
def merged_notification_emails
|
def merged_notification_emails
|
||||||
|
@ -236,6 +237,10 @@ class UserSettingsDecorator
|
||||||
boolean_cast_setting 'setting_hide_followers_count'
|
boolean_cast_setting 'setting_hide_followers_count'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_joke_appearance_preference
|
||||||
|
boolean_cast_setting 'setting_disable_joke_appearance'
|
||||||
|
end
|
||||||
|
|
||||||
def boolean_cast_setting(key)
|
def boolean_cast_setting(key)
|
||||||
ActiveModel::Type::Boolean.new.cast(settings[key])
|
ActiveModel::Type::Boolean.new.cast(settings[key])
|
||||||
end
|
end
|
||||||
|
|
|
@ -414,23 +414,6 @@ class Account < ApplicationRecord
|
||||||
ActionController::Base.helpers.strip_tags(note)
|
ActionController::Base.helpers.strip_tags(note)
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings
|
|
||||||
self[:settings].class == String ? {} : self[:settings]
|
|
||||||
end
|
|
||||||
|
|
||||||
def other_settings
|
|
||||||
local? && user ? settings.merge(
|
|
||||||
{
|
|
||||||
'noindex' => user.setting_noindex,
|
|
||||||
'hide_network' => user.setting_hide_network,
|
|
||||||
'hide_statuses_count' => user.setting_hide_statuses_count,
|
|
||||||
'hide_following_count' => user.setting_hide_following_count,
|
|
||||||
'hide_followers_count' => user.setting_hide_followers_count,
|
|
||||||
'enable_reaction' => user.setting_enable_reaction,
|
|
||||||
}
|
|
||||||
) : settings
|
|
||||||
end
|
|
||||||
|
|
||||||
class Field < ActiveModelSerializers::Model
|
class Field < ActiveModelSerializers::Model
|
||||||
attributes :name, :value, :verified_at, :account
|
attributes :name, :value, :verified_at, :account
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,14 @@ module AccountAvatar
|
||||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
||||||
LIMIT = 2.megabytes
|
LIMIT = 2.megabytes
|
||||||
|
|
||||||
|
BLURHASH_OPTIONS = {
|
||||||
|
x_comp: 4,
|
||||||
|
y_comp: 4,
|
||||||
|
}.freeze
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def avatar_styles(file)
|
def avatar_styles(file)
|
||||||
styles = { original: { geometry: '400x400#', file_geometry_parser: FastGeometryParser } }
|
styles = { original: { geometry: '400x400#', file_geometry_parser: FastGeometryParser, blurhash: BLURHASH_OPTIONS } }
|
||||||
styles[:static] = { geometry: '400x400#', format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
|
styles[:static] = { geometry: '400x400#', format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
|
||||||
styles
|
styles
|
||||||
end
|
end
|
||||||
|
@ -18,7 +23,7 @@ module AccountAvatar
|
||||||
|
|
||||||
included do
|
included do
|
||||||
# Avatar upload
|
# Avatar upload
|
||||||
has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '+profile exif' }, processors: [:lazy_thumbnail]
|
has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '+profile exif' }, processors: [:lazy_thumbnail, :blurhash_transcoder]
|
||||||
validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES
|
validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES
|
||||||
validates_attachment_size :avatar, less_than: LIMIT
|
validates_attachment_size :avatar, less_than: LIMIT
|
||||||
remotable_attachment :avatar, LIMIT, suppress_errors: false
|
remotable_attachment :avatar, LIMIT, suppress_errors: false
|
||||||
|
|
|
@ -3,24 +3,81 @@
|
||||||
module AccountSettings
|
module AccountSettings
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
after_initialize :setting_initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
def cat?
|
||||||
|
true & settings['is_cat']
|
||||||
|
end
|
||||||
|
|
||||||
|
alias cat cat?
|
||||||
|
|
||||||
|
def cat=(val)
|
||||||
|
settings['is_cat'] = true & ActiveModel::Type::Boolean.new.cast(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cat_ears_color
|
||||||
|
settings['cat_ears_color']
|
||||||
|
end
|
||||||
|
|
||||||
|
def birthday
|
||||||
|
settings['birthday']
|
||||||
|
end
|
||||||
|
|
||||||
|
def birthday=(val)
|
||||||
|
settings['birthday'] = ActiveRecord::Type::Date.new.cast(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
def location
|
||||||
|
settings['location']
|
||||||
|
end
|
||||||
|
|
||||||
|
def location=(val)
|
||||||
|
settings['location'] = val
|
||||||
|
end
|
||||||
|
|
||||||
def noindex?
|
def noindex?
|
||||||
local? ? user&.noindex? : settings['noindex']
|
true & (local? ? user&.noindex? : settings['noindex'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_network?
|
def hide_network?
|
||||||
local? ? user&.hide_network? : settings['hide_network']
|
true & (local? ? user&.hide_network? : settings['hide_network'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_statuses_count?
|
def hide_statuses_count?
|
||||||
local? ? user&.hide_statuses_count? : settings['hide_statuses_count']
|
true & (local? ? user&.hide_statuses_count? : settings['hide_statuses_count'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_following_count?
|
def hide_following_count?
|
||||||
local? ? user&.hide_following_count? : settings['hide_following_count']
|
true & (local? ? user&.hide_following_count? : settings['hide_following_count'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_followers_count?
|
def hide_followers_count?
|
||||||
local? ? user&.hide_followers_count? : settings['hide_followers_count']
|
true & (local? ? user&.hide_followers_count? : settings['hide_followers_count'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def other_settings
|
||||||
|
local? && user ? settings.merge(
|
||||||
|
{
|
||||||
|
'noindex' => user.setting_noindex,
|
||||||
|
'hide_network' => user.setting_hide_network,
|
||||||
|
'hide_statuses_count' => user.setting_hide_statuses_count,
|
||||||
|
'hide_following_count' => user.setting_hide_following_count,
|
||||||
|
'hide_followers_count' => user.setting_hide_followers_count,
|
||||||
|
'enable_reaction' => user.setting_enable_reaction,
|
||||||
|
}
|
||||||
|
) : settings
|
||||||
|
end
|
||||||
|
|
||||||
|
# Called by blurhash_transcoder
|
||||||
|
def blurhash=(val)
|
||||||
|
settings['cat_ears_color'] = "##{Blurhash::Base83::decode83(val.slice(2,4)).to_s(16).rjust(6, '0')}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def setting_initialize
|
||||||
|
self[:settings] = {} if has_attribute?(:settings) && self[:settings] === "{}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -131,7 +131,7 @@ class User < ApplicationRecord
|
||||||
:follow_button_to_list_adder, :show_navigation_panel, :show_quote_button, :show_bookmark_button,
|
:follow_button_to_list_adder, :show_navigation_panel, :show_quote_button, :show_bookmark_button,
|
||||||
:place_tab_bar_at_bottom,:show_tab_bar_label, :enable_limited_timeline, :enable_reaction,
|
:place_tab_bar_at_bottom,:show_tab_bar_label, :enable_limited_timeline, :enable_reaction,
|
||||||
:show_reply_tree_button,
|
:show_reply_tree_button,
|
||||||
:hide_statuses_count, :hide_following_count, :hide_followers_count,
|
:hide_statuses_count, :hide_following_count, :hide_followers_count, :disable_joke_appearance,
|
||||||
|
|
||||||
to: :settings, prefix: :setting, allow_nil: false
|
to: :settings, prefix: :setting, allow_nil: false
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
|
||||||
|
|
||||||
context_extensions :manually_approves_followers, :featured, :also_known_as,
|
context_extensions :manually_approves_followers, :featured, :also_known_as,
|
||||||
:moved_to, :property_value, :identity_proof,
|
:moved_to, :property_value, :identity_proof,
|
||||||
:discoverable, :olm, :suspended, :other_setting
|
:discoverable, :olm, :suspended, :other_setting,
|
||||||
|
:vcard
|
||||||
|
|
||||||
attributes :id, :type, :following, :followers,
|
attributes :id, :type, :following, :followers,
|
||||||
:inbox, :outbox, :featured, :featured_tags,
|
:inbox, :outbox, :featured, :featured_tags,
|
||||||
|
@ -24,6 +25,8 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
|
||||||
attribute :moved_to, if: :moved?
|
attribute :moved_to, if: :moved?
|
||||||
attribute :also_known_as, if: :also_known_as?
|
attribute :also_known_as, if: :also_known_as?
|
||||||
attribute :suspended, if: :suspended?
|
attribute :suspended, if: :suspended?
|
||||||
|
attribute :bday, key: :'vcard:bday'
|
||||||
|
attribute :address, key: :'vcard:Address'
|
||||||
|
|
||||||
has_many :virtual_other_settings, key: :other_setting
|
has_many :virtual_other_settings, key: :other_setting
|
||||||
|
|
||||||
|
@ -164,6 +167,14 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
|
||||||
object.created_at.midnight.iso8601
|
object.created_at.midnight.iso8601
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bday
|
||||||
|
object.birthday
|
||||||
|
end
|
||||||
|
|
||||||
|
def address
|
||||||
|
object.location
|
||||||
|
end
|
||||||
|
|
||||||
def virtual_other_settings
|
def virtual_other_settings
|
||||||
object.other_settings.map do |k, v|
|
object.other_settings.map do |k, v|
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
store[:enable_limited_timeline] = object.current_account.user.setting_enable_limited_timeline
|
store[:enable_limited_timeline] = object.current_account.user.setting_enable_limited_timeline
|
||||||
store[:enable_reaction] = object.current_account.user.setting_enable_reaction
|
store[:enable_reaction] = object.current_account.user.setting_enable_reaction
|
||||||
store[:show_reply_tree_button] = object.current_account.user.setting_show_reply_tree_button
|
store[:show_reply_tree_button] = object.current_account.user.setting_show_reply_tree_button
|
||||||
|
store[:disable_joke_appearance] = object.current_account.user.setting_disable_joke_appearance
|
||||||
else
|
else
|
||||||
store[:auto_play_gif] = Setting.auto_play_gif
|
store[:auto_play_gif] = Setting.auto_play_gif
|
||||||
store[:display_media] = Setting.display_media
|
store[:display_media] = Setting.display_media
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class REST::AccountSerializer < ActiveModel::Serializer
|
class REST::AccountSerializer < ActiveModel::Serializer
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :group, :created_at,
|
attributes :id, :username, :acct, :display_name, :locked, :bot, :cat, :discoverable, :group, :created_at,
|
||||||
:note, :url, :avatar, :avatar_static, :header, :header_static,
|
:note, :url, :avatar, :avatar_static, :header, :header_static,
|
||||||
:followers_count, :following_count, :subscribing_count, :statuses_count, :last_status_at
|
:followers_count, :following_count, :subscribing_count, :statuses_count, :last_status_at
|
||||||
|
|
||||||
|
@ -88,6 +88,10 @@ class REST::AccountSerializer < ActiveModel::Serializer
|
||||||
object.suspended? ? false : object.bot
|
object.suspended? ? false : object.bot
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cat
|
||||||
|
object.suspended? ? false : object.cat
|
||||||
|
end
|
||||||
|
|
||||||
def discoverable
|
def discoverable
|
||||||
object.suspended? ? false : object.discoverable
|
object.suspended? ? false : object.discoverable
|
||||||
end
|
end
|
||||||
|
|
|
@ -127,6 +127,8 @@ class REST::InstanceSerializer < ActiveModel::Serializer
|
||||||
:visibility_mutual,
|
:visibility_mutual,
|
||||||
:visibility_limited,
|
:visibility_limited,
|
||||||
:emoji_reaction,
|
:emoji_reaction,
|
||||||
|
:misskey_birthday,
|
||||||
|
:misskey_location,
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
attribute :content, unless: :source_requested?
|
attribute :content, unless: :source_requested?
|
||||||
attribute :text, if: :source_requested?
|
attribute :text, if: :source_requested?
|
||||||
|
|
||||||
|
attribute :nyaize_content, if: :joke_applied?
|
||||||
|
|
||||||
attribute :quote_id, if: :quote?
|
attribute :quote_id, if: :quote?
|
||||||
|
|
||||||
attribute :expires_at, if: :has_expires?
|
attribute :expires_at, if: :has_expires?
|
||||||
|
@ -119,7 +121,11 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def content
|
def content
|
||||||
Formatter.instance.format(object)
|
@content ||= Formatter.instance.format(object)
|
||||||
|
end
|
||||||
|
|
||||||
|
def nyaize_content
|
||||||
|
@nyaize_content ||= Formatter.instance.format(object, nyaize: object.account.cat?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
|
@ -188,6 +194,10 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
instance_options[:source_requested]
|
instance_options[:source_requested]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def joke_applied?
|
||||||
|
!source_requested? && object.account.cat? && nyaize_content != content
|
||||||
|
end
|
||||||
|
|
||||||
def ordered_mentions
|
def ordered_mentions
|
||||||
object.active_mentions.to_a.sort_by(&:id)
|
object.active_mentions.to_a.sort_by(&:id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -98,7 +98,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
||||||
@account.note = @json['summary'] || ''
|
@account.note = @json['summary'] || ''
|
||||||
@account.locked = @json['manuallyApprovesFollowers'] || false
|
@account.locked = @json['manuallyApprovesFollowers'] || false
|
||||||
@account.fields = property_values || {}
|
@account.fields = property_values || {}
|
||||||
@account.settings = defer_settings.merge(other_settings || {})
|
@account.settings = defer_settings.merge(other_settings, birthday, address, is_cat)
|
||||||
@account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) }
|
@account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) }
|
||||||
@account.discoverable = @json['discoverable'] || false
|
@account.discoverable = @json['discoverable'] || false
|
||||||
end
|
end
|
||||||
|
@ -212,16 +212,34 @@ class ActivityPub::ProcessAccountService < BaseService
|
||||||
as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
|
as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def birthday
|
||||||
|
return {} if @json['vcard:bday'].blank?
|
||||||
|
{ 'birthday' => ActiveRecord::Type::Date.new.cast(@json['vcard:bday']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def address
|
||||||
|
return {} if @json['vcard:Address'].blank?
|
||||||
|
{ 'location' => @json['vcard:Address'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_cat
|
||||||
|
return {} unless ActiveModel::Type::Boolean.new.cast(@json['isCat'])
|
||||||
|
{ 'is_cat' => true }
|
||||||
|
end
|
||||||
|
|
||||||
DEFER_SETTINGS_KEYS = %w(
|
DEFER_SETTINGS_KEYS = %w(
|
||||||
|
birthday
|
||||||
|
location
|
||||||
|
cat_ears_color
|
||||||
noindex
|
noindex
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
def defer_settings
|
def defer_settings
|
||||||
(@account.settings || {}).select { |key, _| DEFER_SETTINGS_KEYS.include?(key) }
|
@account.settings.select { |key, _| DEFER_SETTINGS_KEYS.include?(key) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def other_settings
|
def other_settings
|
||||||
return unless @json['otherSetting'].is_a?(Array)
|
return {} unless @json['otherSetting'].is_a?(Array)
|
||||||
@json['otherSetting'].each_with_object({}) { |v, h| h.merge!({v['name'] => v['value']}) if v['type'] == 'PropertyValue' }
|
@json['otherSetting'].each_with_object({}) { |v, h| h.merge!({v['name'] => v['value']}) if v['type'] == 'PropertyValue' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
.public-account-header__image
|
.public-account-header__image
|
||||||
= image_tag (prefers_autoplay? ? account.header_original_url : account.header_static_url), class: 'parallax'
|
= image_tag (prefers_autoplay? ? account.header_original_url : account.header_static_url), class: 'parallax'
|
||||||
.public-account-header__bar
|
.public-account-header__bar
|
||||||
= link_to short_account_url(account), class: 'avatar' do
|
= link_to short_account_url(account), account_cat_params(account, class: 'avatar') do
|
||||||
= image_tag (prefers_autoplay? ? account.avatar_original_url : account.avatar_static_url), id: 'profile_page_avatar', data: { original: full_asset_url(account.avatar_original_url), static: full_asset_url(account.avatar_static_url), autoplay: prefers_autoplay? }
|
= image_tag (prefers_autoplay? ? account.avatar_original_url : account.avatar_static_url), id: 'profile_page_avatar', data: { original: full_asset_url(account.avatar_original_url), static: full_asset_url(account.avatar_static_url), autoplay: prefers_autoplay? }
|
||||||
.public-account-header__tabs
|
.public-account-header__tabs
|
||||||
.public-account-header__tabs__name
|
.public-account-header__tabs__name
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
.card__img
|
.card__img
|
||||||
= image_tag account.header.url, alt: ''
|
= image_tag account.header.url, alt: ''
|
||||||
.card__bar
|
.card__bar
|
||||||
.avatar
|
.avatar{ account_cat_params(account) }
|
||||||
= image_tag account.avatar.url, alt: '', width: 48, height: 48, class: 'u-photo'
|
= image_tag account.avatar.url, alt: '', width: 48, height: 48, class: 'u-photo'
|
||||||
|
|
||||||
.display-name
|
.display-name
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
= image_tag account.header.url, alt: ''
|
= image_tag account.header.url, alt: ''
|
||||||
.directory__card__bar
|
.directory__card__bar
|
||||||
= link_to TagManager.instance.url_for(account), class: 'directory__card__bar__name' do
|
= link_to TagManager.instance.url_for(account), class: 'directory__card__bar__name' do
|
||||||
.avatar
|
.avatar{ account_cat_params(account) }
|
||||||
= image_tag account.avatar.url, alt: '', class: 'u-photo'
|
= image_tag account.avatar.url, alt: '', class: 'u-photo'
|
||||||
|
|
||||||
.display-name
|
.display-name
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
- if Setting.custom_css.present?
|
- if Setting.custom_css.present?
|
||||||
= stylesheet_link_tag custom_css_path, host: request.host, media: 'all'
|
= stylesheet_link_tag custom_css_path, host: request.host, media: 'all'
|
||||||
|
|
||||||
|
%style{ nonce: request.content_security_policy_nonce }
|
||||||
|
!= account_cat_styles
|
||||||
|
|
||||||
= yield :header_tags
|
= yield :header_tags
|
||||||
|
|
||||||
%body{ class: body_classes }
|
%body{ class: body_classes }
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
= 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
|
||||||
|
|
||||||
|
%h4= t 'appearance.joke'
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :setting_disable_joke_appearance, as: :boolean, wrapper: :with_label, fedibird_features: true
|
||||||
|
|
||||||
%h4= t 'appearance.toot_layout'
|
%h4= t 'appearance.toot_layout'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
|
|
|
@ -55,6 +55,16 @@
|
||||||
%input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: link_to('Mastodon', ActivityPub::TagManager.instance.url_for(@account), rel: 'me').to_str }
|
%input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: link_to('Mastodon', ActivityPub::TagManager.instance.url_for(@account), rel: 'me').to_str }
|
||||||
%button{ type: :button }= t('generic.copy')
|
%button{ type: :button }= t('generic.copy')
|
||||||
|
|
||||||
|
.fields-row
|
||||||
|
.fields-row__column.fields-group.fields-row__column-8
|
||||||
|
= f.input :birthday, wrapper: :with_label, input_html: { placeholder: '2016-03-16', pattern: '\d{4}-\d{1,2}-\d{1,2}' }, hint: t('simple_form.hints.defaults.birthday'), fedibird_features: true
|
||||||
|
%p.warning-hint= t('simple_form.hints.defaults.birthday_caution')
|
||||||
|
|
||||||
|
.fields-row
|
||||||
|
.fields-row__column.fields-group.fields-row__column-8
|
||||||
|
= f.input :location, wrapper: :with_label, input_html: { maxlength: 50 }, hint: t('simple_form.hints.defaults.location'), fedibird_features: true
|
||||||
|
%p.warning-hint= t('simple_form.hints.defaults.location_caution')
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.detailed-status.detailed-status--flex{ class: "detailed-status-#{status.visibility}" }
|
.detailed-status.detailed-status--flex{ class: "detailed-status-#{status.visibility}" }
|
||||||
.p-author.h-card
|
.p-author.h-card
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do
|
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do
|
||||||
.detailed-status__display-avatar
|
.detailed-status__display-avatar{ account_cat_params(status.account) }
|
||||||
- if prefers_autoplay?
|
- if prefers_autoplay?
|
||||||
= image_tag status.account.avatar_original_url, alt: '', class: 'account__avatar u-photo'
|
= image_tag status.account.avatar_original_url, alt: '', class: 'account__avatar u-photo'
|
||||||
- else
|
- else
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.status.quote-status{ dataurl: ActivityPub::TagManager.instance.url_for(status) }
|
.status.quote-status{ dataurl: ActivityPub::TagManager.instance.url_for(status) }
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
|
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
|
||||||
.status__avatar
|
.status__avatar{ account_cat_params(status.account) }
|
||||||
%div
|
%div
|
||||||
= image_tag status.account.avatar_static_url, width: 18, height: 18, alt: '', class: 'u-photo account__avatar'
|
= image_tag status.account.avatar_static_url, width: 18, height: 18, alt: '', class: 'u-photo account__avatar'
|
||||||
%span.display-name
|
%span.display-name
|
||||||
|
|
|
@ -11,12 +11,11 @@
|
||||||
|
|
||||||
.p-author.h-card
|
.p-author.h-card
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do
|
||||||
.status__avatar
|
.status__avatar{ account_cat_params(status.account) }
|
||||||
%div
|
- if prefers_autoplay?
|
||||||
- if prefers_autoplay?
|
= image_tag status.account.avatar_original_url, alt: '', class: 'u-photo account__avatar'
|
||||||
= image_tag status.account.avatar_original_url, alt: '', class: 'u-photo account__avatar'
|
- else
|
||||||
- else
|
= image_tag status.account.avatar_static_url, alt: '', class: 'u-photo account__avatar'
|
||||||
= image_tag status.account.avatar_static_url, alt: '', class: 'u-photo account__avatar'
|
|
||||||
%span.display-name
|
%span.display-name
|
||||||
%bdi
|
%bdi
|
||||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
|
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
|
||||||
|
|
|
@ -762,6 +762,7 @@ en:
|
||||||
animations_and_accessibility: Animations and accessibility
|
animations_and_accessibility: Animations and accessibility
|
||||||
confirmation_dialogs: Confirmation dialogs
|
confirmation_dialogs: Confirmation dialogs
|
||||||
discovery: Discovery
|
discovery: Discovery
|
||||||
|
joke: Joke features
|
||||||
localization:
|
localization:
|
||||||
body: Mastodon is translated by volunteers.
|
body: Mastodon is translated by volunteers.
|
||||||
guide_link: https://crowdin.com/project/mastodon
|
guide_link: https://crowdin.com/project/mastodon
|
||||||
|
|
|
@ -740,6 +740,7 @@ ja:
|
||||||
animations_and_accessibility: アニメーションとアクセシビリティー
|
animations_and_accessibility: アニメーションとアクセシビリティー
|
||||||
confirmation_dialogs: 確認ダイアログ
|
confirmation_dialogs: 確認ダイアログ
|
||||||
discovery: 見つける
|
discovery: 見つける
|
||||||
|
joke: ジョーク機能
|
||||||
localization:
|
localization:
|
||||||
body: Mastodonは有志によって翻訳されています。
|
body: Mastodonは有志によって翻訳されています。
|
||||||
guide_link: https://ja.crowdin.com/project/mastodon
|
guide_link: https://ja.crowdin.com/project/mastodon
|
||||||
|
|
|
@ -31,6 +31,8 @@ en:
|
||||||
defaults:
|
defaults:
|
||||||
autofollow: People who sign up through the invite will automatically follow you
|
autofollow: People who sign up through the invite will automatically follow you
|
||||||
avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
|
avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
|
||||||
|
birthday: Specify the date of birth in the format yyyy-mm-dd(ex. 2016-03-16)
|
||||||
|
birthday_caution: It will be published on the Internet. Please handle your personal information with care
|
||||||
bot: Signal to others that the account mainly performs automated actions and might not be monitored
|
bot: Signal to others that the account mainly performs automated actions and might not be monitored
|
||||||
context: One or multiple contexts where the filter should apply
|
context: One or multiple contexts where the filter should apply
|
||||||
current_password: For security purposes please enter the password of the current account
|
current_password: For security purposes please enter the password of the current account
|
||||||
|
@ -43,12 +45,15 @@ en:
|
||||||
inbox_url: Copy the URL from the frontpage of the relay you want to use
|
inbox_url: Copy the URL from the frontpage of the relay you want to use
|
||||||
irreversible: Filtered posts will disappear irreversibly, even if filter is later removed
|
irreversible: Filtered posts will disappear irreversibly, even if filter is later removed
|
||||||
locale: The language of the user interface, e-mails and push notifications
|
locale: The language of the user interface, e-mails and push notifications
|
||||||
|
location: Area of primary residence or activity
|
||||||
|
location_caution: It will be published on the Internet. Please do not include detailed addresses except for business use
|
||||||
locked: Manually control who can follow you by approving follow requests
|
locked: Manually control who can follow you by approving follow requests
|
||||||
password: Use at least 8 characters
|
password: Use at least 8 characters
|
||||||
phrase: Will be matched regardless of casing in text or content warning of a post
|
phrase: Will be matched regardless of casing in text or content warning of a post
|
||||||
scopes: Which APIs the application will be allowed to access. If you select a top-level scope, you don't need to select individual ones.
|
scopes: Which APIs the application will be allowed to access. If you select a top-level scope, you don't need to select individual ones.
|
||||||
setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts)
|
setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts)
|
||||||
setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click
|
setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click
|
||||||
|
setting_disable_joke_appearance: Disable April Fools' Day and other joke functions
|
||||||
setting_display_media_default: Hide media marked as sensitive
|
setting_display_media_default: Hide media marked as sensitive
|
||||||
setting_display_media_hide_all: Always hide media
|
setting_display_media_hide_all: Always hide media
|
||||||
setting_display_media_show_all: Always show media
|
setting_display_media_show_all: Always show media
|
||||||
|
@ -155,6 +160,7 @@ en:
|
||||||
defaults:
|
defaults:
|
||||||
autofollow: Invite to follow your account
|
autofollow: Invite to follow your account
|
||||||
avatar: Avatar
|
avatar: Avatar
|
||||||
|
birthday: Birthday
|
||||||
bot: This is a bot account
|
bot: This is a bot account
|
||||||
chosen_languages: Filter languages
|
chosen_languages: Filter languages
|
||||||
confirm_new_password: Confirm new password
|
confirm_new_password: Confirm new password
|
||||||
|
@ -172,6 +178,7 @@ en:
|
||||||
inbox_url: URL of the relay inbox
|
inbox_url: URL of the relay inbox
|
||||||
irreversible: Drop instead of hide
|
irreversible: Drop instead of hide
|
||||||
locale: Interface language
|
locale: Interface language
|
||||||
|
location: Location
|
||||||
locked: Require follow requests
|
locked: Require follow requests
|
||||||
max_uses: Max number of uses
|
max_uses: Max number of uses
|
||||||
new_password: New password
|
new_password: New password
|
||||||
|
@ -188,6 +195,7 @@ en:
|
||||||
setting_default_privacy: Posting privacy
|
setting_default_privacy: Posting privacy
|
||||||
setting_default_sensitive: Always mark media as sensitive
|
setting_default_sensitive: Always mark media as sensitive
|
||||||
setting_delete_modal: Show confirmation dialog before deleting a post
|
setting_delete_modal: Show confirmation dialog before deleting a post
|
||||||
|
setting_disable_joke_appearance: Disable joke feature to change appearance
|
||||||
setting_disable_swiping: Disable swiping motions
|
setting_disable_swiping: Disable swiping motions
|
||||||
setting_display_media: Media display
|
setting_display_media: Media display
|
||||||
setting_display_media_default: Default
|
setting_display_media_default: Default
|
||||||
|
|
|
@ -31,6 +31,8 @@ ja:
|
||||||
defaults:
|
defaults:
|
||||||
autofollow: 招待から登録した人が自動的にあなたをフォローするようになります
|
autofollow: 招待から登録した人が自動的にあなたをフォローするようになります
|
||||||
avatar: "%{size}までのPNG、GIF、JPGが利用可能です。%{dimensions}pxまで縮小されます"
|
avatar: "%{size}までのPNG、GIF、JPGが利用可能です。%{dimensions}pxまで縮小されます"
|
||||||
|
birthday: 誕生日を年月日の順にyyyy-mm-dd(ex. 2016-03-16)という書式で指定します
|
||||||
|
birthday_caution: インターネットに公開されます。個人情報は慎重に取り扱ってください
|
||||||
bot: このアカウントは主に自動で動作し、人が見ていない可能性があります
|
bot: このアカウントは主に自動で動作し、人が見ていない可能性があります
|
||||||
context: フィルターを適用する対象 (複数選択可)
|
context: フィルターを適用する対象 (複数選択可)
|
||||||
current_password: 現在のアカウントのパスワードを入力してください
|
current_password: 現在のアカウントのパスワードを入力してください
|
||||||
|
@ -43,12 +45,15 @@ ja:
|
||||||
inbox_url: 使用したいリレーサーバーのトップページからURLをコピーします
|
inbox_url: 使用したいリレーサーバーのトップページからURLをコピーします
|
||||||
irreversible: フィルターが後で削除されても、除外された投稿は元に戻せなくなります
|
irreversible: フィルターが後で削除されても、除外された投稿は元に戻せなくなります
|
||||||
locale: ユーザーインターフェース、メールやプッシュ通知の言語
|
locale: ユーザーインターフェース、メールやプッシュ通知の言語
|
||||||
|
location: 主に居住・活動する地域・場所
|
||||||
|
location_caution: インターネットに公開されます。ビジネス用途を除き詳細な住所を記載しないでください
|
||||||
locked: フォロワーを手動で承認する必要があります
|
locked: フォロワーを手動で承認する必要があります
|
||||||
password: 少なくとも8文字は入力してください
|
password: 少なくとも8文字は入力してください
|
||||||
phrase: 投稿内容の大文字小文字や閲覧注意に関係なく一致
|
phrase: 投稿内容の大文字小文字や閲覧注意に関係なく一致
|
||||||
scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。
|
scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。
|
||||||
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
|
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
|
||||||
setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります
|
setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります
|
||||||
|
setting_disable_joke_appearance: エイプリルフール等のジョーク機能を無効にします
|
||||||
setting_display_media_default: 閲覧注意としてマークされたメディアは隠す
|
setting_display_media_default: 閲覧注意としてマークされたメディアは隠す
|
||||||
setting_display_media_hide_all: メディアを常に隠す
|
setting_display_media_hide_all: メディアを常に隠す
|
||||||
setting_display_media_show_all: メディアを常に表示する
|
setting_display_media_show_all: メディアを常に表示する
|
||||||
|
@ -155,6 +160,7 @@ ja:
|
||||||
defaults:
|
defaults:
|
||||||
autofollow: 招待から参加後、あなたをフォロー
|
autofollow: 招待から参加後、あなたをフォロー
|
||||||
avatar: アイコン
|
avatar: アイコン
|
||||||
|
birthday: 誕生日
|
||||||
bot: これは BOT アカウントです
|
bot: これは BOT アカウントです
|
||||||
chosen_languages: 表示する言語
|
chosen_languages: 表示する言語
|
||||||
confirm_new_password: 新しいパスワード(確認用)
|
confirm_new_password: 新しいパスワード(確認用)
|
||||||
|
@ -172,6 +178,7 @@ ja:
|
||||||
inbox_url: リレーサーバーの inbox URL
|
inbox_url: リレーサーバーの inbox URL
|
||||||
irreversible: 隠すのではなく除外する
|
irreversible: 隠すのではなく除外する
|
||||||
locale: 言語
|
locale: 言語
|
||||||
|
location: 場所
|
||||||
locked: 承認制アカウントにする
|
locked: 承認制アカウントにする
|
||||||
max_uses: 使用できる回数
|
max_uses: 使用できる回数
|
||||||
new_password: 新しいパスワード
|
new_password: 新しいパスワード
|
||||||
|
@ -188,6 +195,7 @@ ja:
|
||||||
setting_default_privacy: 投稿の公開範囲
|
setting_default_privacy: 投稿の公開範囲
|
||||||
setting_default_sensitive: メディアを常に閲覧注意としてマークする
|
setting_default_sensitive: メディアを常に閲覧注意としてマークする
|
||||||
setting_delete_modal: 投稿を削除する前に確認ダイアログを表示する
|
setting_delete_modal: 投稿を削除する前に確認ダイアログを表示する
|
||||||
|
setting_disable_joke_appearance: ジョーク機能による見た目の変更を無効にする
|
||||||
setting_disable_swiping: スワイプでの切り替えを無効にする
|
setting_disable_swiping: スワイプでの切り替えを無効にする
|
||||||
setting_display_media: メディアの表示
|
setting_display_media: メディアの表示
|
||||||
setting_display_media_default: 標準
|
setting_display_media_default: 標準
|
||||||
|
|
|
@ -55,6 +55,7 @@ defaults: &defaults
|
||||||
hide_statuses_count: false
|
hide_statuses_count: false
|
||||||
hide_following_count: false
|
hide_following_count: false
|
||||||
hide_followers_count: false
|
hide_followers_count: false
|
||||||
|
disable_joke_appearance: false
|
||||||
notification_emails:
|
notification_emails:
|
||||||
follow: false
|
follow: false
|
||||||
reblog: false
|
reblog: false
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
"requestidlecallback": "^0.3.0",
|
"requestidlecallback": "^0.3.0",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
"s-age": "^1.1.2",
|
||||||
"sass": "^1.37.0",
|
"sass": "^1.37.0",
|
||||||
"sass-loader": "^10.2.0",
|
"sass-loader": "^10.2.0",
|
||||||
"stacktrace-js": "^2.0.2",
|
"stacktrace-js": "^2.0.2",
|
||||||
|
|
|
@ -9869,6 +9869,11 @@ rx-lite@^3.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
||||||
integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=
|
integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=
|
||||||
|
|
||||||
|
s-age@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/s-age/-/s-age-1.1.2.tgz#c0cf15233ccc93f41de92ea42c36d957977d1ea2"
|
||||||
|
integrity sha512-aSN2TlF39WLoZA/6cgYSJZhKt63kJ4EaadejPWjWY9/h4rksIqvfWY3gfd+3uAegSM1IXsA9aWeEhJtkxkFQtA==
|
||||||
|
|
||||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
version "5.1.2"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
|
|
Loading…
Reference in a new issue