Browse Source

Redesign landing page (again) (#6486)

* Redesign landing page (again)

* Move login form in small version to the right column

* Display closed registrations message

* Add site setting for the hero image

* Fix test

* Increase spacing, maximum width, change call to action section
pull/4/head
Eugen Rochko 6 years ago
committed by GitHub
parent
commit
c71aa468b5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 553 additions and 306 deletions
  1. +2
    -0
      app/controllers/admin/settings_controller.rb
  2. +424
    -213
      app/javascript/styles/mastodon/about.scss
  3. +19
    -8
      app/javascript/styles/mastodon/components.scss
  4. +1
    -1
      app/javascript/styles/mastodon/containers.scss
  5. +4
    -0
      app/presenters/instance_presenter.rb
  6. +14
    -0
      app/views/about/_forms.html.haml
  7. +1
    -1
      app/views/about/_links.html.haml
  8. +1
    -1
      app/views/about/_registration.html.haml
  9. +8
    -8
      app/views/about/more.html.haml
  10. +71
    -48
      app/views/about/show.html.haml
  11. +1
    -1
      app/views/about/terms.html.haml
  12. +1
    -0
      app/views/admin/settings/edit.html.haml
  13. +0
    -1
      config/locales/ar.yml
  14. +0
    -1
      config/locales/ca.yml
  15. +0
    -1
      config/locales/de.yml
  16. +3
    -1
      config/locales/en.yml
  17. +0
    -1
      config/locales/es.yml
  18. +0
    -1
      config/locales/fa.yml
  19. +0
    -1
      config/locales/fi.yml
  20. +0
    -1
      config/locales/fr.yml
  21. +0
    -1
      config/locales/gl.yml
  22. +0
    -1
      config/locales/he.yml
  23. +0
    -1
      config/locales/hu.yml
  24. +0
    -1
      config/locales/ja.yml
  25. +0
    -1
      config/locales/ko.yml
  26. +0
    -1
      config/locales/nl.yml
  27. +0
    -1
      config/locales/no.yml
  28. +0
    -1
      config/locales/oc.yml
  29. +0
    -1
      config/locales/pl.yml
  30. +0
    -1
      config/locales/pt-BR.yml
  31. +0
    -1
      config/locales/pt.yml
  32. +0
    -1
      config/locales/ru.yml
  33. +0
    -1
      config/locales/sk.yml
  34. +0
    -1
      config/locales/sr-Latn.yml
  35. +0
    -1
      config/locales/sr.yml
  36. +0
    -1
      config/locales/sv.yml
  37. +0
    -1
      config/locales/zh-CN.yml
  38. +3
    -0
      spec/views/about/show.html.haml_spec.rb

+ 2
- 0
app/controllers/admin/settings_controller.rb View File

@ -16,6 +16,7 @@ module Admin
show_staff_badge
bootstrap_timeline_accounts
thumbnail
hero
min_invite_role
activity_api_enabled
peers_api_enabled
@ -34,6 +35,7 @@ module Admin
UPLOAD_SETTINGS = %w(
thumbnail
hero
).freeze
def edit

+ 424
- 213
app/javascript/styles/mastodon/about.scss View File

@ -1,3 +1,130 @@
$maximum-width: 1235px;
$fluid-breakpoint: $maximum-width + 20px;
$column-breakpoint: 700px;
$small-breakpoint: 960px;
.container {
box-sizing: border-box;
max-width: $maximum-width;
margin: 0 auto;
position: relative;
@media screen and (max-width: $fluid-breakpoint) {
width: 100%;
padding: 0 10px;
}
}
.show-xs,
.show-sm {
display: none;
}
.show-m {
display: block;
}
@media screen and (max-width: $small-breakpoint) {
.hide-sm {
display: none !important;
}
.show-sm {
display: block !important;
}
}
@media screen and (max-width: $column-breakpoint) {
.hide-xs {
display: none !important;
}
.show-xs {
display: block !important;
}
}
.row {
display: flex;
flex-wrap: wrap;
margin: 0 -5px;
@for $i from 1 through 15 {
.column-#{$i} {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
@media screen and (max-width: $small-breakpoint) {
&-sm {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
}
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
}
}
.column-flex {
display: flex;
flex-direction: column;
}
.separator-or {
position: relative;
margin: 40px 0;
text-align: center;
&::before {
content: "";
display: block;
width: 100%;
height: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
position: absolute;
top: 50%;
left: 0;
}
span {
display: inline-block;
background: $ui-base-color;
font-size: 12px;
font-weight: 500;
color: $ui-primary-color;
text-transform: uppercase;
position: relative;
z-index: 1;
padding: 0 8px;
cursor: default;
}
}
.landing-page {
p,
li {
@ -116,10 +243,14 @@
}
hr {
border-color: rgba($ui-base-lighter-color, .6);
width: 100%;
height: 0;
border: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
margin: 20px 0;
}
.container {
.container-alt {
width: 100%;
box-sizing: border-box;
max-width: 800px;
@ -152,24 +283,20 @@
}
}
}
}
.mascot-container {
max-width: 800px;
margin: 0 auto;
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
.brand {
a {
padding-left: 0;
padding-right: 0;
color: $white;
}
.mascot {
position: absolute;
bottom: -14px;
width: auto;
height: auto;
left: 60px;
z-index: 3;
img {
height: 32px;
position: relative;
top: 4px;
left: -10px;
}
}
@ -177,7 +304,7 @@
line-height: 30px;
overflow: hidden;
.container {
.container-alt {
display: flex;
justify-content: space-between;
}
@ -203,21 +330,6 @@
}
}
.brand {
a {
padding-left: 0;
padding-right: 0;
color: $white;
}
img {
height: 32px;
position: relative;
top: 4px;
left: -10px;
}
}
ul {
list-style: none;
margin: 0;
@ -243,53 +355,6 @@
align-items: center;
position: relative;
.floats {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
div {
position: absolute;
transition: all 0.1s linear;
animation-name: floating;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in-out;
z-index: 2;
}
.float-1 {
width: 324px;
height: 170px;
right: -120px;
bottom: 0;
animation-duration: 3s;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 447.1875 234.375" height="170" width="324"><path fill="#{hex-color($ui-base-lighter-color)}" d="M21.69 233.366c-6.45-1.268-13.347-5.63-16.704-10.564-10.705-15.734-1.513-37.724 18.632-44.57l4.8-1.632.173-17.753c.146-14.77.515-19.063 2.2-25.55 6.736-25.944 24.46-46.032 47.766-54.137 11.913-4.143 19.558-5.366 34.178-5.47l13.828-.096V71.12c0-4.755 2.853-17.457 5.238-23.327 8.588-21.137 26.735-35.957 52.153-42.593 23.248-6.07 50.153-6.415 71.863-.923 11.14 2.82 25.686 9.957 33.857 16.615 19.335 15.756 31.82 41.05 35.183 71.275.59 5.305.672 5.435 3.11 4.926 11.833-2.474 30.4-3.132 40.065-1.42 24.388 4.32 40.568 19.076 47.214 43.058 2.16 7.8 3.953 23.894 3.59 32.237l-.24 5.498 5.156 1.317c6.392 1.633 14.55 7.098 18.003 12.062 1.435 2.062 3.305 6.597 4.156 10.078 1.428 5.84 1.43 6.8.04 12.44-1.807 7.318-5.672 13.252-10.872 16.694-8.508 5.63 3.756 5.33-211.916 5.216-108.56-.056-199.22-.464-201.47-.906z"/></svg>');
}
.float-2 {
width: 241px;
height: 100px;
right: 210px;
bottom: 0;
animation-duration: 3.5s;
animation-delay: 0.2s;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 536.25 222.1875" height="100" width="241"><path fill="#{hex-color($ui-base-lighter-color)}" d="M42.626 221.23c-14.104-1.174-26.442-5.133-32.825-10.534-4.194-3.548-7.684-10.66-8.868-18.075-1.934-12.102.633-22.265 7.528-29.81 7.61-8.328 19.998-12.76 39.855-14.257l8.47-.638-2.08-6.223c-4.826-14.422-6.357-24.813-6.37-43.255-.012-14.923.28-18.513 2.1-25.724 2.283-9.048 8.483-23.034 13.345-30.1 14.76-21.45 43.505-38.425 70.535-41.65 30.628-3.655 64.47 12.073 89.668 41.673l5.955 6.995 2.765-4.174c1.52-2.296 5.74-6.93 9.376-10.295 18.382-17.02 43.436-20.676 73.352-10.705 12.158 4.052 21.315 9.53 29.64 17.733 12.752 12.562 18.16 25.718 18.19 44.26l.02 10.98 2.312-3.01c15.64-20.365 42.29-20.485 62.438-.28 3.644 3.653 7.558 8.593 8.697 10.976 4.895 10.24 5.932 25.688 2.486 37.046-.76 2.507-1.388 4.816-1.393 5.13-.006.316 6.845.87 15.224 1.234 53.06 2.297 76.356 12.98 81.817 37.526 3.554 15.973-3.71 28.604-19.566 34.02-4.554 1.555-17.922 1.655-234.517 1.757-126.327.06-233.497-.21-238.154-.597z"/></svg>');
}
.float-3 {
width: 267px;
height: 140px;
right: 110px;
top: -30px;
animation-duration: 4s;
animation-delay: 0.5s;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 388.125 202.5" height="140" width="267"><path fill="#{hex-color($ui-base-lighter-color)}" d="M181.37 201.458c-17.184-1.81-36.762-8.944-49.523-18.05l-5.774-4.12-8.074 2.63c-11.468 3.738-21.382 4.962-35.815 4.422-14.79-.554-24.577-2.845-36.716-8.594-15.483-7.332-28.498-19.98-35.985-34.968C2.44 128.675-.94 108.435.9 91.356c3.362-31.234 18.197-53.698 43.63-66.074 12.803-6.23 22.384-8.55 37.655-9.122 14.433-.54 24.347.684 35.814 4.42l8.073 2.633 5.635-4.01c24.81-17.656 60.007-23.332 92.914-14.985 10.11 2.565 25.498 9.62 33.102 15.178l5.068 3.704 7.632-2.564c10.89-3.66 21.086-4.916 35.516-4.376 45.816 1.716 76.422 30.03 81.285 75.196 1.84 17.08-1.54 37.32-8.585 51.422-7.487 14.99-20.502 27.636-35.984 34.968-12.14 5.75-21.926 8.04-36.716 8.593-14.43.54-24.626-.716-35.516-4.376l-7.632-2.564-5.068 3.704c-12.844 9.387-32.714 16.488-51.545 18.42-10.607 1.09-13.916 1.08-24.81-.066z"/></svg>');
}
}
.heading {
position: relative;
z-index: 4;
@ -346,18 +411,18 @@
background: darken($ui-base-color, 4%);
padding: 20px 0;
.container {
.container-alt {
position: relative;
padding-right: 280px + 15px;
}
.information-board-sections {
&__sections {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.section {
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
@ -382,6 +447,10 @@
font-size: 32px;
line-height: 48px;
}
@media screen and (max-width: $column-breakpoint) {
text-align: center;
}
}
.panel {
@ -460,111 +529,282 @@
}
}
.features {
padding: 50px 0;
&.alternative {
padding: 10px 0;
.container {
display: flex;
}
.brand {
text-align: center;
padding: 30px 0;
margin-bottom: 10px;
#mastodon-timeline {
display: flex;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 13px;
line-height: 18px;
font-weight: 400;
color: $primary-text-color;
width: 330px;
margin-right: 30px;
flex: 0 0 auto;
background: $ui-base-color;
overflow: hidden;
border-radius: 4px;
box-shadow: 0 0 6px rgba($black, 0.1);
img {
position: static;
}
.column-header {
color: inherit;
font-family: inherit;
font-size: 16px;
line-height: inherit;
font-weight: inherit;
margin: 0;
padding: 0;
@media screen and (max-width: $small-breakpoint) {
padding: 15px 0;
}
.column {
@media screen and (max-width: $column-breakpoint) {
padding: 0;
border-radius: 4px;
overflow: hidden;
margin-bottom: -10px;
}
}
}
.scrollable {
height: 400px;
}
&__information,
&__forms {
padding: 20px;
}
&__call-to-action {
margin-bottom: 10px;
background: darken($ui-base-color, 4%);
border-radius: 4px;
padding: 25px 40px;
overflow: hidden;
.row {
align-items: center;
}
.information-board__section {
padding: 0;
}
}
&__logo {
margin-right: 20px;
img {
height: 50px;
width: auto;
mix-blend-mode: lighten;
}
}
&__information {
padding: 45px 40px;
margin-bottom: 10px;
p {
font-size: inherit;
line-height: inherit;
font-weight: inherit;
color: $primary-text-color;
&:last-child {
margin-bottom: 0;
}
@media screen and (max-width: $column-breakpoint) {
padding: 25px 20px;
}
}
&__information,
&__forms,
#mastodon-timeline {
box-sizing: border-box;
background: $ui-base-color;
border-radius: 4px;
box-shadow: 0 0 6px rgba($black, 0.1);
}
&__mascot {
height: 104px;
position: relative;
left: -40px;
bottom: 25px;
img {
height: 190px;
width: auto;
}
}
&__short-description {
.row {
align-items: center;
margin-bottom: 40px;
}
@media screen and (max-width: $column-breakpoint) {
.row {
margin-bottom: 20px;
}
}
&:last-child {
margin-bottom: 0;
}
p a {
color: $ui-secondary-color;
}
a {
h1 {
font-weight: 500;
color: $primary-text-color;
margin-bottom: 0;
small {
color: $ui-primary-color;
span {
color: $ui-secondary-color;
text-decoration: none;
}
}
}
.about-mastodon {
max-width: 675px;
p:last-child {
margin-bottom: 0;
}
}
p {
margin-bottom: 20px;
&__hero {
margin-bottom: 10px;
img {
display: block;
margin: 0;
max-width: 100%;
height: auto;
border-radius: 4px;
}
}
&__forms {
height: 100%;
@media screen and (max-width: $small-breakpoint) {
margin-bottom: 10px;
height: auto;
}
@media screen and (max-width: $column-breakpoint) {
background: transparent;
box-shadow: none;
padding: 0 20px;
margin-top: 30px;
margin-bottom: 40px;
.separator-or {
span {
background: darken($ui-base-color, 8%);
}
}
}
.features-list {
margin-top: 20px;
hr {
margin: 40px 0;
}
.features-list__row {
display: flex;
padding: 10px 0;
justify-content: space-between;
.button {
display: block;
}
&:first-child {
padding-top: 0;
}
.subtle-hint a {
text-decoration: none;
.visual {
flex: 0 0 auto;
display: flex;
align-items: center;
margin-left: 15px;
.fa {
display: block;
color: $ui-primary-color;
font-size: 48px;
}
}
&:hover,
&:focus,
&:active {
text-decoration: underline;
}
}
}
.text {
font-size: 16px;
line-height: 30px;
color: $ui-primary-color;
#mastodon-timeline {
display: flex;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 13px;
line-height: 18px;
font-weight: 400;
color: $primary-text-color;
width: 100%;
flex: 1 1 auto;
overflow: hidden;
h6 {
font-size: inherit;
line-height: inherit;
margin-bottom: 0;
}
}
.column-header {
color: inherit;
font-family: inherit;
font-size: 16px;
line-height: inherit;
font-weight: inherit;
margin: 0;
padding: 0;
}
.column {
padding: 0;
border-radius: 4px;
overflow: hidden;
width: 100%;
}
.scrollable {
height: 400px;
}
p {
font-size: inherit;
line-height: inherit;
font-weight: inherit;
color: $primary-text-color;
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
a {
color: $ui-secondary-color;
text-decoration: none;
}
}
@media screen and (max-width: $column-breakpoint) {
height: 90vh;
}
}
&__features {
.features-list {
margin: 40px 0 !important;
}
&__action {
text-align: center;
}
}
.features-list {
margin-top: 20px;
.features-list__row {
display: flex;
padding: 10px 0;
justify-content: space-between;
&:first-child {
padding-top: 0;
}
.visual {
flex: 0 0 auto;
display: flex;
align-items: center;
margin-left: 15px;
.fa {
display: block;
color: $ui-primary-color;
font-size: 48px;
}
}
.text {
font-size: 16px;
line-height: 30px;
color: $ui-primary-color;
h6 {
font-size: inherit;
line-height: inherit;
margin-bottom: 0;
}
}
}
@ -600,21 +840,31 @@
}
}
&__footer {
margin-top: 10px;
text-align: center;
color: $ui-base-lighter-color;
p {
font-size: 14px;
a {
color: inherit;
text-decoration: underline;
}
}
}
@media screen and (max-width: 840px) {
.container {
.container-alt {
padding: 0 20px;
}
.information-board {
.container {
.container-alt {
padding-right: 20px;
}
.section {
text-align: center;
}
.panel {
position: static;
margin-top: 20px;
@ -626,16 +876,6 @@
}
}
}
.header-wrapper .mascot {
left: 20px;
}
}
@media screen and (max-width: 689px) {
.header-wrapper .mascot {
display: none;
}
}
@media screen and (max-width: 675px) {
@ -651,13 +891,12 @@
}
}
.header .container,
.features .container {
.header .container-alt,
.features .container-alt {
display: block;
}
.header {
.links {
padding-top: 15px;
background: darken($ui-base-color, 4%);
@ -682,10 +921,6 @@
margin-top: 30px;
padding: 0;
.floats {
display: none;
}
.heading {
padding: 30px 20px;
text-align: center;
@ -700,16 +935,6 @@
}
}
}
.features #mastodon-timeline {
height: 70vh;
width: 100%;
margin-bottom: 50px;
.column {
width: 100%;
}
}
}
.cta {
@ -720,7 +945,7 @@
.features {
padding: 30px 0;
.container {
.container-alt {
max-width: 820px;
#mastodon-timeline {
@ -772,7 +997,7 @@
.features {
padding: 10px 0;
.container {
.container-alt {
display: flex;
flex-direction: column;
@ -808,17 +1033,3 @@
}
}
}
@keyframes floating {
from {
transform: translate(0, 0);
}
65% {
transform: translate(0, 4px);
}
to {
transform: translate(0, -0);
}
}

+ 19
- 8
app/javascript/styles/mastodon/components.scss View File

@ -40,14 +40,20 @@
cursor: default;
}
&.button-alternative {
&.button-primary,
&.button-alternative,
&.button-secondary,
&.button-alternative-2 {
font-size: 16px;
line-height: 36px;
height: auto;
color: $ui-base-color;
background: $ui-primary-color;
text-transform: none;
padding: 4px 16px;
}
&.button-alternative {
color: $ui-base-color;
background: $ui-primary-color;
&:active,
&:focus,
@ -56,15 +62,20 @@
}
}
&.button-alternative-2 {
background: $ui-base-lighter-color;
&:active,
&:focus,
&:hover {
background-color: lighten($ui-base-lighter-color, 4%);
}
}
&.button-secondary {
font-size: 16px;
line-height: 36px;
height: auto;
color: $ui-primary-color;
text-transform: none;
background: transparent;
padding: 3px 15px;
border-radius: 4px;
border: 1px solid $ui-primary-color;
&:active,

+ 1
- 1
app/javascript/styles/mastodon/containers.scss View File

@ -1,4 +1,4 @@
.container {
.container-alt {
width: 700px;
margin: 0 auto;
margin-top: 40px;

+ 4
- 0
app/presenters/instance_presenter.rb View File

@ -39,4 +39,8 @@ class InstancePresenter
def thumbnail
@thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') }
end
def hero
@hero ||= Rails.cache.fetch('site_uploads/hero') { SiteUpload.find_by(var: 'hero') }
end
end

+ 14
- 0
app/views/about/_forms.html.haml View File

@ -0,0 +1,14 @@
- if @instance_presenter.open_registrations
= render 'registration'
- else
- if @instance_presenter.closed_registrations_message.blank?
%p= t('about.closed_registrations')
- else
= @instance_presenter.closed_registrations_message.html_safe
= link_to t('auth.register'), 'https://joinmastodon.org', class: 'button button-primary'
.separator-or
%span= t('auth.or')
= link_to t('auth.login'), new_user_session_path, class: 'button button-alternative-2 webapp-btn'

+ 1
- 1
app/views/about/_links.html.haml View File

@ -1,4 +1,4 @@
.container.links
.container-alt.links
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'

+ 1
- 1
app/views/about/_registration.html.haml View File

@ -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)

+ 8
- 8
app/views/about/more.html.haml View File

@ -10,34 +10,34 @@
.header
= render 'links'
.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
= " (#{@instance_presenter.version_number})"

+ 71
- 48
app/views/about/show.html.haml View File

@ -6,51 +6,74 @@
= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
= render partial: 'shared/og'
.landing-page
.header-wrapper
.mascot-container
= image_tag asset_pack_path('elephant-fren.png'), alt: '', role: 'presentation', class: 'mascot'
.header
= render 'links'
.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
= 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
= " (#{@instance_presenter.version_number})"
.landing-page.alternative
.container
.row
.column-4.hide-sm.show-xs.show-m
.landing-page__forms
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
.hide-xs
= render 'forms'
.column-7.column-9-sm
.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.hide-xs
= 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)
.show-xs
.landing-page__forms
= render 'forms'
.landing-page__call-to-action.hide-xs
.row
.column-5
.landing-page__mascot
= image_tag asset_pack_path('elephant_ui_plane.svg')
.column-5
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.column-5
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.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})"
.column-4.column-6-sm.column-flex
.show-sm.hide-xs
.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
#mastodon-timeline{ data: { props: Oj.dump(default_props) } }

+ 1
- 1
app/views/about/terms.html.haml View File

@ -7,5 +7,5 @@
= render 'links'
.extended-description
.container
.container-alt
= @instance_presenter.site_terms.html_safe.presence || t('terms.body_html')

+ 1
- 0
app/views/admin/settings/edit.html.haml View File

@ -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/

+ 0
- 1
config/locales/ar.yml View File

@ -14,7 +14,6 @@ ar:
humane_approach_title: أسلوب يعيد الإعتبار للإنسان
not_a_product_title: إنك إنسان و لست سلعة
real_conversation_title: مبني لتحقيق تواصل حقيقي
find_another_instance: إبحث عن مثيل خادوم آخر
generic_description: "%{domain} هو سيرفر من بين سيرفرات الشبكة"
hosted_on: ماستدون مُستضاف على %{domain}
learn_more: تعلم المزيد

+ 0
- 1
config/locales/ca.yml View File

@ -23,7 +23,6 @@ ca:
real_conversation_title: Construït per a converses reals
within_reach_body: Diverses aplicacions per a iOS, Android i altres plataformes gràcies a un ecosistema API amable amb el desenvolupador, et permet mantenir-te al dia amb els amics en qualsevol lloc..
within_reach_title: Sempre a l'abast
find_another_instance: Troba altres instàncies
generic_description: "%{domain} és un servidor a la xarxa"
hosted_on: Mastodon allotjat a %{domain}
learn_more: Més informació

+ 0
- 1
config/locales/de.yml View File

@ -23,7 +23,6 @@ de:
real_conversation_title: Für das echte Gespräch gemacht
within_reach_body: Verschiedene Apps für iOS, Android und andere Plattformen erlauben dir dank unserem blühenden API-Ökosystem, dich von überall auf dem Laufenden zu halten.
within_reach_title: Immer für dich da
find_another_instance: Eine andere Instanz finden
generic_description: "%{domain} ist ein Server im Netzwerk"
hosted_on: Mastodon, beherbergt auf %{domain}
learn_more: Mehr erfahren

+ 3
- 1
config/locales/en.yml View File

@ -23,7 +23,6 @@ en:
real_conversation_title: Built for real conversation
within_reach_body: Multiple apps for iOS, Android, and other platforms thanks to a developer-friendly API ecosystem allow you to keep up with your friends anywhere.
within_reach_title: Always within reach
find_another_instance: Find another instance
generic_description: "%{domain} is one server in the network"
hosted_on: Mastodon hosted on %{domain}
learn_more: Learn more
@ -274,6 +273,9 @@ en:
contact_information:
email: Business e-mail
username: Contact username
hero:
desc_html: Displayed on the frontpage. At least 600x100px recommended. When not set, falls back to instance thumbnail
title: Hero image
peers_api_enabled:
desc_html: Domain names this instance has encountered in the fediverse
title: Publish list of discovered instances

+ 0
- 1
config/locales/es.yml View File

@ -23,7 +23,6 @@ es:
real_conversation_title: Hecho para verdaderas conversaciones
within_reach_body: Aplicaciones múltiples para iOS, Android, y otras plataformas gracias a un ecosistema de APIs amigable al desarrollador para permitirte estar con tus amigos donde sea.
within_reach_title: Siempre al alcance
find_another_instance: Busca otra instancia
generic_description: "%{domain} es un servidor en la red"
hosted_on: Mastodon hosteado en %{domain}
learn_more: Aprende más

+ 0
- 1
config/locales/fa.yml View File

@ -23,7 +23,6 @@ fa:
real_conversation_title: برای گفتگوهای واقعی
within_reach_body: اپ‌های متنوع برای iOS، اندروید، و سیستم‌های دیگر به خاطر وجود یک اکوسیستم API دوستانه برای برنامه‌نویسان. از همه جا با دوستان خود ارتباط داشته باشید.
within_reach_title: همیشه در دسترس
find_another_instance: یافتن سرورهای دیگر
generic_description: "%{domain} یک سرور روی شبکه است"
hosted_on: ماستدون، میزبانی‌شده روی %{domain}
learn_more: بیشتر بدانید

+ 0
- 1
config/locales/fi.yml View File

@ -21,7 +21,6 @@ fi:
real_conversation_title: Rakennettu oikealle keskustelulle
within_reach_body: Kehittäjäystävällisen rajapintaekosysteemin ansiosta useita appeja Androidille, iOS:lle ja muille alustoille, jotka mahdollistavat yhteydenpidon ystäviesi kanssa missä vain.
within_reach_title: Aina lähellä
find_another_instance: Löydä toinen instanssi
learn_more: Lisätietoja
other_instances: Muut palvelimet
source_code: Lähdekoodi

+ 0
- 1
config/locales/fr.yml View File

@ -23,7 +23,6 @@ fr:
real_conversation_title: Construit pour de vraies conversations
within_reach_body: Grâce à l’existence d’un environnement API accueillant pour les développeur·se·s, de multiples applications pour iOS, Android et d’autres plateformes vous permettent de rester en contact avec vos ami·e·s où que vous soyez.
within_reach_title: Toujours à portée de main
find_another_instance: Trouver une autre instance
generic_description: "%{domain} est seulement un serveur du réseau"
hosted_on: Instance Mastodon hébergée par %{domain}
learn_more: En savoir plus

+ 0
- 1
config/locales/gl.yml View File

@ -23,7 +23,6 @@ gl:
real_conversation_title: Construído para conversacións reais
within_reach_body: Existen múltiples aplicativos para iOS, Android e outras plataformas grazas a un entorno API amigable para o desenvolvedor que lle permite estar ao tanto cos seus amigos en calquer lugar.
within_reach_title: Sempre en contacto
find_another_instance: Atope outra instancia
generic_description: "%{domain} é un servidor na rede"
hosted_on: Mastodon aloxado en %{domain}
learn_more: Coñeza máis

+ 0
- 1
config/locales/he.yml View File

@ -23,7 +23,6 @@ he:
real_conversation_title: בנוי לשיחות אמתיות
within_reach_body: שלל אפליקציות עבור iOS, אנדרואיד ופלטפורמות אחרות שיאפשרו לך לשמור על קשר עם חברים בכל מקום, תודות למערכת מנשקי תוכנה ידידותיים למפתחים.
within_reach_title: תמיד במרחק נגיעה
find_another_instance: לאיתור שרת אחר
generic_description: "%{domain} הוא שרת אחד בתוך הרשת"
hosted_on: מסטודון שיושב בכתובת %{domain}
learn_more: מידע נוסף

+ 0
- 1
config/locales/hu.yml View File

@ -23,7 +23,6 @@ hu:
real_conversation_title: Valódi beszélgetésekre tervezve
within_reach_body: A fejlesztőbarát API-nak köszönhetően számos iOS, Android és egyéb platformra írt alkalmazás teszi lehetővé, hogy bármikor, bárhonnan részt vehess a társalgásban.
within_reach_title: Mindig elérhetőnek lenni
find_another_instance: További instanciák keresése
generic_description: "%{domain} csak egy a számtalan szerver közül a föderációban"
hosted_on: "%{domain} Mastodon instancia"
learn_more: Tudj meg többet

+ 0
- 1
config/locales/ja.yml View File

@ -23,7 +23,6 @@ ja:
real_conversation_title: 本当のコミュニケーションのために
within_reach_body: デベロッパーフレンドリーな API により実現された、iOS や Android、その他様々なプラットフォームのためのアプリでどこでも友人とやりとりできます。
within_reach_title: いつでも身近に
find_another_instance: 他のインスタンスを探す
generic_description: "%{domain} は、Mastodon インスタンスの一つです"
hosted_on: Mastodon hosted on %{domain}
learn_more: もっと詳しく

+ 0
- 1
config/locales/ko.yml View File

@ -23,7 +23,6 @@ ko:
real_conversation_title: 진정한 커뮤니케이션을 위하여
within_reach_body: 개발자 친화적인 API에 의해서 실현된 iOS나 Android, 그 외의 여러 Platform들 덕분에 어디서든 친구들과 자유롭게 메세지를 주고 받을 수 있습니다.
within_reach_title: 언제나 유저의 곁에서
find_another_instance: 다른 인스턴스 찾기
generic_description: "%{domain} 은 Mastodon의 인스턴스 입니다."
hosted_on: "%{domain}에서 호스팅 되는 마스토돈"
learn_more: 자세히

+ 0
- 1
config/locales/nl.yml View File

@ -23,7 +23,6 @@ nl:
real_conversation_title: Voor echte gesprekken gemaakt
within_reach_body: Meerdere apps voor iOS, Android en andere platformen, met dank aan het ontwikkelaarsvriendelijke API-systeem, zorgen ervoor dat je overal op de hoogte blijft.
within_reach_title: Altijd binnen bereik
find_another_instance: Vind een andere server
generic_description: "%{domain} is een server in het Mastodonnetwerk"
hosted_on: Mastodon op %{domain}
learn_more: Meer leren

+ 0
- 1
config/locales/no.yml View File

@ -23,7 +23,6 @@
real_conversation_title: Laget for ekte samtaler
within_reach_body: Takket være et utviklingsvennlig API-økosystem vil flere apper for iOS, Android og andre plattformer la deg holde kontakten med dine venner hvor som helst.
within_reach_title: Alltid innen rekkevidde
find_another_instance: Finn en annen instans
generic_description: "%{domain} er en tjener i nettverket"
hosted_on: Mastodon driftet på %{domain}
learn_more: Lær mer

+ 0
- 1
config/locales/oc.yml View File

@ -23,7 +23,6 @@ oc:
real_conversation_title: Fach per de conversacions vertadièras
within_reach_body: Multiplas aplicacion per iOS, Android, e autras plataformas mercés a un entorn API de bon utilizar, vos permet de gardar lo contacte pertot.
within_reach_title: Totjorn al costat
find_another_instance: Trobar mai instàncias
generic_description: "%{domain} es un dels servidors del malhum"
hosted_on: Mastodon albergat sus %{domain}
learn_more: Ne saber mai

+ 0
- 1
config/locales/pl.yml View File

@ -23,7 +23,6 @@ pl:
real_conversation_title: Zaprojektowany do prawdziwych rozmów
within_reach_body: Wiele aplikacji dla Androida, iOS i innych platform dzięki przyjaznemu programistom API sprawia, że możesz utrzymywać kontakt ze znajomymi praktycznie wszędzie.
within_reach_title: Zawsze w Twoim zasięgu
find_another_instance: Znajdź inną instancję
generic_description: "%{domain} jest jednym z serwerów sieci"
hosted_on: Mastodon uruchomiony na %{domain}
learn_more: Dowiedz się więcej

+ 0
- 1
config/locales/pt-BR.yml View File

@ -23,7 +23,6 @@ pt-BR:
real_conversation_title: Feito para conversas reais
within_reach_body: Vários apps para iOS, Android e outras plataformas graças a um ecossistema de API amigável para desenvolvedores permitem que você possa se manter atualizado sobre seus amigos de qualquer lugar.
within_reach_title: Sempre ao seu alcance
find_another_instance: Encontre outra instância
generic_description: "%{domain} é um servidor na rede"
hosted_on: Mastodon hospedado em %{domain}
learn_more: Saiba mais

+ 0
- 1
config/locales/pt.yml View File

@ -23,7 +23,6 @@ pt:
real_conversation_title: Feito para conversas reais
within_reach_body: Várias aplicações para iOS, Android e outras plataformas graças a um ecossistema de API amigável para desenvolvedores, permitem-te que te mantenhas em contacto com os teus amigos em qualquer lugar.
within_reach_title: Sempre ao teu alcance
find_another_instance: Encontra outra instância
generic_description: "%{domain} é um servidor na rede"
hosted_on: Mastodon em %{domain}
learn_more: Saber mais

+ 0
- 1
config/locales/ru.yml View File

@ -23,7 +23,6 @@ ru:
real_conversation_title: Создан для настоящего общения
within_reach_body: Различные приложения для iOS, Android и других платформ, написанные благодаря дружественной к разработчикам экосистеме API, позволят Вам держать связь с Вашими друзьями где угодно.
within_reach_title: Всегда под рукой
find_another_instance: Найти другой узел
generic_description: "%{domain} - один из серверов сети"
hosted_on: Mastodon размещен на %{domain}
learn_more: Узнать больше

+ 0
- 1
config/locales/sk.yml View File

@ -23,7 +23,6 @@ sk:
real_conversation_title: Vytvorený pre reálnu konverzáciu
within_reach_body: Viacero aplikácií pre iOS, Android a iné platformy, ktoré vďaka jednoduchému API ekosystému vám dovoľujú byť online so svojimi priateľmi kdekoľvek.
within_reach_title: Stále v dosahu
find_another_instance: Nájdi inú inštanciu
generic_description: "%{domain} je jeden server v sieti"
hosted_on: Mastodon hostovaný na %{domain}
learn_more: Dozvedieť sa viac

+ 0
- 1
config/locales/sr-Latn.yml View File

@ -23,7 +23,6 @@ sr-Latn:
real_conversation_title: Pravljen za pravi razgovor
within_reach_body: Više aplikacija za iOS, Android, kao i druge platforme zahvaljujući ekosistemu dobrih API-ja će Vam omogućiti da ostanete u kontaktu sa prijateljima svuda.
within_reach_title: Uvek u kontaktu
find_another_instance: Nađite drugu instancu
generic_description: "%{domain} je server na mreži"
hosted_on: Mastodont hostovan na %{domain}
learn_more: Saznajte više

+ 0
- 1
config/locales/sr.yml View File

@ -23,7 +23,6 @@ sr:
real_conversation_title: Прављен за прави разговор
within_reach_body: Више апликација за iOS, Андроид, као и друге платформе захваљујући екосистему добрих API-ја ће Вам омогућити да останете у контакту са пријатељима свуда.
within_reach_title: Увек у контакту
find_another_instance: Нађите другу инстанцу
generic_description: "%{domain} је сервер на мрежи"
hosted_on: Мастодонт хостован на %{domain}
learn_more: Сазнајте више

+ 0
- 1
config/locales/sv.yml View File

@ -23,7 +23,6 @@ sv:
real_conversation_title: Byggd för riktiga konversationer
within_reach_body: Flera appar för iOS, Android och andra plattformar tack vare ett utvecklingsvänligt API-ekosystem gör att du kan hålla kontakten med dina vänner var som helst.
within_reach_title: Alltid inom räckhåll
find_another_instance: Hitta en annan instans
generic_description: "%{domain} är en server i nätverket"
hosted_on: Mastodon värd på %{domain}
learn_more: Lär dig mer

+ 0
- 1
config/locales/zh-CN.yml View File

@ -23,7 +23,6 @@ zh-CN:
real_conversation_title: 为真正的交流而生
within_reach_body: 通过一个面向开发者友好的 API 生态系统,Mastodon 让你可以随时随地通过众多 iOS、Android 以及其他平台的应用与朋友们保持联系。
within_reach_title: 始终触手可及
find_another_instance: 寻找另一个实例
generic_description: "%{domain} 是这个庞大网络中的一台服务器"
hosted_on: 一个在 %{domain} 上运行的 Mastodon 实例
learn_more: 详细了解

+ 3
- 0
spec/views/about/show.html.haml_spec.rb View File

@ -16,6 +16,9 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do
source_url: 'https://github.com/tootsuite/mastodon',
open_registrations: false,
thumbnail: nil,
hero: nil,
user_count: 0,
status_count: 0,
closed_registrations_message: 'yes')
assign(:instance_presenter, instance_presenter)
render

Loading…
Cancel
Save