New welcome email (#28883)

Co-authored-by: Eugen Rochko <eugen@zeonfederated.com>
This commit is contained in:
HTeuMeuLeu 2024-03-01 13:16:53 +01:00 committed by GitHub
parent 3389c41b58
commit 934cab7508
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
102 changed files with 619 additions and 318 deletions

View file

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 547 B

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View file

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 505 B

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 688 B

After

Width:  |  Height:  |  Size: 688 B

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

Before

Width:  |  Height:  |  Size: 709 B

After

Width:  |  Height:  |  Size: 709 B

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -192,6 +192,18 @@ table + p {
}
}
.email-dir-rtl {
direction: rtl;
[dir='rtl'] & {
direction: ltr;
}
}
.email-dir-ltr {
direction: ltr;
}
.email-padding-24 {
padding: 24px;
}
@ -216,6 +228,30 @@ table + p {
border-bottom: 1px solid #dfdee3;
}
.email-desktop-flex {
font-size: 0;
max-width: 740px;
margin-left: auto;
margin-right: auto;
&.email-dir-rtl > .email-desktop-column {
direction: ltr;
[dir='rtl'] & {
direction: rtl;
}
}
}
.email-desktop-column {
display: inline-block;
width: 100%;
max-width: none;
text-align: start;
vertical-align: top;
font-size: 16px;
}
// Header
.email-header-td {
padding: 16px 32px;
@ -312,6 +348,66 @@ table + p {
}
}
.email-header-card-table {
width: 100%;
border-collapse: separate;
overflow: hidden;
border-radius: 12px;
background-color: #fff;
border: 2px solid #fff;
box-shadow: 0 4px 16px 0 rgba(23, 6, 59, 8%);
}
.email-header-card {
position: relative;
max-height: 100px;
}
.email-header-card-banner-td {
border-radius: 12px 12px 0 0;
height: 80px;
background-color: #f3f2f5 !important;
background-position: center !important;
background-size: cover !important;
}
.email-header-card-body-td {
padding: 12px;
.email-btn-table {
width: 100%;
max-width: 212px;
}
}
.email-header-card-instance {
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
color: #17063b;
font-size: 14px;
line-height: 20px;
font-weight: 600;
&:only-of-type {
margin-bottom: 12px;
}
}
.email-header-card-description {
margin-bottom: 12px;
color: #746a89;
font-size: 12px;
line-height: 16px;
max-height: 32px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// To make the design work with images off
// we create an empty div that overlaps with
// the rest of the content with a dark background.
@ -336,6 +432,16 @@ table + p {
mso-padding-alt: 32px;
}
.email-body-columns-td {
border-top: 1px solid #dfdee3;
padding: 32px 24px 8px;
}
.email-body-huge-padding-td {
padding: 110px 32px 32px;
mso-padding-alt: 32px;
}
.email-body-padding-td {
& > p {
font-size: 14px;
@ -353,6 +459,30 @@ table + p {
}
}
// Texts
.email-h2 {
margin-bottom: 4px;
color: #17063b;
font-size: 18px;
font-weight: 600;
line-height: 28px;
}
.email-h-sub {
margin-bottom: 16px;
color: #746a89;
font-size: 14px;
line-height: 16px;
}
.email-p {
margin-bottom: 16px;
color: #746a89;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
// Footer
.email-footer-td {
padding: 28px 32px 32px;
@ -539,8 +669,13 @@ table + p {
background-color: #fff;
}
.email-checklist-checked {
border-color: #c4e6d7;
background-color: #eaf6f1;
}
.email-checklist-td {
padding: 16px;
padding: 16px 16px 6px;
}
.email-checklist-icons-td {
@ -576,10 +711,15 @@ table + p {
font-size: 14px;
font-weight: 600;
line-height: 16.8px;
.email-checklist-checked & {
color: #746a89;
text-decoration: line-through;
}
}
p {
margin: 0 0 2px;
margin: 0 0 12px;
color: #746a89;
font-size: 14px;
line-height: 16.8px;
@ -597,6 +737,194 @@ table + p {
padding-left: 10px;
padding-right: 10px;
}
div + div {
margin-inline-start: auto;
margin-bottom: 12px;
}
}
// Welcome email
.email-welcome-apps-btns {
font-size: 12px;
line-height: 44px;
}
.email-column-td {
padding: 0 8px;
vertical-align: top;
}
.email-link-with-arrow {
color: #6364ff;
font-size: 14px;
font-weight: 600;
line-height: 16.8px;
&:hover {
color: #563acc !important;
}
span {
font-size: 12px;
font-weight: 400;
}
}
.email-column-action-td {
padding: 24px 0;
color: #6364ff;
font-size: 14px;
font-weight: 600;
line-height: 16.8px;
text-align: center;
}
// Follow and hashtags
.email-mini-wrapper-td {
padding: 4px 0;
table {
table-layout: fixed;
}
}
.email-mini-td {
border-radius: 12px;
border: 1px solid #e8e6eb;
background-color: #fff;
padding: 15px 16px;
}
.email-mini-follow-img-td {
width: 40px;
vertical-align: top;
img {
border-radius: 8px;
}
}
.email-mini-follow-text-td {
padding-left: 8px;
padding-right: 16px;
vertical-align: top;
h3 {
color: #17063b;
font-size: 14px;
font-weight: 600;
line-height: 20px;
}
p {
color: #746a89;
font-size: 12px;
font-weight: 400;
line-height: 16px;
}
}
.email-mini-follow-btn-td {
width: 68px;
vertical-align: top;
.email-btn-table {
width: 100%;
}
.email-btn-td {
mso-padding-alt: 10px;
}
.email-btn-a {
padding-left: 10px;
padding-right: 10px;
}
}
.email-mini-hashtag-td {
height: 40px;
td {
vertical-align: middle;
}
h3 {
color: #17063b;
font-size: 14px;
font-weight: 600;
line-height: 20px;
}
p {
color: #746a89;
font-size: 12px;
font-weight: 400;
line-height: 16px;
word-break: break-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.email-mini-hashtag-img-td {
width: 40px;
height: 20px;
white-space: nowrap;
text-indent: -2px;
font-size: 0;
& + td {
padding-left: 8px;
}
}
.email-mini-hashtag-img-span {
display: inline-block;
max-width: 12px;
font-size: 12px;
img {
width: 16px;
height: 16px;
border-radius: 50%;
max-width: none;
border: 2px solid #fff;
vertical-align: middle;
}
}
// Extra content on light purple background
.email-extra-wave {
height: 42px;
background-image: url('../images/mailer-new/welcome/purple-extra-soft-wave.png');
background-position: bottom center;
background-repeat: no-repeat;
}
.email-extra-td {
padding: 32px 32px 24px;
background-color: #f0f0ff;
background-image: url('../images/mailer-new/welcome/purple-extra-soft-spacer.png'); // Using an image to maintain the color even in forced dark modes
.email-column-td {
padding-top: 8px;
padding-bottom: 8px;
}
}
// Feature card
.email-feature-wrapper-td {
padding: 8px 0;
}
.email-feature-td {
padding: 24px;
background-color: #fff;
border: 1px solid #e8e6eb;
border-radius: 12px;
}
// Responsive
@ -617,4 +945,21 @@ table + p {
.email-desktop-flex {
display: flex;
}
.email-header-left {
padding-right: 32px;
}
.email-header-right {
width: 240px;
margin-inline-start: auto;
}
.email-desktop-column {
max-width: 346px !important;
}
.email-desktop-text-right {
text-align: right;
}
}

View file

@ -135,6 +135,12 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
@suggestions = AccountSuggestions.new(@resource.account).get(5)
@tags = Trends.tags.query.allowed.limit(5)
@has_account_fields = @resource.account.display_name.present? || @resource.account.note.present? || @resource.account.avatar.present?
@has_active_relationships = @resource.account.active_relationships.exists?
@has_statuses = @resource.account.statuses.exists?
I18n.with_locale(locale) do
mail subject: default_i18n_subject
end

View file

@ -490,7 +490,7 @@ class User < ApplicationRecord
BootstrapTimelineWorker.perform_async(account_id)
ActivityTracker.increment('activity:accounts:local')
ActivityTracker.record('activity:logins', id)
UserMailer.welcome(self).deliver_later
UserMailer.welcome(self).deliver_later(wait: 1.hour)
TriggerWebhookWorker.perform_async('account.approved', 'Account', account_id)
end

View file

@ -1,4 +1,7 @@
%table.email-btn-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-btn-td
= link_to "#{text} ➜", url, class: 'email-btn-a email-btn-hover'
- if defined?(has_arrow) && !has_arrow
= link_to text, url, class: 'email-btn-a email-btn-hover'
- else
= link_to "#{text} ➜", url, class: 'email-btn-a email-btn-hover'

View file

@ -1,7 +1,7 @@
%table.email-w-full.email-checklist-wrapper-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-checklist-wrapper-td
%table.email-w-full.email-checklist-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%table.email-w-full.email-checklist-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation', class: ('email-checklist-checked' if defined?(checked) && checked) }
%tr
%td.email-checklist-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
@ -15,15 +15,25 @@
- else
= image_tag frontend_asset_url('images/mailer-new/welcome/checkbox-off.png'), alt: '', width: 20, height: 20
%td.email-checklist-icons-step-td
- if defined?(step_image_url)
= image_tag step_image_url, alt: '', width: 40, height: 40
- if defined?(key)
= image_tag frontend_asset_url("images/mailer-new/welcome/#{key}-#{checked ? 'on' : 'off'}.png"), alt: '', width: 40, height: 40
%td.email-checklist-text-td
.email-desktop-flex
/[if mso]
<table border="0" cellpadding="0" cellspacing="0" align="center" style="width:100%;" role="presentation"><tr><td vertical-align:top;">
%div
- if defined?(title)
%h3= title
- if defined?(text)
%p= text
/[if mso]
</td><td style="vertical-align:top;">
%div
- if defined?(button_text) && defined?(button_url) && defined?(checked) && !checked
= render 'application/mailer/button', text: button_text, url: button_url
- if defined?(show_apps_buttons) && show_apps_buttons
.email-welcome-apps-btns
= link_to image_tag(frontend_asset_url('images/mailer-new/welcome/btn-app-store.png'), alt: t('user_mailer.welcome.apps_ios_action'), width: 120, height: 40), 'https://apps.apple.com/app/mastodon-for-iphone-and-ipad/id1571998974'
= link_to image_tag(frontend_asset_url('images/mailer-new/welcome/btn-google-play.png'), alt: t('user_mailer.welcome.apps_android_action'), width: 120, height: 40), 'https://play.google.com/store/apps/details?id=org.joinmastodon.android'
- elsif defined?(button_text) && defined?(button_url) && defined?(checked) && !checked
= render 'application/mailer/button', text: button_text, url: button_url, has_arrow: false
/[if mso]
</td></tr></table>

View file

@ -0,0 +1,32 @@
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-feature-wrapper-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-feature-td
.email-desktop-flex{ class: ('email-dir-rtl' if defined?(text_first_on_desktop) && !text_first_on_desktop) }
/[if mso]
<table border="0" cellpadding="0" cellspacing="0" align="center" style="width:100%;" role="presentation"><tr><td style="width:50%; vertical-align:top;">
.email-desktop-column
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-td
- if defined?(feature_title)
%h2.email-h2= feature_title
- if defined?(feature_text)
%p.email-p= feature_text
- if defined?(feature_btn_url)
= link_to '', href: feature_btn_url, class: 'email-link-with-arrow' do
#{t('user_mailer.welcome.feature_action')} 
%span= ''
/[if mso]
</td><td style="width:50%; vertical-align:top;">
.email-desktop-column
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-td
- if defined?(key)
%p{ class: ('email-desktop-text-right' if defined?(text_first_on_desktop) && text_first_on_desktop) }
= image_tag frontend_asset_url("images/mailer-new/welcome/#{key}.png"), alt: '', width: 240, height: 230
/[if mso]
</td></tr></table>

View file

@ -0,0 +1,15 @@
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-wrapper-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-follow-img-td
= image_tag full_asset_url(follow.account.avatar.url), alt: '', width: 40, height: 40
%td.email-mini-follow-text-td
%h3= follow.account.display_name.presence || follow.account.username
%p @#{follow.account.pretty_acct}
%td.email-mini-follow-btn-td
= render 'application/mailer/button', text: t('user_mailer.welcome.follow_action'), url: web_url("@#{follow.account.acct}"), has_arrow: false

View file

@ -0,0 +1,20 @@
- accounts = hashtag.statuses.with_public_visibility.joins(:account).merge(Account.without_suspended.without_silenced).includes(:account).limit(3).map(&:account)
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-wrapper-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-hashtag-td{ height: 40 }
%h3 ##{hashtag.display_name}
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-mini-hashtag-img-td
- accounts.each do |account|
%span.email-mini-hashtag-img-span
= image_tag full_asset_url(account.avatar.url), alt: '', width: 16, height: 16
%td
%p= t('user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(hashtag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts), days: 2)

View file

@ -1,25 +1,76 @@
- instance_presenter = InstancePresenter.new
= content_for :heading do
= render 'application/mailer/heading', heading_title: t('user_mailer.welcome.title', name: @resource.account.username), heading_subtitle: t('user_mailer.welcome.explanation')
.email-desktop-flex
.email-header-left
= render 'application/mailer/heading', heading_title: t('user_mailer.welcome.title', name: @resource.account.username), heading_subtitle: t('user_mailer.welcome.explanation')
.email-header-right
.email-header-card
%table.email-header-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-header-card-banner-td{ height: 140, background: full_asset_url(instance_presenter.thumbnail&.file&.url(:'@1x') || frontend_asset_path('images/preview.png')) }
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-header-card-body-td
%p.email-header-card-instance= @instance
- if instance_presenter.description.present?
%p.email-header-card-description= instance_presenter.description
= render 'application/mailer/button', text: t('user_mailer.welcome.sign_in_action'), url: new_user_session_url, has_arrow: false
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-body-padding-td
%table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-inner-card-td-without-padding
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-prose.email-padding-24
%p
%b= t 'user_mailer.welcome.full_handle'
= render 'application/mailer/frame', text: "#{@resource.account.username}@#{@instance}"
%p= t 'user_mailer.welcome.full_handle_hint', instance: @instance
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-border-top.email-prose.email-padding-24
%p= t 'user_mailer.welcome.edit_profile_step'
= render 'application/mailer/button', text: t('user_mailer.welcome.edit_profile_action'), url: settings_profile_url
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-border-top.email-prose.email-padding-24
%p= t 'user_mailer.welcome.edit_profile_step'
= render 'application/mailer/button', text: t('user_mailer.welcome.final_action'), url: web_url
%td.email-body-huge-padding-td
%h2.email-h2= t('user_mailer.welcome.checklist_title')
%p.email-h-sub= t('user_mailer.welcome.checklist_subtitle')
= render 'application/mailer/checklist', key: 'edit_profile_step', title: t('user_mailer.welcome.edit_profile_title'), text: t('user_mailer.welcome.edit_profile_step'), checked: @has_account_fields, button_text: t('user_mailer.welcome.edit_profile_action'), button_url: web_url('start/profile')
= render 'application/mailer/checklist', key: 'follow_step', title: t('user_mailer.welcome.follow_title'), text: t('user_mailer.welcome.follow_step'), checked: @has_active_relationships, button_text: t('user_mailer.welcome.follow_action'), button_url: web_url('start/follows')
= render 'application/mailer/checklist', key: 'post_step', title: t('user_mailer.welcome.post_title'), text: t('user_mailer.welcome.post_step'), checked: @has_statuses, button_text: t('user_mailer.welcome.post_action'), button_url: web_url
= render 'application/mailer/checklist', key: 'share_step', title: t('user_mailer.welcome.share_title'), text: t('user_mailer.welcome.share_step'), checked: false, button_text: t('user_mailer.welcome.share_action'), button_url: web_url('start/share')
= render 'application/mailer/checklist', key: 'apps_step', title: t('user_mailer.welcome.apps_title'), text: t('user_mailer.welcome.apps_step'), checked: false, show_apps_buttons: true
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-body-columns-td
.email-desktop-flex
/[if mso]
<table border="0" cellpadding="0" cellspacing="0" align="center" style="width:100%;" role="presentation"><tr><td style="width:50%; vertical-align:top;">
.email-desktop-column
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-td
%h2.email-h2= t('user_mailer.welcome.follows_title')
%p.email-h-sub= t('user_mailer.welcome.follows_subtitle')
= render partial: 'application/mailer/follow', collection: @suggestions
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-action-td
= link_to '', href: web_url('explore/suggestions'), class: 'email-link-with-arrow' do
= t('user_mailer.welcome.follows_view_more')
%span= ''
/[if mso]
</td><td style="width:50%; vertical-align:top;">
.email-desktop-column
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-td
%h2.email-h2= t('user_mailer.welcome.hashtags_title')
%p.email-h-sub= t('user_mailer.welcome.hashtags_subtitle')
= render partial: 'application/mailer/hashtag', collection: @tags
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-column-action-td
= link_to '', href: web_url('explore/tags'), class: 'email-link-with-arrow' do
= t('user_mailer.welcome.hashtags_view_more')
%span= ''
/[if mso]
</td></tr></table>
.email-extra-wave
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
%tr
%td.email-extra-td
= render 'application/mailer/feature', key: 'feature_control', feature_title: t('user_mailer.welcome.feature_control_title'), feature_text: t('user_mailer.welcome.feature_control'), text_first_on_desktop: true
= render 'application/mailer/feature', key: 'feature_audience', feature_title: t('user_mailer.welcome.feature_audience_title'), feature_text: t('user_mailer.welcome.feature_audience'), text_first_on_desktop: false
= render 'application/mailer/feature', key: 'feature_moderation', feature_title: t('user_mailer.welcome.feature_moderation_title'), feature_text: t('user_mailer.welcome.feature_moderation'), text_first_on_desktop: true
= render 'application/mailer/feature', key: 'feature_creativity', feature_title: t('user_mailer.welcome.feature_creativity_title'), feature_text: t('user_mailer.welcome.feature_creativity'), text_first_on_desktop: false

View file

@ -1,16 +1,78 @@
<%= t 'user_mailer.welcome.title', name: @resource.account.username %> <%= t 'user_mailer.welcome.explanation' %>
===
<%= t 'user_mailer.welcome.full_handle' %> (<%= "@#{@resource.account.local_username_and_domain}" %>)
<%= t 'user_mailer.welcome.full_handle_hint', instance: @instance %>
---
<%= t 'user_mailer.welcome.edit_profile_step' %>
<%= t('user_mailer.welcome.sign_in_action') %>
===
<%= new_user_session_url %>
=> <%= settings_profile_url %>
---
<%= t 'user_mailer.welcome.final_step' %>
<%= t('user_mailer.welcome.checklist_title') %>
===
<%= t('user_mailer.welcome.checklist_subtitle') %>
=> <%= web_url %>
1. <%= t('user_mailer.welcome.edit_profile_title') %>
<%= t('user_mailer.welcome.edit_profile_step') %>
* <%= web_url('start/profile') %>
2. <%= t('user_mailer.welcome.follow_title') %>
<%= t('user_mailer.welcome.follow_step') %>
* <%= web_url('start/follows') %>
3. <%= t('user_mailer.welcome.post_title') %>
<%= t('user_mailer.welcome.post_step') %>
* <%= web_url %>
4. <%= t('user_mailer.welcome.share_title') %>
<%= t('user_mailer.welcome.share_step') %>
* <%= web_url('start/share') %>
5. <%= t('user_mailer.welcome.apps_title') %>
<%= t('user_mailer.welcome.apps_step') %>
* iOS: https://apps.apple.com/app/mastodon-for-iphone-and-ipad/id1571998974
* Android: https://play.google.com/store/apps/details?id=org.joinmastodon.android
---
<%= t('user_mailer.welcome.follows_title') %>
===
<%= t('user_mailer.welcome.follows_subtitle') %>
<%- @suggestions.each do |suggestion| %>
* <%= suggestion.account.display_name.presence || suggestion.account.username %> · @<%= suggestion.account.pretty_acct %>
<%= web_url("@#{suggestion.account.acct}") %>
<%- end %>
<%= web_url('explore/suggestions') %>
---
<%= t('user_mailer.welcome.hashtags_title') %>
===
<%= t('user_mailer.welcome.hashtags_subtitle') %>
<%- @tags.each do |tag| %>
* #<%= tag.display_name %> · <%= t('user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(tag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts), days: 2) %>
<%= tag_url(tag) %>
<%- end %>
<%= web_url('explore/tags') %>
---
<%= t('user_mailer.welcome.feature_control_title') %>
===
<%= word_wrap t('user_mailer.welcome.feature_control') %>
<%= t('user_mailer.welcome.feature_audience_title') %>
===
<%= word_wrap t('user_mailer.welcome.feature_audience') %>
<%= t('user_mailer.welcome.feature_moderation_title') %>
===
<%= word_wrap t('user_mailer.welcome.feature_moderation') %>
<%= t('user_mailer.welcome.feature_creativity_title') %>
===
<%= word_wrap t('user_mailer.welcome.feature_creativity') %>