Merge commit 'b91724fb9d0839365391310e20c2589ff6062d4f' into glitch-soc/merge-upstream
Conflicts: - `Vagrantfile`: Upstream bumped a bunch of values, including one that was already bumped by glitch-soc. Took upstream's version. - `lib/paperclip/transcoder.rb`: glitch-soc already had a partial fix for this. Took upstream's version.
This commit is contained in:
commit
b6b68b44a1
17 changed files with 176 additions and 103 deletions
|
@ -2,3 +2,7 @@ VAGRANT=true
|
||||||
LOCAL_DOMAIN=mastodon.local
|
LOCAL_DOMAIN=mastodon.local
|
||||||
BIND=0.0.0.0
|
BIND=0.0.0.0
|
||||||
DB_HOST=/var/run/postgresql/
|
DB_HOST=/var/run/postgresql/
|
||||||
|
|
||||||
|
ES_ENABLED=true
|
||||||
|
ES_HOST=localhost
|
||||||
|
ES_PORT=9200
|
108
Gemfile.lock
108
Gemfile.lock
|
@ -39,47 +39,47 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (7.0.7)
|
actioncable (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (7.0.7)
|
actionmailbox (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
activejob (= 7.0.7)
|
activejob (= 7.0.7.2)
|
||||||
activerecord (= 7.0.7)
|
activerecord (= 7.0.7.2)
|
||||||
activestorage (= 7.0.7)
|
activestorage (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
actionmailer (7.0.7)
|
actionmailer (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
actionview (= 7.0.7)
|
actionview (= 7.0.7.2)
|
||||||
activejob (= 7.0.7)
|
activejob (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (7.0.7)
|
actionpack (7.0.7.2)
|
||||||
actionview (= 7.0.7)
|
actionview (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
rack (~> 2.0, >= 2.2.4)
|
rack (~> 2.0, >= 2.2.4)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (7.0.7)
|
actiontext (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
activerecord (= 7.0.7)
|
activerecord (= 7.0.7.2)
|
||||||
activestorage (= 7.0.7)
|
activestorage (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
globalid (>= 0.6.0)
|
globalid (>= 0.6.0)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (7.0.7)
|
actionview (7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
|
@ -89,22 +89,22 @@ GEM
|
||||||
activemodel (>= 4.1, < 7.1)
|
activemodel (>= 4.1, < 7.1)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||||
activejob (7.0.7)
|
activejob (7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (7.0.7)
|
activemodel (7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
activerecord (7.0.7)
|
activerecord (7.0.7.2)
|
||||||
activemodel (= 7.0.7)
|
activemodel (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
activestorage (7.0.7)
|
activestorage (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
activejob (= 7.0.7)
|
activejob (= 7.0.7.2)
|
||||||
activerecord (= 7.0.7)
|
activerecord (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
mini_mime (>= 1.1.0)
|
mini_mime (>= 1.1.0)
|
||||||
activesupport (7.0.7)
|
activesupport (7.0.7.2)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
|
@ -482,7 +482,7 @@ GEM
|
||||||
nokogiri (1.15.4)
|
nokogiri (1.15.4)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.15.0)
|
oj (3.16.0)
|
||||||
omniauth (2.1.1)
|
omniauth (2.1.1)
|
||||||
hashie (>= 3.4.6)
|
hashie (>= 3.4.6)
|
||||||
rack (>= 2.2.3)
|
rack (>= 2.2.3)
|
||||||
|
@ -556,20 +556,20 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-test (2.1.0)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
rails (7.0.7)
|
rails (7.0.7.2)
|
||||||
actioncable (= 7.0.7)
|
actioncable (= 7.0.7.2)
|
||||||
actionmailbox (= 7.0.7)
|
actionmailbox (= 7.0.7.2)
|
||||||
actionmailer (= 7.0.7)
|
actionmailer (= 7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
actiontext (= 7.0.7)
|
actiontext (= 7.0.7.2)
|
||||||
actionview (= 7.0.7)
|
actionview (= 7.0.7.2)
|
||||||
activejob (= 7.0.7)
|
activejob (= 7.0.7.2)
|
||||||
activemodel (= 7.0.7)
|
activemodel (= 7.0.7.2)
|
||||||
activerecord (= 7.0.7)
|
activerecord (= 7.0.7.2)
|
||||||
activestorage (= 7.0.7)
|
activestorage (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 7.0.7)
|
railties (= 7.0.7.2)
|
||||||
rails-controller-testing (1.0.5)
|
rails-controller-testing (1.0.5)
|
||||||
actionpack (>= 5.0.1.rc1)
|
actionpack (>= 5.0.1.rc1)
|
||||||
actionview (>= 5.0.1.rc1)
|
actionview (>= 5.0.1.rc1)
|
||||||
|
@ -584,9 +584,9 @@ GEM
|
||||||
rails-i18n (7.0.7)
|
rails-i18n (7.0.7)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 6.0.0, < 8)
|
railties (>= 6.0.0, < 8)
|
||||||
railties (7.0.7)
|
railties (7.0.7.2)
|
||||||
actionpack (= 7.0.7)
|
actionpack (= 7.0.7.2)
|
||||||
activesupport (= 7.0.7)
|
activesupport (= 7.0.7.2)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0)
|
thor (~> 1.0)
|
||||||
|
|
43
Vagrantfile
vendored
43
Vagrantfile
vendored
|
@ -60,6 +60,37 @@ sudo usermod -a -G rvm $USER
|
||||||
|
|
||||||
SCRIPT
|
SCRIPT
|
||||||
|
|
||||||
|
$provisionElasticsearch = <<SCRIPT
|
||||||
|
# Install Elastic Search
|
||||||
|
sudo apt install openjdk-17-jre-headless -y
|
||||||
|
sudo wget -O /usr/share/keyrings/elasticsearch.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
|
||||||
|
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/elasticsearch.asc] https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list'
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install elasticsearch -y
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now elasticsearch
|
||||||
|
|
||||||
|
echo 'path.data: /var/lib/elasticsearch
|
||||||
|
path.logs: /var/log/elasticsearch
|
||||||
|
network.host: 0.0.0.0
|
||||||
|
http.port: 9200
|
||||||
|
discovery.seed_hosts: ["localhost"]
|
||||||
|
cluster.initial_master_nodes: ["node-1"]' > /etc/elasticsearch/elasticsearch.yml
|
||||||
|
|
||||||
|
sudo systemctl restart elasticsearch
|
||||||
|
|
||||||
|
# Install Kibana
|
||||||
|
sudo apt install kibana -y
|
||||||
|
sudo systemctl enable --now kibana
|
||||||
|
|
||||||
|
echo 'server.host: "0.0.0.0"
|
||||||
|
elasticsearch.hosts: ["http://localhost:9200"]' > /etc/kibana/kibana.yml
|
||||||
|
|
||||||
|
sudo systemctl restart kibana
|
||||||
|
|
||||||
|
SCRIPT
|
||||||
|
|
||||||
$provisionB = <<SCRIPT
|
$provisionB = <<SCRIPT
|
||||||
|
|
||||||
source "/etc/profile.d/rvm.sh"
|
source "/etc/profile.d/rvm.sh"
|
||||||
|
@ -102,10 +133,8 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
|
|
||||||
config.vm.provider :virtualbox do |vb|
|
config.vm.provider :virtualbox do |vb|
|
||||||
vb.name = "mastodon"
|
vb.name = "mastodon"
|
||||||
vb.customize ["modifyvm", :id, "--memory", "4096"]
|
vb.customize ["modifyvm", :id, "--memory", "8192"]
|
||||||
# Increase the number of CPUs. Uncomment and adjust to
|
vb.customize ["modifyvm", :id, "--cpus", "3"]
|
||||||
# increase performance
|
|
||||||
# vb.customize ["modifyvm", :id, "--cpus", "3"]
|
|
||||||
|
|
||||||
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
|
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
|
||||||
# https://github.com/mitchellh/vagrant/issues/1172
|
# https://github.com/mitchellh/vagrant/issues/1172
|
||||||
|
@ -141,9 +170,15 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
config.vm.network :forwarded_port, guest: 3000, host: 3000
|
config.vm.network :forwarded_port, guest: 3000, host: 3000
|
||||||
config.vm.network :forwarded_port, guest: 4000, host: 4000
|
config.vm.network :forwarded_port, guest: 4000, host: 4000
|
||||||
config.vm.network :forwarded_port, guest: 8080, host: 8080
|
config.vm.network :forwarded_port, guest: 8080, host: 8080
|
||||||
|
config.vm.network :forwarded_port, guest: 9200, host: 9200
|
||||||
|
config.vm.network :forwarded_port, guest: 9300, host: 9300
|
||||||
|
config.vm.network :forwarded_port, guest: 9243, host: 9243
|
||||||
|
config.vm.network :forwarded_port, guest: 5601, host: 5601
|
||||||
|
|
||||||
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
|
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
|
||||||
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true
|
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true
|
||||||
|
# Run with elevated privileges for Elasticsearch installation
|
||||||
|
config.vm.provision :shell, inline: $provisionElasticsearch, privileged: true
|
||||||
config.vm.provision :shell, inline: $provisionB, privileged: false
|
config.vm.provision :shell, inline: $provisionB, privileged: false
|
||||||
|
|
||||||
config.vm.post_up_message = <<MESSAGE
|
config.vm.post_up_message = <<MESSAGE
|
||||||
|
|
|
@ -22,6 +22,7 @@ module ContextHelper
|
||||||
blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
|
blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
|
||||||
discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' },
|
discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' },
|
||||||
indexable: { 'toot' => 'http://joinmastodon.org/ns#', 'indexable' => 'toot:indexable' },
|
indexable: { 'toot' => 'http://joinmastodon.org/ns#', 'indexable' => 'toot:indexable' },
|
||||||
|
memorial: { 'toot' => 'http://joinmastodon.org/ns#', 'memorial' => 'toot:memorial' },
|
||||||
voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' },
|
voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' },
|
||||||
olm: {
|
olm: {
|
||||||
'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId',
|
'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId',
|
||||||
|
|
|
@ -105,6 +105,21 @@ describe('computeHashtagBarForStatus', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles server-side normalized tags with accentuated characters', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Text</p><p><a href="test">#éaa</a> <a href="test">#Éaa</a></p>',
|
||||||
|
['eaa'], // The server may normalize the hashtags in the `tags` attribute
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual(['Éaa']);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Text</p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('does not display in bar a hashtag in content with a case difference', () => {
|
it('does not display in bar a hashtag in content with a case difference', () => {
|
||||||
const status = createStatus(
|
const status = createStatus(
|
||||||
'<p>Text <a href="test">#Éaa</a></p><p><a href="test">#éaa</a></p>',
|
'<p>Text <a href="test">#Éaa</a></p><p><a href="test">#éaa</a></p>',
|
||||||
|
|
|
@ -23,8 +23,9 @@ export type StatusLike = Record<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
function normalizeHashtag(hashtag: string) {
|
function normalizeHashtag(hashtag: string) {
|
||||||
if (hashtag && hashtag.startsWith('#')) return hashtag.slice(1);
|
return (
|
||||||
else return hashtag;
|
hashtag && hashtag.startsWith('#') ? hashtag.slice(1) : hashtag
|
||||||
|
).normalize('NFKC');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNodeLinkHashtag(element: Node): element is HTMLLinkElement {
|
function isNodeLinkHashtag(element: Node): element is HTMLLinkElement {
|
||||||
|
@ -70,9 +71,16 @@ function uniqueHashtagsWithCaseHandling(hashtags: string[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the collator once, this is much more efficient
|
// Create the collator once, this is much more efficient
|
||||||
const collator = new Intl.Collator(undefined, { sensitivity: 'accent' });
|
const collator = new Intl.Collator(undefined, {
|
||||||
|
sensitivity: 'base', // we use this to emulate the ASCII folding done on the server-side, hopefuly more efficiently
|
||||||
|
});
|
||||||
|
|
||||||
function localeAwareInclude(collection: string[], value: string) {
|
function localeAwareInclude(collection: string[], value: string) {
|
||||||
return collection.find((item) => collator.compare(item, value) === 0);
|
const normalizedValue = value.normalize('NFKC');
|
||||||
|
|
||||||
|
return !!collection.find(
|
||||||
|
(item) => collator.compare(item.normalize('NFKC'), normalizedValue) === 0,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use an intermediate function here to make it easier to test
|
// We use an intermediate function here to make it easier to test
|
||||||
|
@ -121,11 +129,13 @@ export function computeHashtagBarForStatus(status: StatusLike): {
|
||||||
// try to see if the last line is only hashtags
|
// try to see if the last line is only hashtags
|
||||||
let onlyHashtags = true;
|
let onlyHashtags = true;
|
||||||
|
|
||||||
|
const normalizedTagNames = tagNames.map((tag) => tag.normalize('NFKC'));
|
||||||
|
|
||||||
Array.from(lastChild.childNodes).forEach((node) => {
|
Array.from(lastChild.childNodes).forEach((node) => {
|
||||||
if (isNodeLinkHashtag(node) && node.textContent) {
|
if (isNodeLinkHashtag(node) && node.textContent) {
|
||||||
const normalized = normalizeHashtag(node.textContent);
|
const normalized = normalizeHashtag(node.textContent);
|
||||||
|
|
||||||
if (!localeAwareInclude(tagNames, normalized)) {
|
if (!localeAwareInclude(normalizedTagNames, normalized)) {
|
||||||
// stop here, this is not a real hashtag, so consider it as text
|
// stop here, this is not a real hashtag, so consider it as text
|
||||||
onlyHashtags = false;
|
onlyHashtags = false;
|
||||||
return;
|
return;
|
||||||
|
@ -140,12 +150,14 @@ export function computeHashtagBarForStatus(status: StatusLike): {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const hashtagsInBar = tagNames.filter(
|
const hashtagsInBar = tagNames.filter((tag) => {
|
||||||
(tag) =>
|
const normalizedTag = tag.normalize('NFKC');
|
||||||
// the tag does not appear at all in the status content, it is an out-of-band tag
|
// the tag does not appear at all in the status content, it is an out-of-band tag
|
||||||
!localeAwareInclude(contentHashtags, tag) &&
|
return (
|
||||||
!localeAwareInclude(lastLineHashtags, tag),
|
!localeAwareInclude(contentHashtags, normalizedTag) &&
|
||||||
);
|
!localeAwareInclude(lastLineHashtags, normalizedTag)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const isOnlyOneLine = contentWithoutLastLine.content.childElementCount === 0;
|
const isOnlyOneLine = contentWithoutLastLine.content.childElementCount === 0;
|
||||||
const hasMedia = status.get('media_attachments').size > 0;
|
const hasMedia = status.get('media_attachments').size > 0;
|
||||||
|
@ -204,7 +216,7 @@ const HashtagBar: React.FC<{
|
||||||
<div className='hashtag-bar'>
|
<div className='hashtag-bar'>
|
||||||
{revealedHashtags.map((hashtag) => (
|
{revealedHashtags.map((hashtag) => (
|
||||||
<Link key={hashtag} to={`/tags/${hashtag}`}>
|
<Link key={hashtag} to={`/tags/${hashtag}`}>
|
||||||
#{hashtag}
|
#<span>{hashtag}</span>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|
|
@ -546,6 +546,7 @@ class Status extends ImmutablePureComponent {
|
||||||
const visibilityIcon = visibilityIconInfo[status.get('visibility')];
|
const visibilityIcon = visibilityIconInfo[status.get('visibility')];
|
||||||
|
|
||||||
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
||||||
|
const expanded = !status.get('hidden')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
|
@ -574,7 +575,7 @@ class Status extends ImmutablePureComponent {
|
||||||
<StatusContent
|
<StatusContent
|
||||||
status={status}
|
status={status}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
expanded={!status.get('hidden')}
|
expanded={expanded}
|
||||||
onExpandedToggle={this.handleExpandedToggle}
|
onExpandedToggle={this.handleExpandedToggle}
|
||||||
onTranslate={this.handleTranslate}
|
onTranslate={this.handleTranslate}
|
||||||
collapsible
|
collapsible
|
||||||
|
@ -584,7 +585,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
{media}
|
{media}
|
||||||
|
|
||||||
{hashtagBar}
|
{expanded && hashtagBar}
|
||||||
|
|
||||||
<StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters ? this.handleFilterClick : null} {...other} />
|
<StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters ? this.handleFilterClick : null} {...other} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -108,10 +108,10 @@ class Results extends PureComponent {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='account__section-headline'>
|
<div className='account__section-headline'>
|
||||||
<button onClick={this.handleSelectAll} className={type === 'all' && 'active'}><FormattedMessage id='search_results.all' defaultMessage='All' /></button>
|
<button onClick={this.handleSelectAll} className={type === 'all' ? 'active' : undefined}><FormattedMessage id='search_results.all' defaultMessage='All' /></button>
|
||||||
<button onClick={this.handleSelectAccounts} className={type === 'accounts' && 'active'}><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></button>
|
<button onClick={this.handleSelectAccounts} className={type === 'accounts' ? 'active' : undefined}><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></button>
|
||||||
<button onClick={this.handleSelectHashtags} className={type === 'hashtags' && 'active'}><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></button>
|
<button onClick={this.handleSelectHashtags} className={type === 'hashtags' ? 'active' : undefined}><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></button>
|
||||||
<button onClick={this.handleSelectStatuses} className={type === 'statuses' && 'active'}><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></button>
|
<button onClick={this.handleSelectStatuses} className={type === 'statuses' ? 'active' : undefined}><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='explore__search-results'>
|
<div className='explore__search-results'>
|
||||||
|
|
|
@ -293,6 +293,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
||||||
|
const expanded = !status.get('hidden')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={outerStyle}>
|
<div style={outerStyle}>
|
||||||
|
@ -318,7 +319,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
|
|
||||||
{media}
|
{media}
|
||||||
|
|
||||||
{hashtagBar}
|
{expanded && hashtagBar}
|
||||||
|
|
||||||
<div className='detailed-status__meta'>
|
<div className='detailed-status__meta'>
|
||||||
<a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
|
<a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
|
||||||
|
|
|
@ -568,7 +568,7 @@ class Status extends ImmutablePureComponent {
|
||||||
onMoveUp={this.handleMoveUp}
|
onMoveUp={this.handleMoveUp}
|
||||||
onMoveDown={this.handleMoveDown}
|
onMoveDown={this.handleMoveDown}
|
||||||
contextType='thread'
|
contextType='thread'
|
||||||
previousId={i > 0 && list.get(i - 1)}
|
previousId={i > 0 ? list.get(i - 1) : undefined}
|
||||||
nextId={list.get(i + 1) || (ancestors && statusId)}
|
nextId={list.get(i + 1) || (ancestors && statusId)}
|
||||||
rootId={statusId}
|
rootId={statusId}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -115,7 +115,10 @@ export default class ModalRoot extends PureComponent {
|
||||||
{visible && (
|
{visible && (
|
||||||
<>
|
<>
|
||||||
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
|
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
|
||||||
{(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={this.setModalRef} />}
|
{(SpecificComponent) => {
|
||||||
|
const ref = typeof SpecificComponent !== 'function' ? this.setModalRef : undefined;
|
||||||
|
return <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={ref} />
|
||||||
|
}}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
|
|
||||||
<Helmet>
|
<Helmet>
|
||||||
|
|
|
@ -9305,16 +9305,15 @@ noscript {
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
border-radius: 4px;
|
color: $dark-text-color;
|
||||||
background: rgba($highlight-text-color, 0.2);
|
|
||||||
color: $highlight-text-color;
|
|
||||||
padding: 0.4em 0.6em;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover,
|
&:hover {
|
||||||
&:focus,
|
text-decoration: none;
|
||||||
&:active {
|
|
||||||
background: rgba($highlight-text-color, 0.3);
|
span {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,14 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
|
||||||
context :security
|
context :security
|
||||||
|
|
||||||
context_extensions :manually_approves_followers, :featured, :also_known_as,
|
context_extensions :manually_approves_followers, :featured, :also_known_as,
|
||||||
:moved_to, :property_value, :discoverable, :olm, :suspended
|
:moved_to, :property_value, :discoverable, :olm, :suspended,
|
||||||
|
:memorial
|
||||||
|
|
||||||
attributes :id, :type, :following, :followers,
|
attributes :id, :type, :following, :followers,
|
||||||
:inbox, :outbox, :featured, :featured_tags,
|
:inbox, :outbox, :featured, :featured_tags,
|
||||||
:preferred_username, :name, :summary,
|
:preferred_username, :name, :summary,
|
||||||
:url, :manually_approves_followers,
|
:url, :manually_approves_followers,
|
||||||
:discoverable, :published
|
:discoverable, :published, :memorial
|
||||||
|
|
||||||
has_one :public_key, serializer: ActivityPub::PublicKeySerializer
|
has_one :public_key, serializer: ActivityPub::PublicKeySerializer
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ class AccountSearchService < BaseService
|
||||||
multi_match: {
|
multi_match: {
|
||||||
query: @query,
|
query: @query,
|
||||||
type: 'bool_prefix',
|
type: 'bool_prefix',
|
||||||
fields: %w(username username.* display_name display_name.*),
|
fields: %w(username^2 username.*^2 display_name display_name.*),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,6 +116,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
||||||
@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
|
||||||
@account.indexable = @json['indexable'] || false
|
@account.indexable = @json['indexable'] || false
|
||||||
|
@account.memorial = @json['memorial'] || false
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_fetchable_key!
|
def set_fetchable_key!
|
||||||
|
|
|
@ -40,11 +40,11 @@ module Paperclip
|
||||||
unless eligible_to_passthrough?(metadata)
|
unless eligible_to_passthrough?(metadata)
|
||||||
@output_options['acodec'] = 'aac'
|
@output_options['acodec'] = 'aac'
|
||||||
@output_options['strict'] = 'experimental'
|
@output_options['strict'] = 'experimental'
|
||||||
end
|
|
||||||
|
|
||||||
if high_vfr?(metadata) && !eligible_to_passthrough?(metadata)
|
if high_vfr?(metadata)
|
||||||
@output_options['vsync'] = 'vfr'
|
@output_options['vsync'] = 'vfr'
|
||||||
@output_options['r'] = @vfr_threshold
|
@output_options['r'] = @vfr_threshold
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -6658,9 +6658,9 @@ immutable@^3.8.2:
|
||||||
integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==
|
integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==
|
||||||
|
|
||||||
immutable@^4.0.0, immutable@^4.0.0-rc.1, immutable@^4.3.0:
|
immutable@^4.0.0, immutable@^4.0.0-rc.1, immutable@^4.3.0:
|
||||||
version "4.3.2"
|
version "4.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.2.tgz#f89d910f8dfb6e15c03b2cae2faaf8c1f66455fe"
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.3.tgz#8934ff6826d996a7642c8dc4b46e694dd19561e3"
|
||||||
integrity sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==
|
integrity sha512-808ZFYMsIRAjLAu5xkKo0TsbY9LBy9H5MazTKIEHerNkg0ymgilGfBPMR/3G7d/ihGmuK2Hw8S1izY2d3kd3wA==
|
||||||
|
|
||||||
import-fresh@^3.2.1:
|
import-fresh@^3.2.1:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
|
@ -10101,9 +10101,9 @@ react-test-renderer@^18.2.0:
|
||||||
scheduler "^0.23.0"
|
scheduler "^0.23.0"
|
||||||
|
|
||||||
react-textarea-autosize@*, react-textarea-autosize@^8.4.1:
|
react-textarea-autosize@*, react-textarea-autosize@^8.4.1:
|
||||||
version "8.5.2"
|
version "8.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.5.2.tgz#6421df2b5b50b9ca8c5e96fd31be688ea7fa2f9d"
|
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz#d1e9fe760178413891484847d3378706052dd409"
|
||||||
integrity sha512-uOkyjkEl0ByEK21eCJMHDGBAAd/BoFQBawYK5XItjAmCTeSbjxghd8qnt7nzsLYzidjnoObu6M26xts0YGKsGg==
|
integrity sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.20.13"
|
"@babel/runtime" "^7.20.13"
|
||||||
use-composed-ref "^1.3.0"
|
use-composed-ref "^1.3.0"
|
||||||
|
@ -10614,9 +10614,9 @@ sass-loader@^10.2.0:
|
||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
|
|
||||||
sass@^1.62.1:
|
sass@^1.62.1:
|
||||||
version "1.65.1"
|
version "1.66.1"
|
||||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.65.1.tgz#8f283b0c26335a88246a448d22e1342ba2ea1432"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.66.1.tgz#04b51c4671e4650aa393740e66a4e58b44d055b1"
|
||||||
integrity sha512-9DINwtHmA41SEd36eVPQ9BJKpn7eKDQmUHmpI0y5Zv2Rcorrh0zS+cFrt050hdNbmmCNKTW3hV5mWfuegNRsEA==
|
integrity sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar ">=3.0.0 <4.0.0"
|
chokidar ">=3.0.0 <4.0.0"
|
||||||
immutable "^4.0.0"
|
immutable "^4.0.0"
|
||||||
|
|
Loading…
Reference in a new issue