From 8b2cad56374b2dbb6e7a445e7917810935c45536 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 7 Jul 2017 04:02:06 +0200 Subject: Refactor JSON templates to be generated with ActiveModelSerializers instead of Rabl (#4090) --- app/serializers/rest/account_serializer.rb | 33 ++++++++ app/serializers/rest/application_serializer.rb | 14 ++++ app/serializers/rest/context_serializer.rb | 6 ++ app/serializers/rest/instance_serializer.rb | 30 +++++++ .../rest/media_attachment_serializer.rb | 24 ++++++ app/serializers/rest/notification_serializer.rb | 12 +++ app/serializers/rest/preview_card_serializer.rb | 14 ++++ app/serializers/rest/relationship_serializer.rb | 30 +++++++ app/serializers/rest/report_serializer.rb | 5 ++ app/serializers/rest/search_serializer.rb | 12 +++ app/serializers/rest/status_serializer.rb | 93 ++++++++++++++++++++++ 11 files changed, 273 insertions(+) create mode 100644 app/serializers/rest/account_serializer.rb create mode 100644 app/serializers/rest/application_serializer.rb create mode 100644 app/serializers/rest/context_serializer.rb create mode 100644 app/serializers/rest/instance_serializer.rb create mode 100644 app/serializers/rest/media_attachment_serializer.rb create mode 100644 app/serializers/rest/notification_serializer.rb create mode 100644 app/serializers/rest/preview_card_serializer.rb create mode 100644 app/serializers/rest/relationship_serializer.rb create mode 100644 app/serializers/rest/report_serializer.rb create mode 100644 app/serializers/rest/search_serializer.rb create mode 100644 app/serializers/rest/status_serializer.rb (limited to 'app/serializers') diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb new file mode 100644 index 000000000..012a4fd18 --- /dev/null +++ b/app/serializers/rest/account_serializer.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class REST::AccountSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :id, :username, :acct, :display_name, :locked, :created_at, + :note, :url, :avatar, :avatar_static, :header, :header_static, + :followers_count, :following_count, :statuses_count + + def note + Formatter.instance.simplified_format(object) + end + + def url + TagManager.instance.url_for(object) + end + + def avatar + full_asset_url(object.avatar_original_url) + end + + def avatar_static + full_asset_url(object.avatar_static_url) + end + + def header + full_asset_url(object.header_original_url) + end + + def header_static + full_asset_url(object.header_static_url) + end +end diff --git a/app/serializers/rest/application_serializer.rb b/app/serializers/rest/application_serializer.rb new file mode 100644 index 000000000..868a62f1e --- /dev/null +++ b/app/serializers/rest/application_serializer.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class REST::ApplicationSerializer < ActiveModel::Serializer + attributes :id, :name, :website, :redirect_uri, + :client_id, :client_secret + + def client_id + object.uid + end + + def client_secret + object.secret + end +end diff --git a/app/serializers/rest/context_serializer.rb b/app/serializers/rest/context_serializer.rb new file mode 100644 index 000000000..44515c85d --- /dev/null +++ b/app/serializers/rest/context_serializer.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class REST::ContextSerializer < ActiveModel::Serializer + has_many :ancestors, serializer: REST::StatusSerializer + has_many :descendants, serializer: REST::StatusSerializer +end diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb new file mode 100644 index 000000000..8e32f9cb3 --- /dev/null +++ b/app/serializers/rest/instance_serializer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class REST::InstanceSerializer < ActiveModel::Serializer + attributes :uri, :title, :description, :email, + :version, :urls + + def uri + Rails.configuration.x.local_domain + end + + def title + Setting.site_title + end + + def description + Setting.site_description + end + + def email + Setting.site_contact_email + end + + def version + Mastodon::Version.to_s + end + + def urls + { streaming_api: Rails.configuration.x.streaming_api_base_url } + end +end diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb new file mode 100644 index 000000000..9b07a686e --- /dev/null +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class REST::MediaAttachmentSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :id, :type, :url, :preview_url, + :remote_url, :text_url, :meta + + def url + full_asset_url(object.file.url(:original)) + end + + def preview_url + full_asset_url(object.file.url(:small)) + end + + def text_url + medium_url(object.id) + end + + def meta + object.file.meta + end +end diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb new file mode 100644 index 000000000..97fadf32e --- /dev/null +++ b/app/serializers/rest/notification_serializer.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class REST::NotificationSerializer < ActiveModel::Serializer + attributes :id, :type, :created_at + + belongs_to :from_account, key: :account, serializer: REST::AccountSerializer + belongs_to :status, if: :status_type?, serializer: REST::StatusSerializer + + def status_type? + [:favourite, :reblog, :mention].include?(object.type) + end +end diff --git a/app/serializers/rest/preview_card_serializer.rb b/app/serializers/rest/preview_card_serializer.rb new file mode 100644 index 000000000..9c460332c --- /dev/null +++ b/app/serializers/rest/preview_card_serializer.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class REST::PreviewCardSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :url, :title, :description, :type, + :author_name, :author_url, :provider_name, + :provider_url, :html, :width, :height, + :image + + def image + object.image? ? full_asset_url(object.image.url(:original)) : nil + end +end diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb new file mode 100644 index 000000000..1d431aa1b --- /dev/null +++ b/app/serializers/rest/relationship_serializer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class REST::RelationshipSerializer < ActiveModel::Serializer + attributes :id, :following, :followed_by, :blocking, + :muting, :requested, :domain_blocking + + def following + instance_options[:relationships].following[object.id] || false + end + + def followed_by + instance_options[:relationships].followed_by[object.id] || false + end + + def blocking + instance_options[:relationships].blocking[object.id] || false + end + + def muting + instance_options[:relationships].muting[object.id] || false + end + + def requested + instance_options[:relationships].requested[object.id] || false + end + + def domain_blocking + instance_options[:relationships].domain_blocking[object.id] || false + end +end diff --git a/app/serializers/rest/report_serializer.rb b/app/serializers/rest/report_serializer.rb new file mode 100644 index 000000000..0c6bd6556 --- /dev/null +++ b/app/serializers/rest/report_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class REST::ReportSerializer < ActiveModel::Serializer + attributes :id, :action_taken +end diff --git a/app/serializers/rest/search_serializer.rb b/app/serializers/rest/search_serializer.rb new file mode 100644 index 000000000..157f543ae --- /dev/null +++ b/app/serializers/rest/search_serializer.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class REST::SearchSerializer < ActiveModel::Serializer + attributes :hashtags + + has_many :accounts, serializer: REST::AccountSerializer + has_many :statuses, serializer: REST::StatusSerializer + + def hashtags + object.hashtags.map(&:name) + end +end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb new file mode 100644 index 000000000..246b12a90 --- /dev/null +++ b/app/serializers/rest/status_serializer.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +class REST::StatusSerializer < ActiveModel::Serializer + attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id, + :sensitive, :spoiler_text, :visibility, :language, + :uri, :content, :url, :reblogs_count, :favourites_count + + attribute :favourited, if: :current_user? + attribute :reblogged, if: :current_user? + attribute :muted, if: :current_user? + + belongs_to :reblog, serializer: REST::StatusSerializer + belongs_to :application + belongs_to :account, serializer: REST::AccountSerializer + + has_many :media_attachments, serializer: REST::MediaAttachmentSerializer + has_many :mentions + has_many :tags + + def current_user? + !current_user.nil? + end + + def uri + TagManager.instance.uri_for(object) + end + + def content + Formatter.instance.format(object) + end + + def url + TagManager.instance.url_for(object) + end + + def favourited + if instance_options && instance_options[:relationships] + instance_options[:relationships].favourites_map[object.id] || false + else + current_user.account.favourited?(object) + end + end + + def reblogged + if instance_options && instance_options[:relationships] + instance_options[:relationships].reblogs_map[object.id] || false + else + current_user.account.reblogged?(object) + end + end + + def muted + if instance_options && instance_options[:relationships] + instance_options[:relationships].mutes_map[object.conversation_id] || false + else + current_user.account.muting_conversation?(object.conversation) + end + end + + class ApplicationSerializer < ActiveModel::Serializer + attributes :name, :website + end + + class MentionSerializer < ActiveModel::Serializer + attributes :id, :username, :url, :acct + + def id + object.account_id + end + + def username + object.account_username + end + + def url + TagManager.instance.url_for(object.account) + end + + def acct + object.account_acct + end + end + + class TagSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :name, :url + + def url + tag_url(object) + end + end +end -- cgit From 6e1261f277411300e4f1d24f8c1b14ad1a165915 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 7 Jul 2017 16:19:28 +0200 Subject: Fix notifications including wrong status in JSON (#4097) --- app/serializers/rest/notification_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/serializers') diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 97fadf32e..f95d099a3 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -4,7 +4,7 @@ class REST::NotificationSerializer < ActiveModel::Serializer attributes :id, :type, :created_at belongs_to :from_account, key: :account, serializer: REST::AccountSerializer - belongs_to :status, if: :status_type?, serializer: REST::StatusSerializer + belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer def status_type? [:favourite, :reblog, :mention].include?(object.type) -- cgit From 102466ac5842b20f32a9c5e2fa3f35414c34574b Mon Sep 17 00:00:00 2001 From: unarist Date: Sat, 8 Jul 2017 21:50:45 +0900 Subject: Fix JSON serialization of media_attachment (#4111) --- app/serializers/rest/media_attachment_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/serializers') diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb index 9b07a686e..9055b8db4 100644 --- a/app/serializers/rest/media_attachment_serializer.rb +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -15,7 +15,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer end def text_url - medium_url(object.id) + object.local? ? medium_url(object) : nil end def meta -- cgit From 864e3f8d9ca652e10a28bddbb0d0df629d2849d4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 8 Jul 2017 14:51:05 +0200 Subject: Replace OEmbed and initial state Rabl templates with serializers (#4110) * Replace OEmbed Rabl template with serializer * Replace initial state rabl with serializer --- app/controllers/api/oembed_controller.rb | 3 +- app/controllers/home_controller.rb | 17 ++++++--- app/presenters/initial_state_presenter.rb | 5 +++ app/serializers/initial_state_serializer.rb | 39 ++++++++++++++++++++ app/serializers/oembed_serializer.rb | 56 +++++++++++++++++++++++++++++ app/views/api/oembed/show.json.rabl | 14 -------- app/views/home/index.html.haml | 2 +- app/views/home/initial_state.json.rabl | 38 -------------------- spec/controllers/home_controller_spec.rb | 41 ++++----------------- 9 files changed, 121 insertions(+), 94 deletions(-) create mode 100644 app/presenters/initial_state_presenter.rb create mode 100644 app/serializers/initial_state_serializer.rb create mode 100644 app/serializers/oembed_serializer.rb delete mode 100644 app/views/api/oembed/show.json.rabl delete mode 100644 app/views/home/initial_state.json.rabl (limited to 'app/serializers') diff --git a/app/controllers/api/oembed_controller.rb b/app/controllers/api/oembed_controller.rb index 6e3e34d96..f8c87dd16 100644 --- a/app/controllers/api/oembed_controller.rb +++ b/app/controllers/api/oembed_controller.rb @@ -5,8 +5,7 @@ class Api::OEmbedController < Api::BaseController def show @stream_entry = find_stream_entry.stream_entry - @width = maxwidth_or_default - @height = maxheight_or_default + render json: @stream_entry, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default end private diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 6209a3ae9..218da6906 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -2,13 +2,10 @@ class HomeController < ApplicationController before_action :authenticate_user! + before_action :set_initial_state_json def index - @body_classes = 'app-body' - @token = current_session.token - @web_settings = Web::Setting.find_by(user: current_user)&.data || {} - @admin = Account.find_local(Setting.site_contact_username) - @streaming_api_base_url = Rails.configuration.x.streaming_api_base_url + @body_classes = 'app-body' end private @@ -16,4 +13,14 @@ class HomeController < ApplicationController def authenticate_user! redirect_to(single_user_mode? ? account_path(Account.first) : about_path) unless user_signed_in? end + + def set_initial_state_json + state = InitialStatePresenter.new(settings: Web::Setting.find_by(user: current_user)&.data || {}, + current_account: current_account, + token: current_session.token, + admin: Account.find_local(Setting.site_contact_username)) + + serializable_resource = ActiveModelSerializers::SerializableResource.new(state, serializer: InitialStateSerializer) + @initial_state_json = serializable_resource.to_json + end end diff --git a/app/presenters/initial_state_presenter.rb b/app/presenters/initial_state_presenter.rb new file mode 100644 index 000000000..75fef28a8 --- /dev/null +++ b/app/presenters/initial_state_presenter.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class InitialStatePresenter < ActiveModelSerializers::Model + attributes :settings, :token, :current_account, :admin +end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb new file mode 100644 index 000000000..84f9e23a6 --- /dev/null +++ b/app/serializers/initial_state_serializer.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +class InitialStateSerializer < ActiveModel::Serializer + attributes :meta, :compose, :accounts, + :media_attachments, :settings + + def meta + { + streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, + access_token: object.token, + locale: I18n.locale, + domain: Rails.configuration.x.local_domain, + me: object.current_account.id, + admin: object.admin&.id, + boost_modal: object.current_account.user.setting_boost_modal, + delete_modal: object.current_account.user.setting_delete_modal, + auto_play_gif: object.current_account.user.setting_auto_play_gif, + system_font_ui: object.current_account.user.setting_system_font_ui, + } + end + + def compose + { + me: object.current_account.id, + default_privacy: object.current_account.user.setting_default_privacy, + } + end + + def accounts + store = {} + store[object.current_account.id] = ActiveModelSerializers::SerializableResource.new(object.current_account, serializer: REST::AccountSerializer) + store[object.admin.id] = ActiveModelSerializers::SerializableResource.new(object.admin, serializer: REST::AccountSerializer) unless object.admin.nil? + store + end + + def media_attachments + { accept_content_types: MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES } + end +end diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb new file mode 100644 index 000000000..78376d253 --- /dev/null +++ b/app/serializers/oembed_serializer.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class OEmbedSerializer < ActiveModel::Serializer + include RoutingHelper + include ActionView::Helpers::TagHelper + + attributes :type, :version, :title, :author_name, + :author_url, :provider_name, :provider_url, + :cache_age, :html, :width, :height + + def type + 'rich' + end + + def version + '1.0' + end + + def author_name + object.account.display_name.presence || object.account.username + end + + def author_url + account_url(object.account) + end + + def provider_name + Rails.configuration.x.local_domain + end + + def provider_url + root_url + end + + def cache_age + 86_400 + end + + def html + tag :iframe, + src: embed_account_stream_entry_url(object.account, object), + style: 'width: 100%; overflow: hidden', + frameborder: '0', + scrolling: 'no', + width: width, + height: height + end + + def width + instance_options[:width] + end + + def height + instance_options[:height] + end +end diff --git a/app/views/api/oembed/show.json.rabl b/app/views/api/oembed/show.json.rabl deleted file mode 100644 index 11dcec538..000000000 --- a/app/views/api/oembed/show.json.rabl +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true -object @stream_entry - -node(:type) { 'rich' } -node(:version) { '1.0' } -node(:title, &:title) -node(:author_name) { |entry| entry.account.display_name.blank? ? entry.account.username : entry.account.display_name } -node(:author_url) { |entry| account_url(entry.account) } -node(:provider_name) { site_hostname } -node(:provider_url) { root_url } -node(:cache_age) { 86_400 } -node(:html) { |entry| "" } -node(:width) { @width } -node(:height) { @height } diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 33c978c89..71dcb54c6 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - %script#initial-state{ type: 'application/json' }!= json_escape(render(file: 'home/initial_state', formats: :json)) + %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = javascript_pack_tag 'application', integrity: true, crossorigin: 'anonymous' diff --git a/app/views/home/initial_state.json.rabl b/app/views/home/initial_state.json.rabl deleted file mode 100644 index c428a5a1f..000000000 --- a/app/views/home/initial_state.json.rabl +++ /dev/null @@ -1,38 +0,0 @@ -object false - -node(:meta) do - { - streaming_api_base_url: @streaming_api_base_url, - access_token: @token, - locale: I18n.locale, - domain: site_hostname, - me: current_account.id, - admin: @admin.try(:id), - boost_modal: current_account.user.setting_boost_modal, - delete_modal: current_account.user.setting_delete_modal, - auto_play_gif: current_account.user.setting_auto_play_gif, - system_font_ui: current_account.user.setting_system_font_ui, - } -end - -node(:compose) do - { - me: current_account.id, - default_privacy: current_account.user.setting_default_privacy, - } -end - -node(:accounts) do - store = {} - store[current_account.id] = ActiveModelSerializers::SerializableResource.new(current_account, serializer: REST::AccountSerializer) - store[@admin.id] = ActiveModelSerializers::SerializableResource.new(@admin, serializer: REST::AccountSerializer) unless @admin.nil? - store -end - -node(:media_attachments) do - { - accept_content_types: MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES - } -end - -node(:settings) { @web_settings } diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index cc1dbe5a1..d44d720b1 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -23,41 +23,14 @@ RSpec.describe HomeController, type: :controller do expect(assigns(:body_classes)).to eq 'app-body' end - it 'assigns @token' do - app = Doorkeeper::Application.create!(name: 'Web', superapp: true, redirect_uri: Doorkeeper.configuration.native_redirect_uri) - allow(Doorkeeper.configuration).to receive(:access_token_expires_in).and_return(42) - - subject - token = Doorkeeper::AccessToken.find_by(token: assigns(:token)) - - expect(token.application).to eq app - expect(token.resource_owner_id).to eq user.id - expect(token.scopes).to eq Doorkeeper::OAuth::Scopes.from_string('read write follow') - expect(token.expires_in_seconds).to eq 42 - expect(token.use_refresh_token?).to eq false - end - - it 'assigns @web_settings for {} if not available' do - subject - expect(assigns(:web_settings)).to eq({}) - end - - it 'assigns @web_settings for Web::Setting if available' do - setting = Fabricate('Web::Setting', data: '{"home":{}}', user: user) - subject - expect(assigns(:web_settings)).to eq setting.data - end - - it 'assigns @admin' do - admin = Fabricate(:account) - Setting.site_contact_username = admin.username - subject - expect(assigns(:admin)).to eq admin - end - - it 'assigns streaming_api_base_url' do + it 'assigns @initial_state_json' do subject - expect(assigns(:streaming_api_base_url)).to eq 'ws://localhost:4000' + initial_state_json = json_str_to_hash(assigns(:initial_state_json)) + expect(initial_state_json[:meta]).to_not be_nil + expect(initial_state_json[:compose]).to_not be_nil + expect(initial_state_json[:accounts]).to_not be_nil + expect(initial_state_json[:settings]).to_not be_nil + expect(initial_state_json[:media_attachments]).to_not be_nil end end end -- cgit From f8212da329cf857478746c23314e5c662cd490e3 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Mon, 10 Jul 2017 10:29:34 +0900 Subject: Add attribute for default privacy to verify credentials (#4075) * Add attribute for default privacy to verify credentials * add raw_note * source --- app/controllers/api/v1/accounts/credentials_controller.rb | 4 ++-- app/serializers/rest/credential_account_serializer.rb | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 app/serializers/rest/credential_account_serializer.rb (limited to 'app/serializers') diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb index 8ee9a2416..073808532 100644 --- a/app/controllers/api/v1/accounts/credentials_controller.rb +++ b/app/controllers/api/v1/accounts/credentials_controller.rb @@ -6,13 +6,13 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController def show @account = current_account - render json: @account, serializer: REST::AccountSerializer + render json: @account, serializer: REST::CredentialAccountSerializer end def update current_account.update!(account_params) @account = current_account - render json: @account, serializer: REST::AccountSerializer + render json: @account, serializer: REST::CredentialAccountSerializer end private diff --git a/app/serializers/rest/credential_account_serializer.rb b/app/serializers/rest/credential_account_serializer.rb new file mode 100644 index 000000000..094b831c9 --- /dev/null +++ b/app/serializers/rest/credential_account_serializer.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class REST::CredentialAccountSerializer < REST::AccountSerializer + attributes :source + + def source + user = object.user + { + privacy: user.setting_default_privacy, + note: object.note, + } + end +end -- cgit From 2b9721d1b38319d70bed98e76a0fe1d648780298 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Mon, 10 Jul 2017 21:00:32 +0900 Subject: Add setting a always mark media as sensitive (#4136) --- app/controllers/settings/preferences_controller.rb | 1 + app/javascript/mastodon/reducers/compose.js | 7 +++++++ app/lib/user_settings_decorator.rb | 5 +++++ app/models/user.rb | 4 ++++ app/serializers/initial_state_serializer.rb | 1 + app/serializers/rest/credential_account_serializer.rb | 1 + app/views/settings/preferences/show.html.haml | 2 ++ config/locales/simple_form.en.yml | 1 + spec/lib/user_settings_decorator_spec.rb | 7 +++++++ 9 files changed, 29 insertions(+) (limited to 'app/serializers') diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index a15c26031..cac5b0ba8 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -34,6 +34,7 @@ class Settings::PreferencesController < ApplicationController def user_settings_params params.require(:user).permit( :setting_default_privacy, + :setting_default_sensitive, :setting_boost_modal, :setting_delete_modal, :setting_auto_play_gif, diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index d0b47a85c..752377739 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -45,6 +45,7 @@ const initialState = Immutable.Map({ suggestions: Immutable.List(), me: null, default_privacy: 'public', + default_sensitive: false, resetFileKey: Math.floor((Math.random() * 0x10000)), idempotencyKey: null, }); @@ -75,6 +76,8 @@ function clearAll(state) { }; function appendMedia(state, media) { + const prevSize = state.get('media_attachments').size; + return state.withMutations(map => { map.update('media_attachments', list => list.push(media)); map.set('is_uploading', false); @@ -82,6 +85,10 @@ function appendMedia(state, media) { map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`); map.set('focusDate', new Date()); map.set('idempotencyKey', uuid()); + + if (prevSize === 0 && state.get('default_sensitive')) { + map.set('sensitive', true); + } }); }; diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 9c0cb4545..e0e92b19d 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -18,6 +18,7 @@ class UserSettingsDecorator user.settings['notification_emails'] = merged_notification_emails user.settings['interactions'] = merged_interactions user.settings['default_privacy'] = default_privacy_preference + user.settings['default_sensitive'] = default_sensitive_preference user.settings['boost_modal'] = boost_modal_preference user.settings['delete_modal'] = delete_modal_preference user.settings['auto_play_gif'] = auto_play_gif_preference @@ -36,6 +37,10 @@ class UserSettingsDecorator settings['setting_default_privacy'] end + def default_sensitive_preference + boolean_cast_setting 'setting_default_sensitive' + end + def boost_modal_preference boolean_cast_setting 'setting_boost_modal' end diff --git a/app/models/user.rb b/app/models/user.rb index e2bb3d0ed..c80115a08 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -79,6 +79,10 @@ class User < ApplicationRecord settings.default_privacy || (account.locked? ? 'private' : 'public') end + def setting_default_sensitive + settings.default_sensitive + end + def setting_boost_modal settings.boost_modal end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 84f9e23a6..49ff9e377 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -23,6 +23,7 @@ class InitialStateSerializer < ActiveModel::Serializer { me: object.current_account.id, default_privacy: object.current_account.user.setting_default_privacy, + default_sensitive: object.current_account.user.setting_default_sensitive, } end diff --git a/app/serializers/rest/credential_account_serializer.rb b/app/serializers/rest/credential_account_serializer.rb index 094b831c9..870d8b71f 100644 --- a/app/serializers/rest/credential_account_serializer.rb +++ b/app/serializers/rest/credential_account_serializer.rb @@ -7,6 +7,7 @@ class REST::CredentialAccountSerializer < REST::AccountSerializer user = object.user { privacy: user.setting_default_privacy, + sensitive: user.setting_default_sensitive, note: object.note, } end diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index 26fbfdf82..56a261ab6 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -24,6 +24,8 @@ = f.input :setting_default_privacy, collection: Status.visibilities.keys - ['direct'], wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), content_tag(:span, I18n.t("statuses.visibilities.#{visibility}_long"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' + = f.input :setting_default_sensitive, as: :boolean, wrapper: :with_label + .fields-group = f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff| = ff.input :follow, as: :boolean, wrapper: :with_label diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index d8d3b8a6f..fc5ab5ec8 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -37,6 +37,7 @@ en: setting_auto_play_gif: Auto-play animated GIFs setting_boost_modal: Show confirmation dialog before boosting setting_default_privacy: Post privacy + setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog before deleting a toot setting_system_font_ui: Use system's default font severity: Severity diff --git a/spec/lib/user_settings_decorator_spec.rb b/spec/lib/user_settings_decorator_spec.rb index e1ba56d97..a67487779 100644 --- a/spec/lib/user_settings_decorator_spec.rb +++ b/spec/lib/user_settings_decorator_spec.rb @@ -28,6 +28,13 @@ describe UserSettingsDecorator do expect(user.settings['default_privacy']).to eq 'public' end + it 'updates the user settings value for sensitive' do + values = { 'setting_default_sensitive' => '1' } + + settings.update(values) + expect(user.settings['default_sensitive']).to eq true + end + it 'updates the user settings value for boost modal' do values = { 'setting_boost_modal' => '1' } -- cgit From e19eefe219c46ea9f763d0279029f03c5cf4554f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 11 Jul 2017 15:27:59 +0200 Subject: Redesign the landing page, mount public timeline on it (#4122) * Redesign the landing page, mount public timeline on it * Adjust the standalone mounted component to the lacking of router * Adjust auth layout pages to new design * Fix tests * Standalone public timeline polling every 5 seconds * Remove now obsolete translations * Add responsive design for new landing page * Address reviews * Add floating clouds behind frontpage form * Use access token from public page when available * Fix mentions and hashtags links, cursor on status content in standalone mode * Add footer link to source code * Fix errors on pages that don't embed the component, use classnames * Fix tests * Change anonymous autoPlayGif default to false * When gif autoplay is disabled, hover to play * Add option to hide the timeline preview * Slightly improve alt layout * Add elephant friend to new frontpage * Display "back to mastodon" in place of "login" when logged in on frontpage * Change polling time to 3s --- app/controllers/about_controller.rb | 13 +- app/controllers/admin/settings_controller.rb | 9 +- app/controllers/home_controller.rb | 16 +- .../fonts/montserrat/Montserrat-Medium.ttf | Bin 0 -> 192488 bytes app/javascript/images/cloud2.png | Bin 0 -> 4973 bytes app/javascript/images/cloud3.png | Bin 0 -> 5860 bytes app/javascript/images/cloud4.png | Bin 0 -> 5273 bytes app/javascript/images/elephant-fren.png | Bin 0 -> 40859 bytes app/javascript/images/logo.svg | 2 +- .../mastodon/components/dropdown_menu.js | 19 +- .../mastodon/components/media_gallery.js | 38 +- app/javascript/mastodon/components/permalink.js | 4 +- app/javascript/mastodon/components/status.js | 8 +- .../mastodon/components/status_action_bar.js | 11 +- .../mastodon/components/status_content.js | 17 +- app/javascript/mastodon/components/video_player.js | 22 +- .../mastodon/containers/timeline_container.js | 39 ++ .../features/standalone/public_timeline/index.js | 76 ++++ app/javascript/packs/public.js | 10 + app/javascript/styles/about.scss | 448 ++++++++++++++++++--- app/javascript/styles/basics.scss | 7 +- app/javascript/styles/boost.scss | 4 + app/javascript/styles/components.scss | 32 +- app/javascript/styles/containers.scss | 48 +-- app/javascript/styles/fonts/montserrat.scss | 8 + app/javascript/styles/forms.scss | 39 +- app/presenters/instance_presenter.rb | 1 + app/serializers/initial_state_serializer.rb | 35 +- app/views/about/_features.html.haml | 25 ++ app/views/about/_registration.html.haml | 20 +- app/views/about/show.html.haml | 120 +++--- app/views/admin/settings/edit.html.haml | 43 +- app/views/auth/registrations/new.html.haml | 6 +- app/views/layouts/auth.html.haml | 3 +- config/locales/ar.yml | 13 +- config/locales/bg.yml | 13 +- config/locales/ca.yml | 17 +- config/locales/de.yml | 13 - config/locales/en.yml | 43 +- config/locales/eo.yml | 23 +- config/locales/es.yml | 13 +- config/locales/fa.yml | 13 - config/locales/fi.yml | 13 +- config/locales/fr.yml | 15 +- config/locales/he.yml | 13 - config/locales/hr.yml | 13 +- config/locales/id.yml | 13 - config/locales/io.yml | 13 - config/locales/it.yml | 13 +- config/locales/ja.yml | 15 +- config/locales/ko.yml | 19 +- config/locales/nl.yml | 21 +- config/locales/no.yml | 13 - config/locales/oc.yml | 17 +- config/locales/pl.yml | 19 +- config/locales/pt-BR.yml | 13 - config/locales/pt.yml | 13 - config/locales/ru.yml | 13 - config/locales/th.yml | 13 - config/locales/tr.yml | 13 - config/locales/uk.yml | 13 - config/locales/zh-CN.yml | 13 - config/locales/zh-HK.yml | 13 - config/locales/zh-TW.yml | 13 - config/settings.yml | 1 + lib/tasks/mastodon.rake | 8 +- spec/requests/localization_spec.rb | 8 +- spec/views/about/show.html.haml_spec.rb | 9 +- 68 files changed, 956 insertions(+), 655 deletions(-) create mode 100644 app/javascript/fonts/montserrat/Montserrat-Medium.ttf create mode 100644 app/javascript/images/cloud2.png create mode 100644 app/javascript/images/cloud3.png create mode 100644 app/javascript/images/cloud4.png create mode 100644 app/javascript/images/elephant-fren.png create mode 100644 app/javascript/mastodon/containers/timeline_container.js create mode 100644 app/javascript/mastodon/features/standalone/public_timeline/index.js create mode 100644 app/views/about/_features.html.haml (limited to 'app/serializers') diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb index c0addbecc..47690e81e 100644 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@ -4,7 +4,10 @@ class AboutController < ApplicationController before_action :set_body_classes before_action :set_instance_presenter, only: [:show, :more, :terms] - def show; end + def show + serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer) + @initial_state_json = serializable_resource.to_json + end def more; end @@ -15,6 +18,7 @@ class AboutController < ApplicationController def new_user User.new.tap(&:build_account) end + helper_method :new_user def set_instance_presenter @@ -24,4 +28,11 @@ class AboutController < ApplicationController def set_body_classes @body_classes = 'about-body' end + + def initial_state_params + { + settings: {}, + token: current_session&.token, + } + end end diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index f27a1f4d4..29b590d7a 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -11,8 +11,15 @@ module Admin site_terms open_registrations closed_registrations_message + open_deletion + timeline_preview + ).freeze + + BOOLEAN_SETTINGS = %w( + open_registrations + open_deletion + timeline_preview ).freeze - BOOLEAN_SETTINGS = %w(open_registrations).freeze def edit @settings = Setting.all_as_records diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 218da6906..8a8b9ec76 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -15,12 +15,16 @@ class HomeController < ApplicationController end def set_initial_state_json - state = InitialStatePresenter.new(settings: Web::Setting.find_by(user: current_user)&.data || {}, - current_account: current_account, - token: current_session.token, - admin: Account.find_local(Setting.site_contact_username)) - - serializable_resource = ActiveModelSerializers::SerializableResource.new(state, serializer: InitialStateSerializer) + serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer) @initial_state_json = serializable_resource.to_json end + + def initial_state_params + { + settings: Web::Setting.find_by(user: current_user)&.data || {}, + current_account: current_account, + token: current_session.token, + admin: Account.find_local(Setting.site_contact_username), + } + end end diff --git a/app/javascript/fonts/montserrat/Montserrat-Medium.ttf b/app/javascript/fonts/montserrat/Montserrat-Medium.ttf new file mode 100644 index 000000000..88d70b89c Binary files /dev/null and b/app/javascript/fonts/montserrat/Montserrat-Medium.ttf differ diff --git a/app/javascript/images/cloud2.png b/app/javascript/images/cloud2.png new file mode 100644 index 000000000..f325ca6de Binary files /dev/null and b/app/javascript/images/cloud2.png differ diff --git a/app/javascript/images/cloud3.png b/app/javascript/images/cloud3.png new file mode 100644 index 000000000..ab194d0b8 Binary files /dev/null and b/app/javascript/images/cloud3.png differ diff --git a/app/javascript/images/cloud4.png b/app/javascript/images/cloud4.png new file mode 100644 index 000000000..98323f5a2 Binary files /dev/null and b/app/javascript/images/cloud4.png differ diff --git a/app/javascript/images/elephant-fren.png b/app/javascript/images/elephant-fren.png new file mode 100644 index 000000000..3b64edf08 Binary files /dev/null and b/app/javascript/images/elephant-fren.png differ diff --git a/app/javascript/images/logo.svg b/app/javascript/images/logo.svg index c233db842..16cb3a944 100644 --- a/app/javascript/images/logo.svg +++ b/app/javascript/images/logo.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js index 12e1b44fa..98323b069 100644 --- a/app/javascript/mastodon/components/dropdown_menu.js +++ b/app/javascript/mastodon/components/dropdown_menu.js @@ -14,6 +14,7 @@ export default class DropdownMenu extends React.PureComponent { size: PropTypes.number.isRequired, direction: PropTypes.string, ariaLabel: PropTypes.string, + disabled: PropTypes.bool, }; static defaultProps = { @@ -68,9 +69,19 @@ export default class DropdownMenu extends React.PureComponent { } render () { - const { icon, items, size, direction, ariaLabel } = this.props; - const { expanded } = this.state; + const { icon, items, size, direction, ariaLabel, disabled } = this.props; + const { expanded } = this.state; const directionClass = (direction === 'left') ? 'dropdown__left' : 'dropdown__right'; + const iconStyle = { fontSize: `${size}px`, width: `${size}px`, lineHeight: `${size}px` }; + const iconClassname = `fa fa-fw fa-${icon} dropdown__icon`; + + if (disabled) { + return ( +
+ +
+ ); + } const dropdownItems = expanded && (