diff options
Diffstat (limited to 'app/views')
39 files changed, 447 insertions, 229 deletions
diff --git a/app/views/about/_forms.html.haml b/app/views/about/_forms.html.haml new file mode 100644 index 000000000..81f7173f7 --- /dev/null +++ b/app/views/about/_forms.html.haml @@ -0,0 +1,15 @@ +- if @instance_presenter.open_registrations + = render 'registration' +- else + = link_to t('auth.register_elsewhere'), 'https://joinmastodon.org', class: 'button button-primary' + + .closed-registrations-message + - if @instance_presenter.closed_registrations_message.blank? + %p= t('about.closed_registrations') + - else + = @instance_presenter.closed_registrations_message.html_safe + +.separator-or + %span= t('auth.or') + += link_to t('auth.login'), new_user_session_path, class: 'button button-alternative-2 webapp-btn' diff --git a/app/views/about/_links.html.haml b/app/views/about/_links.html.haml new file mode 100644 index 000000000..f79c37e65 --- /dev/null +++ b/app/views/about/_links.html.haml @@ -0,0 +1,16 @@ +.container-alt.links + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + + %ul.nav + %li + - if user_signed_in? + = link_to t('settings.back'), root_url, class: 'webapp-btn' + - else + = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn' + %li= link_to t('about.about_this'), about_more_path + %li + = link_to 'https://joinmastodon.org/' do + = "#{t('about.other_instances')}" + %i.fa.fa-external-link{ style: 'padding-left: 5px;' } diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml index 7a28f9738..6ca1d7129 100644 --- a/app/views/about/_registration.html.haml +++ b/app/views/about/_registration.html.haml @@ -10,6 +10,6 @@ = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' } .actions - = f.button :button, t('auth.register'), type: :submit, class: 'button button-alternative' + = f.button :button, t('auth.register'), type: :submit, class: 'button button-primary' %p.hint.subtle-hint=t('auth.agreement_html', rules_path: about_more_path, terms_path: terms_path) diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index d92362bd7..f86051fbf 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -7,51 +7,36 @@ .landing-page .header-wrapper.compact .header - .container.links - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + = render 'links' - %ul.nav - %li - - if user_signed_in? - = link_to t('settings.back'), root_url, class: 'webapp-btn' - - else - = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn' - %li= link_to t('about.about_this'), about_more_path - %li - = link_to 'https://joinmastodon.org/' do - = "#{t('about.other_instances')}" - %i.fa.fa-external-link{ style: 'padding-left: 5px;' } - - .container.hero + .container-alt.hero .heading %h3= t('about.description_headline', domain: site_hostname) %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) .information-board - .container - .information-board-sections - .section + .container-alt + .information-board__sections + .information-board__section %span= t 'about.user_count_before' %strong= number_with_delimiter @instance_presenter.user_count %span= t 'about.user_count_after' - .section + .information-board__section %span= t 'about.status_count_before' %strong= number_with_delimiter @instance_presenter.status_count %span= t 'about.status_count_after' - .section + .information-board__section %span= t 'about.domain_count_before' %strong= number_with_delimiter @instance_presenter.domain_count %span= t 'about.domain_count_after' = render 'contact', contact: @instance_presenter .extended-description - .container + .container-alt = @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html') .footer-links - .container + .container-alt %p = link_to t('about.source_code'), @instance_presenter.source_url - if @instance_presenter.commit_hash == "" diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 4f5b53470..2f0b31a9f 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -2,80 +2,134 @@ = site_hostname - content_for :header_tags do + %link{ rel: 'canonical', href: about_url }/ %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = render partial: 'shared/og' -.landing-page - .header-wrapper - .mascot-container - = image_tag asset_pack_path('elephant-fren.png'), alt: '', role: 'presentation', class: 'mascot' - - .header - .container.links +.landing-page.alternative + .container + .grid + .column-0 .brand = link_to root_url do = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - %ul.nav - %li - - if user_signed_in? - = link_to t('settings.back'), root_url, class: 'webapp-btn' - - else - = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn' - %li= link_to t('about.about_this'), about_more_path - %li - = link_to 'https://joinmastodon.org/' do - = "#{t('about.other_instances')}" - %i.fa.fa-external-link{ style: 'padding-left: 5px;' } - - .container.hero - .floats - %div{ role: 'presentation', class: 'float-1' } - %div{ role: 'presentation', class: 'float-2' } - %div{ role: 'presentation', class: 'float-3' } - .heading - %h1 - = @instance_presenter.site_title - %small= t 'about.hosted_on', domain: site_hostname - - if @instance_presenter.open_registrations - = render 'registration' - - else - .closed-registrations-message - %div - - if @instance_presenter.closed_registrations_message.blank? - %p= t('about.closed_registrations') - - else - = @instance_presenter.closed_registrations_message.html_safe - - = simple_form_for(:user, html: { style: 'margin-left: -20px' }, url: session_path(:user)) do |f| - = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } - = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' } - - .actions - = f.button :button, t('auth.login'), type: :submit - = link_to t('about.find_another_instance'), 'https://joinmastodon.org/', class: 'button button-alternative button--block' - - .about-short - .container - %h3= t('about.description_headline', domain: site_hostname) - %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) - - .features - .container - if Setting.timeline_preview - #mastodon-timeline{ data: { props: Oj.dump(default_props) } } - - .about-mastodon - %h3= t 'about.what_is_mastodon' - %p= t 'about.about_mastodon_html' - = link_to t('about.learn_more'), 'https://joinmastodon.org/', class: 'button button-secondary' - = render 'features' - .footer-links - .container - %p - = link_to t('about.source_code'), @instance_presenter.source_url - - if @instance_presenter.commit_hash == "" - %strong= " (#{@instance_presenter.version_number})" - - else - %strong= " (#{@instance_presenter.version_number}, " - %strong= " #{@instance_presenter.commit_hash})" + .column-1 + .landing-page__forms + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + + = render 'forms' + + - else + .column-1.non-preview + .landing-page__forms + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + + = render 'forms' + + - if Setting.timeline_preview + .column-2 + .landing-page__hero + = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title + + .landing-page__information + .landing-page__short-description + .row + .landing-page__logo + = image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon' + + %h1 + = @instance_presenter.site_title + %small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname) + + %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + + .landing-page__call-to-action + .row + .row__information-board + .information-board__section + %span= t 'about.user_count_before' + %strong= number_with_delimiter @instance_presenter.user_count + %span= t 'about.user_count_after' + .information-board__section + %span= t 'about.status_count_before' + %strong= number_with_delimiter @instance_presenter.status_count + %span= t 'about.status_count_after' + .row__mascot + .landing-page__mascot + = image_tag asset_pack_path('elephant_ui_plane.svg') + + - else + .column-2.non-preview + .landing-page__hero + = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title + + .landing-page__information + .landing-page__short-description + .row + .landing-page__logo + = image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon' + + %h1 + = @instance_presenter.site_title + %small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname) + + %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + + .landing-page__call-to-action + .row + .row__information-board + .information-board__section + %span= t 'about.user_count_before' + %strong= number_with_delimiter @instance_presenter.user_count + %span= t 'about.user_count_after' + .information-board__section + %span= t 'about.status_count_before' + %strong= number_with_delimiter @instance_presenter.status_count + %span= t 'about.status_count_after' + .row__mascot + .landing-page__mascot + = image_tag asset_pack_path('elephant_ui_plane.svg') + + - if Setting.timeline_preview + .column-3 + #mastodon-timeline{ data: { props: Oj.dump(default_props) } } + + - if Setting.timeline_preview + .column-4.landing-page__information + .landing-page__features + .features-list + %div + %h3= t 'about.what_is_mastodon' + %p= t 'about.about_mastodon_html' + + = render 'features' + + .landing-page__features__action + = link_to t('about.learn_more'), 'https://joinmastodon.org/', class: 'button button-alternative' + + .landing-page__footer + %p + = link_to t('about.source_code'), @instance_presenter.source_url + = " (#{@instance_presenter.version_number})" + + - else + .column-4.non-preview.landing-page__information + .landing-page__features + %h3= t 'about.what_is_mastodon' + %p= t 'about.about_mastodon_html' + + = render 'features' + + .landing-page__features__action + = link_to t('about.learn_more'), 'https://joinmastodon.org/', class: 'button button-alternative' + + .landing-page__footer + %p + = link_to t('about.source_code'), @instance_presenter.source_url + = " (#{@instance_presenter.version_number})" diff --git a/app/views/about/terms.html.haml b/app/views/about/terms.html.haml index 7004cb0b1..c7d36ed47 100644 --- a/app/views/about/terms.html.haml +++ b/app/views/about/terms.html.haml @@ -4,20 +4,8 @@ .landing-page .header-wrapper.compact .header - .container.links - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - - %ul.nav - %li - - if user_signed_in? - = link_to t('settings.back'), root_url, class: 'webapp-btn' - - else - = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn' - %li= link_to t('about.about_this'), about_more_path - %li= link_to t('about.other_instances'), 'https://joinmastodon.org/' + = render 'links' .extended-description - .container + .container-alt = @instance_presenter.site_terms.html_safe.presence || t('terms.body_html') diff --git a/app/views/accounts/_follow_button.html.haml b/app/views/accounts/_follow_button.html.haml new file mode 100644 index 000000000..e476e0aff --- /dev/null +++ b/app/views/accounts/_follow_button.html.haml @@ -0,0 +1,23 @@ +- relationships ||= nil + +- unless account.memorial? || account.moved? + - if user_signed_in? + - requested = relationships ? relationships.requested[account.id].present? : current_account.requested?(account) + - following = relationships ? relationships.following[account.id].present? : current_account.following?(account) + + - if user_signed_in? && current_account.id != account.id && !requested + .controls + - if following + = link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do + = fa_icon 'user-times' + = t('accounts.unfollow') + - else + = link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do + = fa_icon 'user-plus' + = t('accounts.follow') + - elsif !user_signed_in? + .controls + .remote-follow + = link_to account_remote_follow_path(account), class: 'icon-button' do + = fa_icon 'user-plus' + = t('accounts.remote_follow') diff --git a/app/views/accounts/_grid_card.html.haml b/app/views/accounts/_grid_card.html.haml index 305eb2c44..95acbd581 100644 --- a/app/views/accounts/_grid_card.html.haml +++ b/app/views/accounts/_grid_card.html.haml @@ -1,9 +1,12 @@ .account-grid-card .account-grid-card__header{ style: "background-image: url(#{account.header.url(:original)})" } + = render 'accounts/follow_button', account: account, relationships: @relationships .account-grid-card__avatar .avatar= image_tag account.avatar.url(:original) .name = link_to TagManager.instance.url_for(account) do %span.display_name.emojify= display_name(account) - %span.username @#{account.acct} - %p.note.emojify= truncate(strip_tags(account.note), length: 150) + %span.username + @#{account.local? ? account.local_username_and_domain : account.acct} + = fa_icon('lock') if account.locked? + .account__header__content.p-note.emojify= Formatter.instance.simplified_format(account) diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index b0062752c..74251b923 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -1,24 +1,7 @@ - processed_bio = FrontmatterHandler.instance.process_bio Formatter.instance.simplified_format account .card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" } .card__illustration - - unless account.memorial? || account.moved? - - if user_signed_in? && current_account.id != account.id && !current_account.requested?(account) - .controls - - if current_account.following?(account) - = link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do - = fa_icon 'user-times' - = t('accounts.unfollow') - - else - = link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do - = fa_icon 'user-plus' - = t('accounts.follow') - - elsif !user_signed_in? - .controls - .remote-follow - = link_to account_remote_follow_path(account), class: 'icon-button' do - = fa_icon 'user-plus' - = t('accounts.remote_follow') - + = render 'accounts/follow_button', account: account .avatar= image_tag account.avatar.url(:original), class: 'u-photo' .card__bio diff --git a/app/views/accounts/_og.html.haml b/app/views/accounts/_og.html.haml index 1d16be590..26424a49c 100644 --- a/app/views/accounts/_og.html.haml +++ b/app/views/accounts/_og.html.haml @@ -1,7 +1,7 @@ = opengraph 'og:url', url = opengraph 'og:site_name', site_title = opengraph 'og:title', [yield(:page_title).strip.presence, site_title].compact.join(' - ') -= opengraph 'og:description', account.note += opengraph 'og:description', account_description(account) = opengraph 'og:image', full_asset_url(account.avatar.url(:original)) = opengraph 'og:image:width', '120' = opengraph 'og:image:height', '120' diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index accad5f78..c62a573b0 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -1,7 +1,9 @@ - content_for :page_title do - = display_name(@account) + = "#{display_name(@account)} (@#{@account.username})" - content_for :header_tags do + %meta{ name: 'description', content: account_description(@account) }/ + - if @account.user&.setting_noindex %meta{ name: 'robots', content: 'noindex' }/ @@ -9,6 +11,11 @@ %link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/ %link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@account) }/ + - if @older_url + %link{ rel: 'next', href: @older_url }/ + - if @newer_url + %link{ rel: 'prev', href: @newer_url }/ + = opengraph 'og:type', 'profile' = render 'og', account: @account, url: short_account_url(@account, only_path: false) @@ -39,6 +46,9 @@ = render partial: 'stream_entries/status', collection: @statuses, as: :status - - if @statuses.size == 20 + - if @newer_url || @older_url .pagination - = link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), @next_url, class: 'next', rel: 'next' + - if @older_url + = link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'next' + - if @newer_url + = link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'prev' diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index 5f5d0995c..dbbf5fc09 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -18,7 +18,10 @@ %tr %th= t('admin.accounts.role') %td - = t("admin.accounts.roles.#{@account.user&.role}") + - if @account.user.nil? + = t("admin.accounts.moderation.suspended") + - else + = t("admin.accounts.roles.#{@account.user&.role}") = table_link_to 'angle-double-up', t('admin.accounts.promote'), promote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:promote, @account.user) = table_link_to 'angle-double-down', t('admin.accounts.demote'), demote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:demote, @account.user) %tr diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 4f9115ed2..08d05d738 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -12,6 +12,7 @@ .fields-group = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') + = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html') %hr/ @@ -19,6 +20,9 @@ = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html') .fields-group + = f.input :show_known_fediverse_at_about_page, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_known_fediverse_at_about_page.title'), hint: t('admin.settings.show_known_fediverse_at_about_page.desc_html') + + .fields-group = f.input :show_staff_badge, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_staff_badge.title'), hint: t('admin.settings.show_staff_badge.desc_html') .fields-group diff --git a/app/views/auth/confirmations/finish_signup.html.haml b/app/views/auth/confirmations/finish_signup.html.haml new file mode 100644 index 000000000..4b5161d6b --- /dev/null +++ b/app/views/auth/confirmations/finish_signup.html.haml @@ -0,0 +1,14 @@ +- content_for :page_title do + = t('auth.confirm_email') + += simple_form_for(current_user, as: 'user', url: finish_signup_path, html: { role: 'form'}) do |f| + - if @show_errors && current_user.errors.any? + #error_explanation + - current_user.errors.full_messages.each do |msg| + = msg + %br + + = f.input :email + + .actions + = f.submit t('auth.confirm_email'), class: 'button' diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml index 5ef3de976..53d1769d6 100644 --- a/app/views/auth/passwords/edit.html.haml +++ b/app/views/auth/passwords/edit.html.haml @@ -3,12 +3,16 @@ = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| = render 'shared/error_messages', object: resource - = f.input :reset_password_token, as: :hidden - = f.input :password, autofocus: true, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } - = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' } + - if !use_seamless_external_login? || resource.encrypted_password.present? + = f.input :reset_password_token, as: :hidden - .actions - = f.button :button, t('auth.set_new_password'), type: :submit + = f.input :password, autofocus: true, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } + = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' } + + .actions + = f.button :button, t('auth.set_new_password'), type: :submit + - else + %p.hint= t('users.seamless_external_login') .form-footer= render 'auth/shared/links' diff --git a/app/views/auth/registrations/_sessions.html.haml b/app/views/auth/registrations/_sessions.html.haml index 8424a8901..8586c0549 100644 --- a/app/views/auth/registrations/_sessions.html.haml +++ b/app/views/auth/registrations/_sessions.html.haml @@ -1,4 +1,4 @@ -%h6= t 'sessions.title' +%h4= t 'sessions.title' %p.muted-hint= t 'sessions.explanation' .table-wrapper diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml index 145f5cd9e..05fc7df31 100644 --- a/app/views/auth/registrations/edit.html.haml +++ b/app/views/auth/registrations/edit.html.haml @@ -1,23 +1,24 @@ - content_for :page_title do - = t('auth.change_password') + = t('auth.security') +%h4= t('auth.change_password') = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit' }) do |f| = render 'shared/error_messages', object: resource - = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } - = f.input :password, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } - = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' } - = f.input :current_password, placeholder: t('simple_form.labels.defaults.current_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.current_password'), :autocomplete => 'off' } + - if !use_seamless_external_login? || resource.encrypted_password.present? + = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } + = f.input :password, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } + = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' } + = f.input :current_password, placeholder: t('simple_form.labels.defaults.current_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.current_password'), :autocomplete => 'off' } - .actions - = f.button :button, t('generic.save_changes'), type: :submit - -%hr/ + .actions + = f.button :button, t('generic.save_changes'), type: :submit + - else + %p.hint= t('users.seamless_external_login') = render 'sessions' - if open_deletion? - %hr/ - %h6= t('auth.delete_account') + %h4= t('auth.delete_account') %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path) diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml index a52b0053b..0c9f9d5fe 100644 --- a/app/views/auth/sessions/new.html.haml +++ b/app/views/auth/sessions/new.html.haml @@ -5,10 +5,22 @@ = render partial: 'shared/og' = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } + - if use_seamless_external_login? + = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.username_or_email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') } + - else + = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' } .actions = f.button :button, t('auth.login'), type: :submit +- if devise_mapping.omniauthable? and resource_class.omniauth_providers.any? + .simple_form.alternative-login + %h4= t('auth.or_log_in_with') + + .actions + - resource_class.omniauth_providers.each do |provider| + = link_to omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}" do + = t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize) + .form-footer= render 'auth/shared/links' diff --git a/app/views/authorize_follows/success.html.haml b/app/views/authorize_follows/success.html.haml index f0b495689..63ff3bcf1 100644 --- a/app/views/authorize_follows/success.html.haml +++ b/app/views/authorize_follows/success.html.haml @@ -12,5 +12,5 @@ .post-follow-actions %div= link_to t('authorize_follow.post_follow.web'), web_url("accounts/#{@account.id}"), class: 'button button--block' - %div= link_to t('authorize_follow.post_follow.return'), @account.url, class: 'button button--block' + %div= link_to t('authorize_follow.post_follow.return'), TagManager.instance.url_for(@account), class: 'button button--block' %div= t('authorize_follow.post_follow.close') diff --git a/app/views/follower_accounts/index.html.haml b/app/views/follower_accounts/index.html.haml index 738b31638..a24e4ea20 100644 --- a/app/views/follower_accounts/index.html.haml +++ b/app/views/follower_accounts/index.html.haml @@ -2,9 +2,7 @@ = t('accounts.people_who_follow', name: display_name(@account)) - content_for :header_tags do - - if @account.user&.setting_noindex - %meta{ name: 'robots', content: 'noindex' }/ - + %meta{ name: 'robots', content: 'noindex' }/ = render 'accounts/og', account: @account, url: account_followers_url(@account, only_path: false) = render 'accounts/header', account: @account diff --git a/app/views/following_accounts/index.html.haml b/app/views/following_accounts/index.html.haml index 9637c689f..67f6cfede 100644 --- a/app/views/following_accounts/index.html.haml +++ b/app/views/following_accounts/index.html.haml @@ -2,9 +2,7 @@ = t('accounts.people_followed_by', name: display_name(@account)) - content_for :header_tags do - - if @account.user&.setting_noindex - %meta{ name: 'robots', content: 'noindex' }/ - + %meta{ name: 'robots', content: 'noindex' }/ = render 'accounts/og', account: @account, url: account_followers_url(@account, only_path: false) = render 'accounts/header', account: @account diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 322d7403e..9ede598b3 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -2,7 +2,7 @@ %html{ lang: I18n.locale } %head %meta{ charset: 'utf-8' }/ - %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }/ + %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }/ %link{ rel: 'icon', href: favicon_path, type: 'image/x-icon' }/ %link{ rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }/ %link{ rel: 'mask-icon', href: '/mask-icon.svg', color: '#2B90D9' }/ @@ -11,11 +11,7 @@ %meta{ name: 'theme-color', content: '#282c37' }/ %meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/ - %title< - - if content_for?(:page_title) - = yield(:page_title) - = ' - ' - = title + %title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title = javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous' - if @theme diff --git a/app/views/layouts/auth.html.haml b/app/views/layouts/auth.html.haml index f4812ac6a..ca9c13945 100644 --- a/app/views/layouts/auth.html.haml +++ b/app/views/layouts/auth.html.haml @@ -1,5 +1,5 @@ - content_for :content do - .container + .container-alt .logo-container %h1 = link_to root_path do diff --git a/app/views/layouts/mailer.html.haml b/app/views/layouts/mailer.html.haml index ad15754d5..6321fec61 100644 --- a/app/views/layouts/mailer.html.haml +++ b/app/views/layouts/mailer.html.haml @@ -7,7 +7,7 @@ %title/ = stylesheet_pack_tag 'core/mailer' - %body + %body{ dir: locale_direction } %table.email-table{ cellspacing: 0, cellpadding: 0 } %tbody %tr diff --git a/app/views/layouts/modal.html.haml b/app/views/layouts/modal.html.haml index a5d79f5c0..e808593cd 100644 --- a/app/views/layouts/modal.html.haml +++ b/app/views/layouts/modal.html.haml @@ -8,7 +8,7 @@ = link_to destroy_user_session_path, method: :delete, class: 'logout-link icon-button' do = fa_icon 'sign-out' - .container= yield + .container-alt= yield .modal-layout__mastodon %div diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml index b3795eaad..07441a77d 100644 --- a/app/views/layouts/public.html.haml +++ b/app/views/layouts/public.html.haml @@ -1,5 +1,5 @@ - content_for :content do - .container= yield + .container-alt= yield .footer - if !user_signed_in? && single_user_mode? %span.single-user-login diff --git a/app/views/media/player.html.haml b/app/views/media/player.html.haml new file mode 100644 index 000000000..ea868b3f6 --- /dev/null +++ b/app/views/media/player.html.haml @@ -0,0 +1,2 @@ +%video{ poster: @media_attachment.file.url(:small), preload: 'auto', autoplay: 'autoplay', muted: 'muted', loop: 'loop', controls: 'controls', style: "width: #{@media_attachment.file.meta.dig('original', 'width')}px; height: #{@media_attachment.file.meta.dig('original', 'height')}px" } + %source{ src: @media_attachment.file.url(:original), type: @media_attachment.file_content_type } diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index 85f9294e9..f82ada146 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -1,6 +1,6 @@ - i ||= 0 -%table.email-table{ cellspacing: 0, cellpadding: 0 } +%table.email-table{ cellspacing: 0, cellpadding: 0, dir: 'ltr' } %tbody %tr %td.email-body @@ -19,12 +19,13 @@ %tbody %tr %td{ align: 'left', width: 48 } - = image_tag full_asset_url(status.account.avatar), alt:'' + = image_tag full_asset_url(status.account.avatar.url), alt:'' %td{ align: 'left' } %bdi= display_name(status.account) = "@#{status.account.acct}" - = Formatter.instance.format(status) + %div{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + = Formatter.instance.format(status) %p.status-footer = link_to l(status.created_at), web_url("statuses/#{status.id}") diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml index e0df1c480..89d768d3f 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -20,3 +20,26 @@ %th= t('exports.mutes') %td= @export.total_mutes %td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv) + +%p.muted-hint= t('exports.archive_takeout.hint_html') + +- if policy(:backup).create? + %p= link_to t('exports.archive_takeout.request'), settings_export_path, class: 'button', method: :post + +- unless @backups.empty? + .table-wrapper + %table.table + %thead + %tr + %th= t('exports.archive_takeout.date') + %th= t('exports.archive_takeout.size') + %th + %tbody + - @backups.each do |backup| + %tr + %td= l backup.created_at + - if backup.processed? + %td= number_to_human_size backup.dump_file_size + %td= table_link_to 'download', t('exports.archive_takeout.download'), backup.dump.url + - else + %td{ colspan: 2 }= t('exports.archive_takeout.in_progress') diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index d1459d93c..102e4d200 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -4,6 +4,9 @@ = simple_form_for current_user, url: settings_preferences_path, html: { method: :put } do |f| = render 'shared/error_messages', object: current_user + .actions.actions--top + = f.button :button, t('generic.save_changes'), type: :submit + %h4= t 'preferences.languages' .fields-group @@ -33,6 +36,7 @@ .fields-group = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label + = f.input :setting_display_sensitive_media, as: :boolean, wrapper: :with_label = f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index d88ec8280..e1122d5a2 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -22,9 +22,9 @@ - if !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first - %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 670, height: 380, detailed: true) }}< + %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true) }} - else - %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, sensitive: status.sensitive?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }}< + %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }} - elsif status.preview_cards.first %div{ data: { component: 'Card', props: Oj.dump('maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json) }} diff --git a/app/views/stream_entries/_og_description.html.haml b/app/views/stream_entries/_og_description.html.haml index d2fa99e63..9c24e0a61 100644 --- a/app/views/stream_entries/_og_description.html.haml +++ b/app/views/stream_entries/_og_description.html.haml @@ -1,4 +1 @@ -- if activity.is_a?(Status) && activity.spoiler_text? - = opengraph 'og:description', activity.spoiler_text -- else - = opengraph 'og:description', activity.content += opengraph 'og:description', [activity.spoiler_text, activity.text].reject(&:blank?).join("\n\n") diff --git a/app/views/stream_entries/_og_image.html.haml b/app/views/stream_entries/_og_image.html.haml index 1056c1744..526034faa 100644 --- a/app/views/stream_entries/_og_image.html.haml +++ b/app/views/stream_entries/_og_image.html.haml @@ -1,23 +1,34 @@ -- if activity.is_a?(Status) && activity.non_sensitive_with_media? +- if activity.is_a?(Status) && activity.media_attachments.any? + - player_card = false - activity.media_attachments.each do |media| - if media.image? = opengraph 'og:image', full_asset_url(media.file.url(:original)) = opengraph 'og:image:type', media.file_content_type - unless media.file.meta.nil? - = opengraph 'og:image:width', media.file.meta['original']['width'] - = opengraph 'og:image:height', media.file.meta['original']['height'] - - elsif media.video? + = opengraph 'og:image:width', media.file.meta.dig('original', 'width') + = opengraph 'og:image:height', media.file.meta.dig('original', 'height') + - elsif media.video? || media.gifv? + - player_card = true = opengraph 'og:image', full_asset_url(media.file.url(:small)) = opengraph 'og:image:type', 'image/png' - unless media.file.meta.nil? - = opengraph 'og:image:width', media.file.meta['small']['width'] - = opengraph 'og:image:height', media.file.meta['small']['height'] + = opengraph 'og:image:width', media.file.meta.dig('small', 'width') + = opengraph 'og:image:height', media.file.meta.dig('small', 'height') = opengraph 'og:video', full_asset_url(media.file.url(:original)) + = opengraph 'og:video:secure_url', full_asset_url(media.file.url(:original)) = opengraph 'og:video:type', media.file_content_type + = opengraph 'twitter:player', medium_player_url(media) + = opengraph 'twitter:player:stream', full_asset_url(media.file.url(:original)) + = opengraph 'twitter:player:stream:content_type', media.file_content_type - unless media.file.meta.nil? - = opengraph 'og:video:width', media.file.meta['small']['width'] - = opengraph 'og:video:height', media.file.meta['small']['height'] - = opengraph 'twitter:card', 'summary_large_image' + = opengraph 'og:video:width', media.file.meta.dig('original', 'width') + = opengraph 'og:video:height', media.file.meta.dig('original', 'height') + = opengraph 'twitter:player:width', media.file.meta.dig('original', 'width') + = opengraph 'twitter:player:height', media.file.meta.dig('original', 'height') + - if player_card + = opengraph 'twitter:card', 'player' + - else + = opengraph 'twitter:card', 'summary_large_image' - else = opengraph 'og:image', full_asset_url(account.avatar.url(:original)) = opengraph 'og:image:width', '120' diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 0b45ff308..2ad1f5120 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -20,10 +20,9 @@ %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }< = Formatter.instance.format(status, custom_emojify: true) - - unless status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first - %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 610, height: 343) }}>< + %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343) }} - else - %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 343, sensitive: status.sensitive?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }}>< + %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }} diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml index cf6671e67..a87c51952 100644 --- a/app/views/stream_entries/show.html.haml +++ b/app/views/stream_entries/show.html.haml @@ -1,5 +1,5 @@ - content_for :page_title do - = t('statuses.title', name: display_name(@account), quote: truncate(@stream_entry.activity.spoiler_text.presence || @stream_entry.activity.text, length: 50, omission: '…')) + = t('statuses.title', name: display_name(@account), quote: truncate(@stream_entry.activity.spoiler_text.presence || @stream_entry.activity.text, length: 50, omission: '…', escape: false)) - content_for :header_tags do - if @account.user&.setting_noindex diff --git a/app/views/tags/_features.html.haml b/app/views/tags/_features.html.haml new file mode 100644 index 000000000..8fbc6b760 --- /dev/null +++ b/app/views/tags/_features.html.haml @@ -0,0 +1,25 @@ +.features-list + .features-list__row + .text + %h6= t 'about.features.real_conversation_title' + = t 'about.features.real_conversation_body' + .visual + = fa_icon 'fw comments' + .features-list__row + .text + %h6= t 'about.features.not_a_product_title' + = t 'about.features.not_a_product_body' + .visual + = fa_icon 'fw users' + .features-list__row + .text + %h6= t 'about.features.within_reach_title' + = t 'about.features.within_reach_body' + .visual + = fa_icon 'fw mobile' + .features-list__row + .text + %h6= t 'about.features.humane_approach_title' + = t 'about.features.humane_approach_body' + .visual + = fa_icon 'fw leaf' diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml index 03f19e20a..000aa0c4d 100644 --- a/app/views/tags/show.html.haml +++ b/app/views/tags/show.html.haml @@ -5,48 +5,31 @@ %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = render 'og' -.landing-page.tag-page +.landing-page.tag-page.alternative .features .container - #mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) } } + .grid + .column-1 + #mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) } } - .about-mastodon - .about-hashtag - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + .column-2 + .about-mastodon + .about-hashtag.landing-page__information + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - %p= t 'about.about_hashtag_html', hashtag: @tag.name + %p= t 'about.about_hashtag_html', hashtag: @tag.name - .cta - - if user_signed_in? - = link_to t('settings.back'), root_path, class: 'button button-secondary' - - else - = link_to t('auth.login'), new_user_session_path, class: 'button button-secondary' - = link_to t('about.learn_more'), about_path, class: 'button button-alternative' + .cta + - if user_signed_in? + = link_to t('settings.back'), root_path, class: 'button button-secondary' + - else + = link_to t('auth.login'), new_user_session_path, class: 'button button-secondary' + = link_to t('about.learn_more'), about_path, class: 'button button-alternative' - .features-list - .features-list__row - .text - %h6= t 'about.features.real_conversation_title' - = t 'about.features.real_conversation_body' - .visual - = fa_icon 'fw comments' - .features-list__row - .text - %h6= t 'about.features.not_a_product_title' - = t 'about.features.not_a_product_body' - .visual - = fa_icon 'fw users' - .features-list__row - .text - %h6= t 'about.features.within_reach_title' - = t 'about.features.within_reach_body' - .visual - = fa_icon 'fw mobile' - .features-list__row - .text - %h6= t 'about.features.humane_approach_title' - = t 'about.features.humane_approach_body' - .visual - = fa_icon 'fw leaf' + .landing-page__features.landing-page__information + %h3= t 'about.what_is_mastodon' + %p= t 'about.about_mastodon_html' + + = render 'features' diff --git a/app/views/user_mailer/backup_ready.html.haml b/app/views/user_mailer/backup_ready.html.haml new file mode 100644 index 000000000..d5a4b8b48 --- /dev/null +++ b/app/views/user_mailer/backup_ready.html.haml @@ -0,0 +1,59 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('icon_file_download.png'), alt: '' + + %h1= t 'user_mailer.backup_ready.title' + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center + %p= t 'user_mailer.backup_ready.explanation' + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to full_asset_url(@backup.dump.url) do + %span= t 'exports.archive_takeout.download' diff --git a/app/views/user_mailer/backup_ready.text.erb b/app/views/user_mailer/backup_ready.text.erb new file mode 100644 index 000000000..eb89e7d74 --- /dev/null +++ b/app/views/user_mailer/backup_ready.text.erb @@ -0,0 +1,7 @@ +<%= t 'user_mailer.backup_ready.title' %> + +=== + +<%= t 'user_mailer.backup_ready.explanation' %> + +=> <%= full_asset_url(@backup.dump.url) %> |