From fa2e7b1708385c4277a67f04e540cc39fc661390 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Tue, 20 Aug 2024 07:52:45 -0400
Subject: [PATCH] Migrate fontawesome->material in more views (#31360)

---
 app/helpers/application_helper.rb                  |  3 ++-
 app/helpers/settings_helper.rb                     |  4 ++--
 app/javascript/material-icons/400-24px/chat.svg    |  5 +++++
 .../material-icons/400-24px/desktop_mac.svg        |  5 +++++
 .../material-icons/400-24px/format_paragraph.svg   |  5 +++++
 .../material-icons/400-24px/smartphone.svg         |  5 +++++
 app/javascript/material-icons/400-24px/tablet.svg  |  5 +++++
 app/javascript/styles/mastodon/accounts.scss       |  2 +-
 app/views/application/_card.html.haml              |  2 +-
 .../auth/registrations/_account_warning.html.haml  |  2 +-
 app/views/auth/registrations/_session.html.haml    |  2 +-
 app/views/disputes/strikes/show.html.haml          |  4 ++--
 app/views/filters/_filter.html.haml                |  4 ++--
 app/views/filters/_filter_fields.html.haml         |  2 +-
 app/views/filters/_keyword_fields.html.haml        |  2 +-
 app/views/invites/_invite.html.haml                |  2 +-
 app/views/kaminari/_next_page.html.haml            |  2 +-
 app/views/kaminari/_prev_page.html.haml            |  2 +-
 app/views/oauth/authorizations/new.html.haml       |  2 +-
 .../oauth/authorized_applications/index.html.haml  |  2 +-
 app/views/relationships/show.html.haml             |  8 ++++----
 app/views/statuses/_detailed_status.html.haml      | 10 +++++-----
 app/views/statuses/_simple_status.html.haml        | 14 +++++++-------
 spec/helpers/application_helper_spec.rb            |  9 +++++++++
 spec/helpers/settings_helper_spec.rb               |  4 ++--
 25 files changed, 71 insertions(+), 36 deletions(-)
 create mode 100644 app/javascript/material-icons/400-24px/chat.svg
 create mode 100644 app/javascript/material-icons/400-24px/desktop_mac.svg
 create mode 100644 app/javascript/material-icons/400-24px/format_paragraph.svg
 create mode 100644 app/javascript/material-icons/400-24px/smartphone.svg
 create mode 100644 app/javascript/material-icons/400-24px/tablet.svg

diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a6ab4044b..20da199d4 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -117,7 +117,8 @@ module ApplicationHelper
     inline_svg_tag(
       "400-24px/#{icon}.svg",
       class: ['icon', "material-#{icon}"].concat(attributes[:class].to_s.split),
-      role: :img
+      role: :img,
+      data: attributes[:data]
     )
   end
 
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 10863a316..64f2ad70a 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -26,11 +26,11 @@ module SettingsHelper
     device = session.detection.device
 
     if device.mobile?
-      'mobile'
+      'smartphone'
     elsif device.tablet?
       'tablet'
     else
-      'desktop'
+      'desktop_mac'
     end
   end
 
diff --git a/app/javascript/material-icons/400-24px/chat.svg b/app/javascript/material-icons/400-24px/chat.svg
new file mode 100644
index 000000000..7369e6f84
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/chat.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
+    fill="#5f6368">
+    <path
+        d="M240-400h320v-80H240v80Zm0-120h480v-80H240v80Zm0-120h480v-80H240v80ZM80-80v-720q0-33 23.5-56.5T160-880h640q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H240L80-80Zm126-240h594v-480H160v525l46-45Zm-46 0v-480 480Z" />
+</svg>
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/desktop_mac.svg b/app/javascript/material-icons/400-24px/desktop_mac.svg
new file mode 100644
index 000000000..5d2a07a36
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/desktop_mac.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
+    fill="#5f6368">
+    <path
+        d="M320-120v-40l80-80H160q-33 0-56.5-23.5T80-320v-440q0-33 23.5-56.5T160-840h640q33 0 56.5 23.5T880-760v440q0 33-23.5 56.5T800-240H560l80 80v40H320ZM160-440h640v-320H160v320Zm0 0v-320 320Z" />
+</svg>
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/format_paragraph.svg b/app/javascript/material-icons/400-24px/format_paragraph.svg
new file mode 100644
index 000000000..657b483c0
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/format_paragraph.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
+    fill="#5f6368">
+    <path
+        d="M360-160v-240q-83 0-141.5-58.5T160-600q0-83 58.5-141.5T360-800h360v80h-80v560h-80v-560H440v560h-80Z" />
+</svg>
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/smartphone.svg b/app/javascript/material-icons/400-24px/smartphone.svg
new file mode 100644
index 000000000..fa5682548
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/smartphone.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
+    fill="#5f6368">
+    <path
+        d="M280-40q-33 0-56.5-23.5T200-120v-720q0-33 23.5-56.5T280-920h400q33 0 56.5 23.5T760-840v720q0 33-23.5 56.5T680-40H280Zm0-120v40h400v-40H280Zm0-80h400v-480H280v480Zm0-560h400v-40H280v40Zm0 0v-40 40Zm0 640v40-40Z" />
+</svg>
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/tablet.svg b/app/javascript/material-icons/400-24px/tablet.svg
new file mode 100644
index 000000000..09a5fe6bb
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/tablet.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
+    fill="#5f6368">
+    <path
+        d="M120-160q-33 0-56.5-23.5T40-240v-480q0-33 23.5-56.5T120-800h720q33 0 56.5 23.5T920-720v480q0 33-23.5 56.5T840-160H120Zm40-560h-40v480h40v-480Zm80 480h480v-480H240v480Zm560-480v480h40v-480h-40Zm0 0h40-40Zm-640 0h-40 40Z" />
+</svg>
\ No newline at end of file
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index 894332acb..3f70a7d23 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -66,7 +66,7 @@
       margin-inline-start: 15px;
       text-align: start;
 
-      i[data-hidden] {
+      svg[data-hidden] {
         display: none;
       }
 
diff --git a/app/views/application/_card.html.haml b/app/views/application/_card.html.haml
index 1b3dd889c..ae74f1dc6 100644
--- a/app/views/application/_card.html.haml
+++ b/app/views/application/_card.html.haml
@@ -15,4 +15,4 @@
           %strong.emojify.p-name= display_name(account, custom_emojify: true)
         %span
           = acct(account)
-          = fa_icon('lock', { data: ({ hidden: true } unless account.locked?) })
+          = material_symbol('lock', { data: ({ hidden: true } unless account.locked?) })
diff --git a/app/views/auth/registrations/_account_warning.html.haml b/app/views/auth/registrations/_account_warning.html.haml
index c51179b49..d558e1d9c 100644
--- a/app/views/auth/registrations/_account_warning.html.haml
+++ b/app/views/auth/registrations/_account_warning.html.haml
@@ -2,7 +2,7 @@
   .strike-entry__header
     .strike-entry__avatar
       .indicator-icon{ class: account_warning.overruled? ? 'success' : 'failure' }
-        = fa_icon 'warning'
+        = material_symbol 'warning'
     .strike-entry__content
       .strike-entry__title
         = t 'disputes.strikes.title',
diff --git a/app/views/auth/registrations/_session.html.haml b/app/views/auth/registrations/_session.html.haml
index 631ae0460..92e514759 100644
--- a/app/views/auth/registrations/_session.html.haml
+++ b/app/views/auth/registrations/_session.html.haml
@@ -1,7 +1,7 @@
 %tr
   %td
     %span{ title: session.user_agent }<
-      = fa_icon "#{session_device_icon(session)} fw", 'aria-label': session_device_icon(session)
+      = material_symbol session_device_icon(session), 'aria-label': session_device_icon(session)
       &nbsp;
       = t 'sessions.description',
           browser: t("sessions.browsers.#{session.browser}", default: session.browser.to_s),
diff --git a/app/views/disputes/strikes/show.html.haml b/app/views/disputes/strikes/show.html.haml
index 5f7213882..2bfecebbf 100644
--- a/app/views/disputes/strikes/show.html.haml
+++ b/app/views/disputes/strikes/show.html.haml
@@ -9,13 +9,13 @@
 - if @strike.overruled?
   %p.hint
     %span.positive-hint
-      = fa_icon 'check'
+      = material_symbol 'check'
       &nbsp;
       = t 'disputes.strikes.appeal_approved'
 - elsif @appeal.persisted? && @appeal.rejected?
   %p.hint
     %span.negative-hint
-      = fa_icon 'times'
+      = material_symbol 'close'
       &nbsp;
       = t 'disputes.strikes.appeal_rejected'
 
diff --git a/app/views/filters/_filter.html.haml b/app/views/filters/_filter.html.haml
index 9d82a979f..a544ac3a7 100644
--- a/app/views/filters/_filter.html.haml
+++ b/app/views/filters/_filter.html.haml
@@ -14,7 +14,7 @@
       - unless filter.keywords.empty?
         %li.permissions-list__item
           .permissions-list__item__icon
-            = fa_icon('paragraph')
+            = material_symbol('format_paragraph')
           .permissions-list__item__text
             .permissions-list__item__text__title
               = t('filters.index.keywords', count: filter.keywords.size)
@@ -25,7 +25,7 @@
       - unless filter.statuses.empty?
         %li.permissions-list__item
           .permissions-list__item__icon
-            = fa_icon('comment')
+            = material_symbol('chat')
           .permissions-list__item__text
             .permissions-list__item__text__title
               = t('filters.index.statuses', count: filter.statuses.size)
diff --git a/app/views/filters/_filter_fields.html.haml b/app/views/filters/_filter_fields.html.haml
index 0f4049ffb..797c969b2 100644
--- a/app/views/filters/_filter_fields.html.haml
+++ b/app/views/filters/_filter_fields.html.haml
@@ -58,4 +58,4 @@
       %tr
         %td{ colspan: 3 }
           = link_to_add_association f, :keywords, class: 'table-action-link', partial: 'keyword_fields', 'data-association-insertion-node': '.keywords-table tbody', 'data-association-insertion-method': 'append' do
-            = safe_join([fa_icon('plus'), t('filters.edit.add_keyword')])
+            = safe_join([material_symbol('add'), t('filters.edit.add_keyword')])
diff --git a/app/views/filters/_keyword_fields.html.haml b/app/views/filters/_keyword_fields.html.haml
index eedd514ef..136ab1653 100644
--- a/app/views/filters/_keyword_fields.html.haml
+++ b/app/views/filters/_keyword_fields.html.haml
@@ -5,4 +5,4 @@
   %td
     = f.hidden_field :id if f.object&.persisted? # Required so Rails doesn't put the field outside of the <tr/>
     = link_to_remove_association(f, class: 'table-action-link') do
-      = safe_join([fa_icon('times'), t('filters.index.delete')])
+      = safe_join([material_symbol('close'), t('filters.index.delete')])
diff --git a/app/views/invites/_invite.html.haml b/app/views/invites/_invite.html.haml
index d332dc5a4..94e1a7112 100644
--- a/app/views/invites/_invite.html.haml
+++ b/app/views/invites/_invite.html.haml
@@ -7,7 +7,7 @@
 
   - if invite.valid_for_use?
     %td
-      = fa_icon 'user fw'
+      = material_symbol 'person'
       = invite.uses
       = " / #{invite.max_uses}" unless invite.max_uses.nil?
     %td
diff --git a/app/views/kaminari/_next_page.html.haml b/app/views/kaminari/_next_page.html.haml
index c44aea1f1..5f27f4c8e 100644
--- a/app/views/kaminari/_next_page.html.haml
+++ b/app/views/kaminari/_next_page.html.haml
@@ -8,4 +8,4 @@
     remote:        data-remote
 
 %span.next
-  = link_to_unless current_page.last?, safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), url, rel: 'next', remote: remote
+  = link_to_unless current_page.last?, safe_join([t('pagination.next'), material_symbol('chevron_right')], ' '), url, rel: 'next', remote: remote
diff --git a/app/views/kaminari/_prev_page.html.haml b/app/views/kaminari/_prev_page.html.haml
index 284d6223b..c5584f6a8 100644
--- a/app/views/kaminari/_prev_page.html.haml
+++ b/app/views/kaminari/_prev_page.html.haml
@@ -7,4 +7,4 @@
     per_page:      number of items to fetch per page
     remote:        data-remote
 %span.prev
-  = link_to_unless current_page.first?, safe_join([fa_icon('chevron-left'), t('pagination.prev')], ' '), url, rel: 'prev', remote: remote
+  = link_to_unless current_page.first?, safe_join([material_symbol('chevron_left'), t('pagination.prev')], ' '), url, rel: 'prev', remote: remote
diff --git a/app/views/oauth/authorizations/new.html.haml b/app/views/oauth/authorizations/new.html.haml
index d4563b2f0..ca9d12a67 100644
--- a/app/views/oauth/authorizations/new.html.haml
+++ b/app/views/oauth/authorizations/new.html.haml
@@ -13,7 +13,7 @@
       - grouped_scopes(@pre_auth.scopes).each do |scope|
         %li.permissions-list__item
           .permissions-list__item__icon
-            = fa_icon('check')
+            = material_symbol('check')
           .permissions-list__item__text
             .permissions-list__item__text__title
               = t(scope.key, scope: [:doorkeeper, :grouped_scopes, :title])
diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml
index 009bbf8d8..b6819bbd7 100644
--- a/app/views/oauth/authorized_applications/index.html.haml
+++ b/app/views/oauth/authorized_applications/index.html.haml
@@ -36,7 +36,7 @@
           - grouped_scopes(application.scopes).each do |scope|
             %li.permissions-list__item
               .permissions-list__item__icon
-                = fa_icon('check')
+                = material_symbol('check')
               .permissions-list__item__text
                 .permissions-list__item__text__title
                   = t(scope.key, scope: [:doorkeeper, :grouped_scopes, :title])
diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml
index 6a866b13f..7478b8c5c 100644
--- a/app/views/relationships/show.html.haml
+++ b/app/views/relationships/show.html.haml
@@ -42,13 +42,13 @@
       %label.batch-table__toolbar__select.batch-checkbox-all
         = check_box_tag :batch_checkbox_all, nil, false
       .batch-table__toolbar__actions
-        = f.button safe_join([fa_icon('user-plus'), t('relationships.follow_selected_followers')]), name: :follow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_follow_selected_followers') } if followed_by_relationship? && !mutual_relationship?
+        = f.button safe_join([material_symbol('person_add'), t('relationships.follow_selected_followers')]), name: :follow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_follow_selected_followers') } if followed_by_relationship? && !mutual_relationship?
 
-        = f.button safe_join([fa_icon('user-times'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_follows') } unless followed_by_relationship?
+        = f.button safe_join([material_symbol('person_remove'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_follows') } unless followed_by_relationship?
 
-        = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_followers') } unless following_relationship?
+        = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_followers') } unless following_relationship?
 
-        = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship?
+        = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship?
     .batch-table__body
       - if @accounts.empty?
         = nothing_here 'nothing-here--under-tabs'
diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml
index c55dff5d9..6cd240bbb 100644
--- a/app/views/statuses/_detailed_status.html.haml
+++ b/app/views/statuses/_detailed_status.html.haml
@@ -11,7 +11,7 @@
           %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
         %span.display-name__account
           = acct(status.account)
-          = fa_icon('lock') if status.account.locked?
+          = material_symbol('lock') if status.account.locked?
 
   = account_action_button(status.account)
 
@@ -58,20 +58,20 @@
       ·
     %span.detailed-status__link
       - if status.in_reply_to_id.nil?
-        = fa_icon('reply')
+        = material_symbol('reply')
       - else
-        = fa_icon('reply-all')
+        = material_symbol('reply_all')
       %span.detailed-status__reblogs>= friendly_number_to_human status.replies_count
       &nbsp;
     ·
     - if status.public_visibility? || status.unlisted_visibility?
       %span.detailed-status__link
-        = fa_icon('retweet')
+        = material_symbol('repeat')
         %span.detailed-status__reblogs>= friendly_number_to_human status.reblogs_count
         &nbsp;
       ·
     %span.detailed-status__link
-      = fa_icon('star')
+      = material_symbol('star')
       %span.detailed-status__favorites>= friendly_number_to_human status.favourites_count
       &nbsp;
 
diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml
index 93effc452..ee7900fbf 100644
--- a/app/views/statuses/_simple_status.html.haml
+++ b/app/views/statuses/_simple_status.html.haml
@@ -26,7 +26,7 @@
           &nbsp;
           %span.display-name__account
             = acct(status.account)
-            = fa_icon('lock') if status.account.locked?
+            = material_symbol('lock') if status.account.locked?
   .status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }<
     - if status.spoiler_text?
       %p<
@@ -55,16 +55,16 @@
   .status__action-bar
     %span.status__action-bar-button.icon-button.icon-button--with-counter
       - if status.in_reply_to_id.nil?
-        = fa_icon 'reply fw'
+        = material_symbol 'reply'
       - else
-        = fa_icon 'reply-all fw'
+        = material_symbol 'reply_all'
       %span.icon-button__counter= obscured_counter status.replies_count
     %span.status__action-bar-button.icon-button
       - if status.distributable?
-        = fa_icon 'retweet fw'
+        = material_symbol 'repeat'
       - elsif status.private_visibility? || status.limited_visibility?
-        = fa_icon 'lock fw'
+        = material_symbol 'lock'
       - else
-        = fa_icon 'at fw'
+        = material_symbol 'alternate_email'
     %span.status__action-bar-button.icon-button
-      = fa_icon 'star fw'
+      = material_symbol 'star'
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 463a90b69..95e697616 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -59,6 +59,15 @@ describe ApplicationHelper do
     end
   end
 
+  describe '#material_symbol' do
+    it 'returns an svg with the icon and options' do
+      expect(helper.material_symbol('lock', class: :test, data: { hidden: true }))
+        .to match('<svg.*/svg>')
+        .and match('class="icon material-lock test"')
+        .and match('data-hidden="true"')
+    end
+  end
+
   describe 'open_registrations?' do
     it 'returns true when open for registrations' do
       allow(Setting).to receive(:[]).with('registrations_mode').and_return('open')
diff --git a/spec/helpers/settings_helper_spec.rb b/spec/helpers/settings_helper_spec.rb
index cba5c6ee8..ca447d8ce 100644
--- a/spec/helpers/settings_helper_spec.rb
+++ b/spec/helpers/settings_helper_spec.rb
@@ -10,7 +10,7 @@ describe SettingsHelper do
       it 'detects the device and returns a descriptive string' do
         result = helper.session_device_icon(session)
 
-        expect(result).to eq('mobile')
+        expect(result).to eq('smartphone')
       end
     end
 
@@ -30,7 +30,7 @@ describe SettingsHelper do
       it 'detects the device and returns a descriptive string' do
         result = helper.session_device_icon(session)
 
-        expect(result).to eq('desktop')
+        expect(result).to eq('desktop_mac')
       end
     end
   end