From cea1190ab958cf2e708a1fdcd9f167d1d00ce2a2 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Wed, 4 Jan 2023 16:12:43 +0100 Subject: [PATCH] Remove and replace usage of media classes --- app/views/answerbox/_comments.html.haml | 10 ++++---- app/views/answerbox/_header.html.haml | 23 +++++++++-------- app/views/answerbox/_smiles.html.haml | 6 ++--- app/views/application/_answerbox.html.haml | 8 +++--- app/views/discover/_userbox.html.haml | 8 +++--- app/views/inbox/_entry.html.haml | 13 +++++----- app/views/modal/list/_item.html.haml | 6 ++--- app/views/modal/privileges/_item.html.haml | 6 ++--- app/views/moderation/inbox/_header.html.haml | 9 ++++--- .../moderation/questions/_header.html.haml | 4 +-- app/views/notifications/index.html.haml | 2 +- .../notifications/index.turbo_stream.haml | 2 +- .../notifications/type/_answer.html.haml | 18 ++++++------- .../notifications/type/_comment.html.haml | 18 ++++++------- .../notifications/type/_dataexport.html.haml | 8 +++--- ..._expiredtwitterserviceconnection.html.haml | 8 +++--- .../notifications/type/_follow.html.haml | 8 +++--- .../notifications/type/_reaction.html.haml | 12 ++++----- .../type/_webpushsubscription.html.haml | 8 +++--- app/views/question/_question.html.haml | 25 ++++++++++--------- app/views/settings/data/index.html.haml | 6 ++--- app/views/settings/profile/edit.html.haml | 6 ++--- app/views/shared/_question.html.haml | 20 +++++++-------- 23 files changed, 114 insertions(+), 120 deletions(-) diff --git a/app/views/answerbox/_comments.html.haml b/app/views/answerbox/_comments.html.haml index 5bf67655..9b906dfd 100644 --- a/app/views/answerbox/_comments.html.haml +++ b/app/views/answerbox/_comments.html.haml @@ -5,18 +5,18 @@ - a.comments.order(:created_at).each do |comment| %li.comment{ data: { comment_id: comment.id } } %div{ style: "height: 0; width: 0" }= render "modal/comment_smiles", comment: comment - .media - .pull-left + .d-flex + .flex-shrink-0 %a{ href: user_path(comment.user) } %img.comment__user-avatar.avatar-sm{ src: comment.user.profile_picture.url(:small), loading: :lazy } - .media-body - %h6.media-heading.comment__user + .flex-grow-1 + %h6.comment__user = user_screen_name comment.user %span.text-muted{ title: comment.created_at, data: { bs_toggle: :tooltip, bs_placement: :right } } = t("time.distance_ago", time: time_ago_in_words(comment.created_at)) .comment__content = markdown comment.content - .pull-right + .flex-shrink-0.ms-auto %button.btn.btn-link.answerbox__action{ type: :button, name: "ab-smile-comment", data: { c_id: comment.id, action: current_user&.smiled?(comment) ? :unsmile : :smile }, disabled: !user_signed_in? } %i.fa.fa-fw.fa-smile-o %span{ id: "ab-comment-smile-count-#{comment.id}" }= comment.smile_count diff --git a/app/views/answerbox/_header.html.haml b/app/views/answerbox/_header.html.haml index 7a5deda5..65db63a1 100644 --- a/app/views/answerbox/_header.html.haml +++ b/app/views/answerbox/_header.html.haml @@ -1,16 +1,11 @@ .card-header - .media + .d-flex - unless a.question.author_is_anonymous - %a.pull-left{ href: user_path(a.question.user) } - %img.answerbox__question-user-avatar.avatar-md{ src: a.question.user.profile_picture.url(:small), loading: :lazy } - .media-body - - if user_signed_in? - .pull-right - .btn-group - %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } - %span.caret - = render "actions/question", question: a.question - %h6.text-muted.media-heading.answerbox__question-user + .flex-shrink-0 + %a{ href: user_path(a.question.user) } + %img.answerbox__question-user-avatar.avatar-md{ src: a.question.user.profile_picture.url(:small), loading: :lazy } + .flex-grow-1 + %h6.text-muted.answerbox__question-user - if a.question.author_is_anonymous %i.fas.fa-user-secret{ title: t(".anon_hint") } = t(".asked_html", user: user_screen_name(a.question.user, context_user: a.user, author_identifier: a.question.author_is_anonymous ? a.question.author_identifier: nil), time: time_tooltip(a.question)) @@ -20,3 +15,9 @@ = t(".answers", count: a.question.answer_count) .answerbox__question-text = question_markdown a.question.content + - if user_signed_in? + .flex-shrink-0.ms-auto + .btn-group + %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } + %span.caret + = render "actions/question", question: a.question diff --git a/app/views/answerbox/_smiles.html.haml b/app/views/answerbox/_smiles.html.haml index b4e3a668..518c72ee 100644 --- a/app/views/answerbox/_smiles.html.haml +++ b/app/views/answerbox/_smiles.html.haml @@ -1,7 +1,7 @@ -.media.smiles - .pull-left +.d-flex.smiles + .flex-shrink-0.me-1 %i.fa.fa-smile-o - .media-body + .flex-grow-1 - if a.smiles.all.count.zero? = t(".none") - else diff --git a/app/views/application/_answerbox.html.haml b/app/views/application/_answerbox.html.haml index 57e2afa7..6808daf4 100644 --- a/app/views/application/_answerbox.html.haml +++ b/app/views/application/_answerbox.html.haml @@ -16,12 +16,12 @@ - if @user.nil? .row .col-sm-6.text-start.text-muted - .media - .pull-left + .d-flex + .flex-shrink-0 %a{ href: user_path(a.user) } %img.answerbox__answer-user-avatar.avatar-sm{ src: a.user.profile_picture.url(:small), loading: :lazy } - .media-body - %h6.media-heading.answerbox__answer-user + .flex-grow-1 + %h6.answerbox__answer-user = raw t(".answered", hide: hidespan(t(".hide"), "d-none d-sm-inline"), user: user_screen_name(a.user)) .answerbox__answer-date = link_to(raw(t("time.distance_ago", time: time_tooltip(a))), answer_path(a.user.screen_name, a.id)) diff --git a/app/views/discover/_userbox.html.haml b/app/views/discover/_userbox.html.haml index 77718798..8c322b50 100644 --- a/app/views/discover/_userbox.html.haml +++ b/app/views/discover/_userbox.html.haml @@ -1,11 +1,11 @@ .card{ data: { id: u.id } } .card-body - .media - .pull-left + .d-flex + .flex-shrink-0 %a{ href: user_path(u) } %img.avatar-md.me-2{ src: u.profile_picture.url(:medium) } - .media-body - %h6.media-heading.answerbox__question-user + .flex-grow-1 + %h6.answerbox__question-user - if u.profile.display_name.blank? %a{ href: user_path(u) } = u.screen_name diff --git a/app/views/inbox/_entry.html.haml b/app/views/inbox/_entry.html.haml index 9e108caf..09513f1e 100644 --- a/app/views/inbox/_entry.html.haml +++ b/app/views/inbox/_entry.html.haml @@ -1,11 +1,12 @@ .card.inbox-entry{ id: "inbox_#{i.id}", class: i.new? ? "inbox-entry--new" : "", data: { id: i.id } } .card-header - .media + .d-flex - unless i.question.author_is_anonymous - %a.pull-left{ href: user_path(i.question.user) } - %img.answerbox__question-user-avatar.avatar-md{ src: i.question.user.profile_picture.url(:small), loading: :lazy } - .media-body - %h6.text-muted.media-heading.answerbox__question-user + .flex-shrink-0 + %a.pull-left{ href: user_path(i.question.user) } + %img.answerbox__question-user-avatar.avatar-md{ src: i.question.user.profile_picture.url(:small), loading: :lazy } + .flex-grow-1 + %h6.text-muted.answerbox__question-user - if i.question.author_is_anonymous %i.fas.fa-user-secret{ title: t('.anon_hint') } = t(".asked_html", user: user_screen_name(i.question.user, context_user: i.user, author_identifier: i.question.author_is_anonymous ? i.question.author_identifier : nil), time: time_tooltip(i.question)) @@ -15,7 +16,7 @@ = t(".answers", count: i.question.answer_count) .answerbox__question-text= question_markdown i.question.content - if i.question.user_id != current_user.id || current_user.has_cached_role?(:administrator) - .pull-right + .flex-shrink-0.ms-auto .btn-group %button.btn.btn-default.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } %span.caret diff --git a/app/views/modal/list/_item.html.haml b/app/views/modal/list/_item.html.haml index 4d62fb5e..5b3539ab 100644 --- a/app/views/modal/list/_item.html.haml +++ b/app/views/modal/list/_item.html.haml @@ -1,13 +1,13 @@ %li.list-group-item{ id: "list-#{list.name}" } - .media - .pull-left + .d-flex + .flex-shrink-0 .custom-control.custom-checkbox %input.custom-control-input{ type: :checkbox, id: "listCheck#{list.id}", name: 'gm-list-check', data: { list: list.name, user: user.screen_name }, checked: user.member_of?(list), autocomplete: :off } %label.custom-control-label{ for: "listCheck#{list.id}" } - .media-body + .flex-grow-1 .list-group-item-heading= list.display_name .list-group-item-text.text-muted %span{ id: "#{list.name}-members", data: { count: list.members.count } }= t(".members", count: list.members.count) diff --git a/app/views/modal/privileges/_item.html.haml b/app/views/modal/privileges/_item.html.haml index 461fb08b..f87b4d3b 100644 --- a/app/views/modal/privileges/_item.html.haml +++ b/app/views/modal/privileges/_item.html.haml @@ -4,10 +4,10 @@ requires_role = %w[admin moderator].include?(privilege) checked = requires_role ? user.has_cached_role?(role_mapping.fetch(privilege, privilege).to_sym) : user.public_send("#{privilege}?") %li.list-group-item{ id: "privilege-#{privilege}" } - .media - .pull-left + .d-flex + .flex-shrink-0 %input{ type: :checkbox, name: "check-your-privileges", data: { type: privilege, user: user.screen_name }, checked: checked, autocomplete: :off } - .media-body + .flex-grow-1 .list-group-item-heading= privilege.capitalize - unless description.blank? .list-group-item-text.text-muted= description diff --git a/app/views/moderation/inbox/_header.html.haml b/app/views/moderation/inbox/_header.html.haml index 94f53fce..eae01b4b 100644 --- a/app/views/moderation/inbox/_header.html.haml +++ b/app/views/moderation/inbox/_header.html.haml @@ -1,8 +1,9 @@ .card.question--fixed{ class: hidden ? 'question--hidden' : '', tabindex: hidden ? -1 : '', aria: { hidden: hidden } } .container .card-body - .media - %a.pull-left{ href: user_path(user) } - %img.answerbox__question-user-avatar.avatar-md{ src: user.profile_picture.url(:medium) } - .media-body + .d-flex + .flex-shrink-0 + %a{ href: user_path(user) } + %img.answerbox__question-user-avatar.avatar-md{ src: user.profile_picture.url(:medium) } + .flex-grow-1 = t(".title_html", screen_name: user.screen_name, user_id: user.id) diff --git a/app/views/moderation/questions/_header.html.haml b/app/views/moderation/questions/_header.html.haml index ec427aa4..c8984458 100644 --- a/app/views/moderation/questions/_header.html.haml +++ b/app/views/moderation/questions/_header.html.haml @@ -1,6 +1,6 @@ .card.question--fixed{ class: hidden ? 'question--hidden' : '', tabindex: hidden ? -1 : '', aria: { hidden: hidden } } .container .card-body - .media - .media-body + .d-flex + .flex-grow-1 = t(".title_html", author_identifier: author_identifier, short: author_identifier.truncate(32)) diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 3ba9d82a..1963dce3 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -13,7 +13,7 @@ - @notifications.each do |notification| %li.card .card-body - .media + .d-flex = render "notifications/type/#{notification.target.class.name.downcase.split('::').last}", notification: notification - if @more_data_available diff --git a/app/views/notifications/index.turbo_stream.haml b/app/views/notifications/index.turbo_stream.haml index 8c7fb94d..7fc5355f 100644 --- a/app/views/notifications/index.turbo_stream.haml +++ b/app/views/notifications/index.turbo_stream.haml @@ -2,7 +2,7 @@ - @notifications.each do |notification| %li.card .card-body - .media + .d-flex = render "notifications/type/#{notification.target.class.name.downcase.split('::').last}", notification: notification = turbo_stream.update "paginator" do diff --git a/app/views/notifications/type/_answer.html.haml b/app/views/notifications/type/_answer.html.haml index c17f0480..bef0030a 100644 --- a/app/views/notifications/type/_answer.html.haml +++ b/app/views/notifications/type/_answer.html.haml @@ -1,7 +1,7 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %i.fa.fa-2x.fa-fw.fa-exclamation - .media-body + .flex-grow-1 .notification__heading %img.avatar-xs{ src: notification.target.user.profile_picture.url(:small), loading: :lazy } = t(".heading_html", @@ -10,12 +10,8 @@ time: time_tooltip(notification.target)) .list-group .list-group-item - .media.question-media - .media-body - %h6.notification__list-heading= t("activerecord.models.question.one") - = markdown notification.target.question.content[0..60] + (notification.target.question.content.length > 60 ? '[...]' : '') + %h6.notification__list-heading= t("activerecord.models.question.one") + = markdown notification.target.question.content[0..60] + (notification.target.question.content.length > 60 ? '[...]' : '') .list-group-item - .media.question-media - .media-body - %h6.notification__list-heading= t("activerecord.models.answer.one") - = markdown notification.target.content[0..60] + (notification.target.content.length > 60 ? '[...]' : '') + %h6.notification__list-heading= t("activerecord.models.answer.one") + = markdown notification.target.content[0..60] + (notification.target.content.length > 60 ? '[...]' : '') diff --git a/app/views/notifications/type/_comment.html.haml b/app/views/notifications/type/_comment.html.haml index f7fb4a25..26cb55cd 100644 --- a/app/views/notifications/type/_comment.html.haml +++ b/app/views/notifications/type/_comment.html.haml @@ -1,7 +1,7 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %i.fa.fa-2x.fa-fw.fa-comments - .media-body + .flex-grow-1 .notification__heading %img.avatar-xs{ src: notification.target.user.profile_picture.url(:small), loading: :lazy } - if notification.target.answer.user == current_user @@ -21,12 +21,8 @@ time: time_tooltip(notification.target)) .list-group .list-group-item - .media.question-media - .media-body - %h6.notification__list-heading= t("activerecord.models.answer.one") - = markdown notification.target.answer.content[0..60] + (notification.target.answer.content.length > 60 ? '[...]' : '') + %h6.notification__list-heading= t("activerecord.models.answer.one") + = markdown notification.target.answer.content[0..60] + (notification.target.answer.content.length > 60 ? '[...]' : '') .list-group-item - .media.question-media - .media-body - %h6.notification__list-heading= t("activerecord.models.comment.one") - = markdown notification.target.content[0..60] + (notification.target.content.length > 60 ? '[...]' : '') + %h6.notification__list-heading= t("activerecord.models.comment.one") + = markdown notification.target.content[0..60] + (notification.target.content.length > 60 ? '[...]' : '') diff --git a/app/views/notifications/type/_dataexport.html.haml b/app/views/notifications/type/_dataexport.html.haml index b39210fe..3da53c4c 100644 --- a/app/views/notifications/type/_dataexport.html.haml +++ b/app/views/notifications/type/_dataexport.html.haml @@ -1,8 +1,8 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %i.fa.fa-2x.fa-fw.fa-download - .media-body - %h6.media-heading.notification__user + .flex-grow-1 + %h6.notification__user = t(".heading") .notification__text = t(".text_html", settings_export: link_to(t(".settings_export"), settings_export_path)) diff --git a/app/views/notifications/type/_expiredtwitterserviceconnection.html.haml b/app/views/notifications/type/_expiredtwitterserviceconnection.html.haml index 36014390..fd941e2f 100644 --- a/app/views/notifications/type/_expiredtwitterserviceconnection.html.haml +++ b/app/views/notifications/type/_expiredtwitterserviceconnection.html.haml @@ -1,8 +1,8 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %i.fa.fa-2x.fa-fw.fa-twitter - .media-body - %h6.media-heading.notification__user + .flex-grow-1 + %h6.notification__user = t(".heading") .notification__text = t(".text_html", settings_sharing: link_to(t(".settings_services"), services_path)) diff --git a/app/views/notifications/type/_follow.html.haml b/app/views/notifications/type/_follow.html.haml index 85355be7..ec44fc56 100644 --- a/app/views/notifications/type/_follow.html.haml +++ b/app/views/notifications/type/_follow.html.haml @@ -1,8 +1,8 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %img.avatar-sm{ src: notification.target.source.profile_picture.url(:small), loading: :lazy } - .media-body - %h6.media-heading.notification__user + .flex-grow-1 + %h6.notification__user = user_screen_name notification.target.source .notification__text = t(".heading_html", time: time_ago_in_words(notification.target.created_at)) diff --git a/app/views/notifications/type/_reaction.html.haml b/app/views/notifications/type/_reaction.html.haml index a97b5c27..8462dd88 100644 --- a/app/views/notifications/type/_reaction.html.haml +++ b/app/views/notifications/type/_reaction.html.haml @@ -1,7 +1,7 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %i.fa.fa-2x.fa-fw.fa-smile-o - .media-body + .flex-grow-1 .notification__heading %img.avatar-xs{ src: notification.target.user.profile_picture.url(:small), loading: :lazy } - if notification.target.parent_type == 'Answer' @@ -16,7 +16,5 @@ time: time_tooltip(notification.target)) .list-group .list-group-item - .media.question-media - .media-body - %h6.notification__list-heading= t("activerecord.models.#{notification.target.parent_type.downcase}.one") - = markdown notification.target.parent.content[0..60] + (notification.target.parent.content.length > 60 ? '[...]' : '') + %h6.notification__list-heading= t("activerecord.models.#{notification.target.parent_type.downcase}.one") + = markdown notification.target.parent.content[0..60] + (notification.target.parent.content.length > 60 ? '[...]' : '') diff --git a/app/views/notifications/type/_webpushsubscription.html.haml b/app/views/notifications/type/_webpushsubscription.html.haml index 607c5d35..b077f489 100644 --- a/app/views/notifications/type/_webpushsubscription.html.haml +++ b/app/views/notifications/type/_webpushsubscription.html.haml @@ -1,10 +1,10 @@ -.media.notification - .notification__icon +.d-flex.notification + .flex-shrink-0.notification__icon %span.fa-stack %i.fa.fa-2x.fa-fw.fa-bell %i.fa.fa-stack-1x.fa-fw.fa-exclamation-triangle.text-danger.ps-2 - .media-body - %h6.media-heading.notification__user + .flex-grow-1 + %h6.notification__user = t(".heading") .notification__text = t(".text_html", settings_push: link_to(t(".settings_push"), settings_push_notifications_path)) diff --git a/app/views/question/_question.html.haml b/app/views/question/_question.html.haml index 4843510c..8015015a 100644 --- a/app/views/question/_question.html.haml +++ b/app/views/question/_question.html.haml @@ -1,22 +1,23 @@ .card.question--fixed{ class: hidden ? 'question--hidden' : '', tabindex: hidden ? -1 : '', aria: { hidden: hidden } } .container .card-body - .media + .d-flex - unless question.author_is_anonymous - %a.pull-left{ href: unless hidden then user_path(question.user) end } - %img.answerbox__question-user-avatar.avatar-md{ src: question.user.profile_picture.url(:small) } - .media-body - - if user_signed_in? - .pull-right - .btn-group - %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } - %span.caret - - unless hidden - = render "actions/question", question: question - %h6.text-muted.media-heading.answerbox__question-user + .flex-shrink-0 + %a{ href: unless hidden then user_path(question.user) end } + %img.answerbox__question-user-avatar.avatar-md{ src: question.user.profile_picture.url(:small) } + .flex-grow-1 + %h6.text-muted.answerbox__question-user - identifier = question.author_is_anonymous ? question.author_identifier : nil - if hidden = user_screen_name question.user, author_identifier: identifier, url: false - else = t("answerbox.header.asked_html", user: user_screen_name(question.user, author_identifier: identifier), time: time_tooltip(question)) .answerbox__question-text= question_markdown question.content + - if user_signed_in? + .flex-shrink-0.ms-auto + .btn-group + %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } + %span.caret + - unless hidden + = render "actions/question", question: question diff --git a/app/views/settings/data/index.html.haml b/app/views/settings/data/index.html.haml index bff8b524..24f9a115 100644 --- a/app/views/settings/data/index.html.haml +++ b/app/views/settings/data/index.html.haml @@ -30,10 +30,10 @@ .col-md-6.col-sm-6.col-xs-12.mb-3 %h4= t(".section.pictures") %p.fw-bold.mb-0= t(".pictures.profile_picture.heading") - .media.mb-3 - .pull-left + .d-flex.mb-3 + .flex-shrink-0 %img.profile--img{ src: current_user.profile_picture.url(:medium) } - .media-body + .flex-grow-1 %ul %li %a{ href: current_user.profile_picture.url(:small) }= t(".pictures.profile_picture.size.small") diff --git a/app/views/settings/profile/edit.html.haml b/app/views/settings/profile/edit.html.haml index 1b273f91..9b86a12a 100644 --- a/app/views/settings/profile/edit.html.haml +++ b/app/views/settings/profile/edit.html.haml @@ -2,10 +2,10 @@ .card-body = bootstrap_form_for(current_user, url: settings_profile_picture_path, html: { multipart: true }, method: :patch, data: { turbo: false }) do |f| - .media#profile-picture-media - .pull-left + .d-flex#profile-picture-media + .flex-shrink-0 %img.avatar-lg.me-3{ src: current_user.profile_picture.url(:medium) } - .media-body + .flex-grow-1 = f.file_field :profile_picture, accept: APP_CONFIG[:accepted_image_formats].join(",") .row.d-none#profile-picture-crop-controls diff --git a/app/views/shared/_question.html.haml b/app/views/shared/_question.html.haml index cc703f37..9f6e31b2 100644 --- a/app/views/shared/_question.html.haml +++ b/app/views/shared/_question.html.haml @@ -1,19 +1,13 @@ - type ||= nil .card.questionbox{ data: { id: q.id } } .card-body - .media + .d-flex - if type == 'discover' - .pull-left + .flex-shrink-0 %a{ href: user_screen_name(q.user, link_only: true) } %img.avatar-md.me-2{ src: q.user&.profile_picture&.url(:small), loading: :lazy } - .media-body - - if user_signed_in? - .pull-right - .btn-group - %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } - %span.caret - = render "actions/question", question: q - %h6.media-heading.text-muted.answerbox__question-user + .flex-grow-1 + %h6.text-muted.answerbox__question-user = t("answerbox.header.asked_html", user: user_screen_name(q.user), time: time_tooltip(q)) - if q.answer_count > 1 ยท @@ -21,3 +15,9 @@ = pluralize(q.answer_count, t("voc.answer")) .answerbox__question-text = question_markdown q.content + - if user_signed_in? + .flex-shrink-0.ms-auto + .btn-group + %button.btn.btn-link.btn-sm.dropdown-toggle{ data: { bs_toggle: :dropdown }, aria: { expanded: false } } + %span.caret + = render "actions/question", question: q