mirror of
https://github.com/mastodon/mastodon.git
synced 2024-12-20 00:08:37 +00:00
Merge pull request #886 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
This commit is contained in:
commit
077639c274
|
@ -429,7 +429,7 @@ GEM
|
||||||
rack-attack (5.4.2)
|
rack-attack (5.4.2)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rack-cors (1.0.2)
|
rack-cors (1.0.2)
|
||||||
rack-protection (2.0.4)
|
rack-protection (2.0.5)
|
||||||
rack
|
rack
|
||||||
rack-proxy (0.6.4)
|
rack-proxy (0.6.4)
|
||||||
rack
|
rack
|
||||||
|
@ -553,8 +553,9 @@ GEM
|
||||||
scss_lint (0.57.1)
|
scss_lint (0.57.1)
|
||||||
rake (>= 0.9, < 13)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.5, >= 3.5.5)
|
sass (~> 3.5, >= 3.5.5)
|
||||||
sidekiq (5.2.3)
|
sidekiq (5.2.5)
|
||||||
connection_pool (~> 2.2, >= 2.2.2)
|
connection_pool (~> 2.2, >= 2.2.2)
|
||||||
|
rack (>= 1.5.0)
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
redis (>= 3.3.5, < 5)
|
redis (>= 3.3.5, < 5)
|
||||||
sidekiq-bulk (0.2.0)
|
sidekiq-bulk (0.2.0)
|
||||||
|
@ -639,7 +640,7 @@ GEM
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
rack-proxy (>= 0.6.1)
|
rack-proxy (>= 0.6.1)
|
||||||
railties (>= 4.2)
|
railties (>= 4.2)
|
||||||
webpush (0.3.5)
|
webpush (0.3.6)
|
||||||
hkdf (~> 0.2)
|
hkdf (~> 0.2)
|
||||||
jwt (~> 2.0)
|
jwt (~> 2.0)
|
||||||
websocket-driver (0.7.0)
|
websocket-driver (0.7.0)
|
||||||
|
|
|
@ -69,8 +69,12 @@ module ApplicationHelper
|
||||||
tag(:meta, content: content, property: property)
|
tag(:meta, content: content, property: property)
|
||||||
end
|
end
|
||||||
|
|
||||||
def react_component(name, props = {})
|
def react_component(name, props = {}, &block)
|
||||||
content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) })
|
if block.nil?
|
||||||
|
content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) })
|
||||||
|
else
|
||||||
|
content_tag(:div, data: { component: name.to_s.camelcase, props: Oj.dump(props) }, &block)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def body_classes
|
def body_classes
|
||||||
|
|
|
@ -61,6 +61,12 @@ function main() {
|
||||||
if (reactComponents.length > 0) {
|
if (reactComponents.length > 0) {
|
||||||
import(/* webpackChunkName: "containers/media_container" */ 'flavours/glitch/containers/media_container')
|
import(/* webpackChunkName: "containers/media_container" */ 'flavours/glitch/containers/media_container')
|
||||||
.then(({ default: MediaContainer }) => {
|
.then(({ default: MediaContainer }) => {
|
||||||
|
[].forEach.call(reactComponents, (component) => {
|
||||||
|
[].forEach.call(component.children, (child) => {
|
||||||
|
component.removeChild(child);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
ReactDOM.render(<MediaContainer locale={locale} components={reactComponents} />, content);
|
ReactDOM.render(<MediaContainer locale={locale} components={reactComponents} />, content);
|
||||||
|
|
|
@ -1044,6 +1044,10 @@ $small-breakpoint: 960px;
|
||||||
|
|
||||||
.scrollable {
|
.scrollable {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
|
|
||||||
|
@media screen and (max-width: $column-breakpoint) {
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
$no-columns-breakpoint: 600px;
|
$no-columns-breakpoint: 600px;
|
||||||
|
$sidebar-width: 240px;
|
||||||
|
$content-width: 840px;
|
||||||
|
|
||||||
.admin-wrapper {
|
.admin-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -6,7 +8,7 @@ $no-columns-breakpoint: 600px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
flex: 1;
|
flex: 1 1 $sidebar-width;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -14,7 +16,7 @@ $no-columns-breakpoint: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 240px;
|
width: $sidebar-width;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
@ -95,12 +97,12 @@ $no-columns-breakpoint: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
flex: 2;
|
flex: 2 1 $content-width;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
max-width: 700px;
|
max-width: $content-width;
|
||||||
padding: 20px 15px;
|
padding: 20px 15px;
|
||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
|
|
|
@ -92,11 +92,14 @@ const handlePush = (event) => {
|
||||||
options.image = notification.status && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url || undefined;
|
options.image = notification.status && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url || undefined;
|
||||||
options.data = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/web/statuses/${notification.status.id}` : `/web/accounts/${notification.account.id}` };
|
options.data = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/web/statuses/${notification.status.id}` : `/web/accounts/${notification.account.id}` };
|
||||||
|
|
||||||
if (notification.status && notification.status.sensitive) {
|
if (notification.status && notification.status.spoiler_text || notification.status.sensitive) {
|
||||||
options.data.hiddenBody = htmlToPlainText(notification.status.content);
|
options.data.hiddenBody = htmlToPlainText(notification.status.content);
|
||||||
options.data.hiddenImage = notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url;
|
options.data.hiddenImage = notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url;
|
||||||
|
|
||||||
options.body = notification.status.spoiler_text;
|
if (notification.status.spoiler_text) {
|
||||||
|
options.body = notification.status.spoiler_text;
|
||||||
|
}
|
||||||
|
|
||||||
options.image = undefined;
|
options.image = undefined;
|
||||||
options.actions = [actionExpand(preferred_locale)];
|
options.actions = [actionExpand(preferred_locale)];
|
||||||
} else if (notification.type === 'mention') {
|
} else if (notification.type === 'mention') {
|
||||||
|
|
|
@ -66,6 +66,12 @@ function main() {
|
||||||
if (reactComponents.length > 0) {
|
if (reactComponents.length > 0) {
|
||||||
import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container')
|
import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container')
|
||||||
.then(({ default: MediaContainer }) => {
|
.then(({ default: MediaContainer }) => {
|
||||||
|
[].forEach.call(reactComponents, (component) => {
|
||||||
|
[].forEach.call(component.children, (child) => {
|
||||||
|
component.removeChild(child);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
ReactDOM.render(<MediaContainer locale={locale} components={reactComponents} />, content);
|
ReactDOM.render(<MediaContainer locale={locale} components={reactComponents} />, content);
|
||||||
|
|
|
@ -1041,6 +1041,10 @@ $small-breakpoint: 960px;
|
||||||
|
|
||||||
.scrollable {
|
.scrollable {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
|
|
||||||
|
@media screen and (max-width: $column-breakpoint) {
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
$no-columns-breakpoint: 600px;
|
$no-columns-breakpoint: 600px;
|
||||||
|
$sidebar-width: 240px;
|
||||||
|
$content-width: 840px;
|
||||||
|
|
||||||
.admin-wrapper {
|
.admin-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -6,7 +8,7 @@ $no-columns-breakpoint: 600px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
flex: 1;
|
flex: 1 1 $sidebar-width;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -14,7 +16,7 @@ $no-columns-breakpoint: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 240px;
|
width: $sidebar-width;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
@ -95,12 +97,12 @@ $no-columns-breakpoint: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
flex: 2;
|
flex: 2 1 $content-width;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
max-width: 700px;
|
max-width: $content-width;
|
||||||
padding: 20px 15px;
|
padding: 20px 15px;
|
||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
|
|
8
app/views/stream_entries/_attachment_list.html.haml
Normal file
8
app/views/stream_entries/_attachment_list.html.haml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.attachment-list
|
||||||
|
.attachment-list__icon
|
||||||
|
= fa_icon 'link'
|
||||||
|
%ul.attachment-list__list
|
||||||
|
- attachments.each do |media|
|
||||||
|
%li
|
||||||
|
- url = media.remote_url.presence || media.file.url
|
||||||
|
= link_to File.basename(url), url, title: media.description
|
|
@ -25,9 +25,11 @@
|
||||||
- if !status.media_attachments.empty?
|
- if !status.media_attachments.empty?
|
||||||
- if status.media_attachments.first.video?
|
- if status.media_attachments.first.video?
|
||||||
- video = status.media_attachments.first
|
- video = status.media_attachments.first
|
||||||
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 670, height: 380, detailed: true, inline: true, alt: video.description
|
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
|
||||||
|
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- else
|
- else
|
||||||
= react_component :media_gallery, height: 380, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
|
= react_component :media_gallery, height: 380, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
||||||
|
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.preview_card
|
- elsif status.preview_card
|
||||||
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,11 @@
|
||||||
- if !status.media_attachments.empty?
|
- if !status.media_attachments.empty?
|
||||||
- if status.media_attachments.first.video?
|
- if status.media_attachments.first.video?
|
||||||
- video = status.media_attachments.first
|
- video = status.media_attachments.first
|
||||||
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description
|
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description do
|
||||||
|
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- else
|
- else
|
||||||
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
|
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
||||||
|
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.preview_card
|
- elsif status.preview_card
|
||||||
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,131 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Admin::AccountAction, type: :model do
|
RSpec.describe Admin::AccountAction, type: :model do
|
||||||
|
let(:account_action) { described_class.new }
|
||||||
|
|
||||||
|
describe '#save!' do
|
||||||
|
subject { account_action.save! }
|
||||||
|
let(:account) { Fabricate(:account, user: Fabricate(:user, admin: true)) }
|
||||||
|
let(:target_account) { Fabricate(:account, user: Fabricate(:user)) }
|
||||||
|
let(:type) { 'disable' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
account_action.assign_attributes(
|
||||||
|
type: type,
|
||||||
|
current_account: account,
|
||||||
|
target_account: target_account
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'type is "disable"' do
|
||||||
|
let(:type) { 'disable' }
|
||||||
|
|
||||||
|
it 'disable user' do
|
||||||
|
subject
|
||||||
|
expect(target_account.user).to be_disabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'type is "silence"' do
|
||||||
|
let(:type) { 'silence' }
|
||||||
|
|
||||||
|
it 'silences account' do
|
||||||
|
subject
|
||||||
|
expect(target_account).to be_silenced
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'type is "suspend"' do
|
||||||
|
let(:type) { 'suspend' }
|
||||||
|
|
||||||
|
it 'suspends account' do
|
||||||
|
subject
|
||||||
|
expect(target_account).to be_suspended
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'queues Admin::SuspensionWorker by 1' do
|
||||||
|
Sidekiq::Testing.fake! do
|
||||||
|
expect do
|
||||||
|
subject
|
||||||
|
end.to change { Admin::SuspensionWorker.jobs.size }.by 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates Admin::ActionLog' do
|
||||||
|
expect do
|
||||||
|
subject
|
||||||
|
end.to change { Admin::ActionLog.count }.by 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls queue_email!' do
|
||||||
|
expect(account_action).to receive(:queue_email!)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls process_reports!' do
|
||||||
|
expect(account_action).to receive(:process_reports!)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#report' do
|
||||||
|
subject { account_action.report }
|
||||||
|
|
||||||
|
context 'report_id.present?' do
|
||||||
|
before do
|
||||||
|
account_action.report_id = Fabricate(:report).id
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns Report' do
|
||||||
|
expect(subject).to be_instance_of Report
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context '!report_id.present?' do
|
||||||
|
it 'returns nil' do
|
||||||
|
expect(subject).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#with_report?' do
|
||||||
|
subject { account_action.with_report? }
|
||||||
|
|
||||||
|
context '!report.nil?' do
|
||||||
|
before do
|
||||||
|
account_action.report_id = Fabricate(:report).id
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true' do
|
||||||
|
expect(subject).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context '!(!report.nil?)' do
|
||||||
|
it 'returns false' do
|
||||||
|
expect(subject).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.types_for_account' do
|
||||||
|
subject { described_class.types_for_account(account) }
|
||||||
|
|
||||||
|
context 'account.local?' do
|
||||||
|
let(:account) { Fabricate(:account, domain: nil) }
|
||||||
|
|
||||||
|
it 'returns ["none", "disable", "silence", "suspend"]' do
|
||||||
|
expect(subject).to eq %w(none disable silence suspend)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context '!account.local?' do
|
||||||
|
let(:account) { Fabricate(:account, domain: 'hoge.com') }
|
||||||
|
|
||||||
|
it 'returns ["silence", "suspend"]' do
|
||||||
|
expect(subject).to eq %w(silence suspend)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Admin::ActionLog, type: :model do
|
RSpec.describe Admin::ActionLog, type: :model do
|
||||||
|
describe '#action' do
|
||||||
|
it 'returns action' do
|
||||||
|
action_log = described_class.new(action: 'hoge')
|
||||||
|
expect(action_log.action).to be :hoge
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue