From bb71538bb503159177d46d8956bd466973c0876b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 28 Jul 2018 19:25:33 +0200 Subject: [PATCH] Redesign public profiles and toots (#8068) --- .../concerns/account_controller_concern.rb | 5 + app/controllers/statuses_controller.rb | 5 + app/helpers/stream_entries_helper.rb | 46 ++ .../mastodon/components/relative_timestamp.js | 50 +- app/javascript/packs/public.js | 45 +- app/javascript/styles/application.scss | 2 +- app/javascript/styles/mastodon/accounts.scss | 575 +++--------------- app/javascript/styles/mastodon/basics.scss | 5 +- .../styles/mastodon/components.scss | 12 + .../styles/mastodon/containers.scss | 573 +++++++++++++++++ app/javascript/styles/mastodon/footer.scss | 155 ++++- .../styles/mastodon/landing_strip.scss | 111 ---- .../styles/mastodon/stream_entries.scss | 400 +++--------- app/javascript/styles/mastodon/variables.scss | 2 + app/javascript/styles/mastodon/widgets.scss | 123 ++++ app/models/concerns/account_header.rb | 5 +- app/views/accounts/_bio.html.haml | 15 + app/views/accounts/_follow_button.html.haml | 28 - app/views/accounts/_follow_grid.html.haml | 8 - .../accounts/_follow_grid_hidden.html.haml | 3 - app/views/accounts/_grid_card.html.haml | 12 - app/views/accounts/_header.html.haml | 82 ++- ...moved_strip.html.haml => _moved.html.haml} | 11 +- app/views/accounts/_nothing_here.html.haml | 1 - app/views/accounts/show.html.haml | 57 +- app/views/application/_card.html.haml | 16 + app/views/application/_sidebar.html.haml | 6 + app/views/auth/registrations/new.html.haml | 2 +- app/views/authorize_follows/_card.html.haml | 23 - app/views/authorize_follows/show.html.haml | 2 +- app/views/authorize_follows/success.html.haml | 2 +- app/views/follower_accounts/index.html.haml | 9 +- app/views/following_accounts/index.html.haml | 9 +- app/views/layouts/public.html.haml | 55 +- app/views/remote_follow/new.html.haml | 2 +- app/views/remote_unfollows/success.html.haml | 2 +- app/views/settings/migrations/show.html.haml | 2 +- app/views/settings/profiles/show.html.haml | 3 +- app/views/shared/_landing_strip.html.haml | 6 - .../stream_entries/_content_spoiler.html.haml | 7 - .../stream_entries/_detailed_status.html.haml | 34 +- app/views/stream_entries/_media.html.haml | 4 - app/views/stream_entries/_more.html.haml | 2 - .../stream_entries/_simple_status.html.haml | 34 +- app/views/stream_entries/_status.html.haml | 23 +- app/views/stream_entries/embed.html.haml | 2 +- app/views/stream_entries/show.html.haml | 11 +- config/locales/ar.yml | 5 - config/locales/ast.yml | 3 - config/locales/bg.yml | 5 - config/locales/ca.yml | 5 - config/locales/co.yml | 5 - config/locales/da.yml | 3 - config/locales/de.yml | 5 - config/locales/el.yml | 5 - config/locales/en.yml | 15 +- config/locales/eo.yml | 5 - config/locales/es.yml | 5 - config/locales/eu.yml | 5 - config/locales/fa.yml | 5 - config/locales/fi.yml | 5 - config/locales/fr.yml | 5 - config/locales/gl.yml | 5 - config/locales/he.yml | 5 - config/locales/hr.yml | 5 - config/locales/hu.yml | 5 - config/locales/id.yml | 5 - config/locales/io.yml | 5 - config/locales/it.yml | 5 - config/locales/ja.yml | 5 - config/locales/ko.yml | 5 - config/locales/nl.yml | 5 - config/locales/no.yml | 5 - config/locales/oc.yml | 5 - config/locales/pl.yml | 5 - config/locales/pt-BR.yml | 5 - config/locales/pt.yml | 5 - config/locales/ru.yml | 5 - config/locales/sk.yml | 5 - config/locales/sl.yml | 1 - config/locales/sr-Latn.yml | 5 - config/locales/sr.yml | 5 - config/locales/sv.yml | 5 - config/locales/th.yml | 5 - config/locales/tr.yml | 5 - config/locales/uk.yml | 5 - config/locales/zh-CN.yml | 5 - config/locales/zh-HK.yml | 5 - config/locales/zh-TW.yml | 5 - lib/mastodon/version.rb | 6 +- package.json | 1 + .../stream_entries/show.html.haml_spec.rb | 1 + yarn.lock | 4 + 93 files changed, 1388 insertions(+), 1423 deletions(-) delete mode 100644 app/javascript/styles/mastodon/landing_strip.scss create mode 100644 app/javascript/styles/mastodon/widgets.scss create mode 100644 app/views/accounts/_bio.html.haml delete mode 100644 app/views/accounts/_follow_button.html.haml delete mode 100644 app/views/accounts/_follow_grid.html.haml delete mode 100644 app/views/accounts/_follow_grid_hidden.html.haml delete mode 100644 app/views/accounts/_grid_card.html.haml rename app/views/accounts/{_moved_strip.html.haml => _moved.html.haml} (54%) delete mode 100644 app/views/accounts/_nothing_here.html.haml create mode 100644 app/views/application/_card.html.haml create mode 100644 app/views/application/_sidebar.html.haml delete mode 100644 app/views/authorize_follows/_card.html.haml delete mode 100644 app/views/shared/_landing_strip.html.haml delete mode 100644 app/views/stream_entries/_content_spoiler.html.haml delete mode 100644 app/views/stream_entries/_media.html.haml delete mode 100644 app/views/stream_entries/_more.html.haml diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb index 5b9981aa26..6c27ef330b 100644 --- a/app/controllers/concerns/account_controller_concern.rb +++ b/app/controllers/concerns/account_controller_concern.rb @@ -8,6 +8,7 @@ module AccountControllerConcern included do layout 'public' before_action :set_account + before_action :set_instance_presenter before_action :set_link_headers before_action :check_account_suspension end @@ -18,6 +19,10 @@ module AccountControllerConcern @account = Account.find_local!(params[:account_username]) end + def set_instance_presenter + @instance_presenter = InstancePresenter.new + end + def set_link_headers response.headers['Link'] = LinkHeader.new( [ diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index b853418229..755af1debd 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -12,6 +12,7 @@ class StatusesController < ApplicationController before_action :set_account before_action :set_status + before_action :set_instance_presenter before_action :set_link_headers before_action :check_account_suspension before_action :redirect_to_original, only: [:show] @@ -148,6 +149,10 @@ class StatusesController < ApplicationController raise ActiveRecord::RecordNotFound end + def set_instance_presenter + @instance_presenter = InstancePresenter.new + end + def check_account_suspension gone if @account.suspended? end diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index 05cea73d7b..121644263d 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -12,6 +12,52 @@ module StreamEntriesHelper end end + def account_action_button(account) + if user_signed_in? + if account.id == current_user.account_id + link_to settings_profile_url, class: 'button logo-button' do + safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')]) + end + elsif current_account.following?(account) || current_account.requested?(account) + link_to account_unfollow_path(account), class: 'button logo-button', data: { method: :post } do + safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')]) + end + else + link_to account_follow_path(account), class: 'button logo-button', data: { method: :post } do + safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')]) + end + end + else + link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do + safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')]) + end + end + end + + def account_badge(account) + if account.bot? + content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles') + elsif Setting.show_staff_badge && account.user_staff? + content_tag(:div, class: 'roles') do + if account.user_admin? + content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin') + elsif account.user_moderator? + content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator') + end + end + end + end + + def link_to_more(url) + link_to t('statuses.show_more'), url, class: 'load-more load-gap' + end + + def nothing_here(extra_classes = '') + content_tag(:div, class: "nothing-here #{extra_classes}") do + t('accounts.nothing_here') + end + end + def account_description(account) prepend_str = [ [ diff --git a/app/javascript/mastodon/components/relative_timestamp.js b/app/javascript/mastodon/components/relative_timestamp.js index 3c8db70926..9609714a1c 100644 --- a/app/javascript/mastodon/components/relative_timestamp.js +++ b/app/javascript/mastodon/components/relative_timestamp.js @@ -60,6 +60,32 @@ const getUnitDelay = units => { } }; +export const timeAgoString = (intl, date, now, year) => { + const delta = now - date.getTime(); + + let relativeTime; + + if (delta < 10 * SECOND) { + relativeTime = intl.formatMessage(messages.just_now); + } else if (delta < 7 * DAY) { + if (delta < MINUTE) { + relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) }); + } else if (delta < HOUR) { + relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) }); + } else if (delta < DAY) { + relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) }); + } else { + relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) }); + } + } else if (date.getFullYear() === year) { + relativeTime = intl.formatDate(date, shortDateFormatOptions); + } else { + relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' }); + } + + return relativeTime; +}; + @injectIntl export default class RelativeTimestamp extends React.Component { @@ -121,28 +147,8 @@ export default class RelativeTimestamp extends React.Component { render () { const { timestamp, intl, year } = this.props; - const date = new Date(timestamp); - const delta = this.state.now - date.getTime(); - - let relativeTime; - - if (delta < 10 * SECOND) { - relativeTime = intl.formatMessage(messages.just_now); - } else if (delta < 7 * DAY) { - if (delta < MINUTE) { - relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) }); - } else if (delta < HOUR) { - relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) }); - } else if (delta < DAY) { - relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) }); - } else { - relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) }); - } - } else if (date.getFullYear() === year) { - relativeTime = intl.formatDate(date, shortDateFormatOptions); - } else { - relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' }); - } + const date = new Date(timestamp); + const relativeTime = timeAgoString(intl, date, this.state.now, year); return (