From a75138d07336c2f10a8cbdba86f72f08c81cf9d7 Mon Sep 17 00:00:00 2001
From: Renaud Chaput <renchap@gmail.com>
Date: Thu, 13 Jul 2023 11:28:55 +0200
Subject: [PATCH] Convert Home timeline components to Typescript (#25583)

---
 .../components/column_settings.jsx            | 38 -----------
 .../components/column_settings.tsx            | 66 +++++++++++++++++++
 .../components/explore_prompt.jsx             | 25 -------
 .../components/explore_prompt.tsx             | 46 +++++++++++++
 .../containers/column_settings_container.js   | 22 -------
 .../mastodon/features/home_timeline/index.jsx |  4 +-
 6 files changed, 114 insertions(+), 87 deletions(-)
 delete mode 100644 app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
 create mode 100644 app/javascript/mastodon/features/home_timeline/components/column_settings.tsx
 delete mode 100644 app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
 create mode 100644 app/javascript/mastodon/features/home_timeline/components/explore_prompt.tsx
 delete mode 100644 app/javascript/mastodon/features/home_timeline/containers/column_settings_container.js

diff --git a/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
deleted file mode 100644
index b6e6b9cff6..0000000000
--- a/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import PropTypes from 'prop-types';
-import { PureComponent } from 'react';
-
-import { injectIntl, FormattedMessage } from 'react-intl';
-
-import ImmutablePropTypes from 'react-immutable-proptypes';
-
-import SettingToggle from '../../notifications/components/setting_toggle';
-
-class ColumnSettings extends PureComponent {
-
-  static propTypes = {
-    settings: ImmutablePropTypes.map.isRequired,
-    onChange: PropTypes.func.isRequired,
-    intl: PropTypes.object.isRequired,
-  };
-
-  render () {
-    const { settings, onChange } = this.props;
-
-    return (
-      <div>
-        <span className='column-settings__section'><FormattedMessage id='home.column_settings.basic' defaultMessage='Basic' /></span>
-
-        <div className='column-settings__row'>
-          <SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'reblog']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_reblogs' defaultMessage='Show boosts' />} />
-        </div>
-
-        <div className='column-settings__row'>
-          <SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'reply']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_replies' defaultMessage='Show replies' />} />
-        </div>
-      </div>
-    );
-  }
-
-}
-
-export default injectIntl(ColumnSettings);
diff --git a/app/javascript/mastodon/features/home_timeline/components/column_settings.tsx b/app/javascript/mastodon/features/home_timeline/components/column_settings.tsx
new file mode 100644
index 0000000000..477e94c9c5
--- /dev/null
+++ b/app/javascript/mastodon/features/home_timeline/components/column_settings.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/no-unsafe-call,
+                  @typescript-eslint/no-unsafe-return,
+                  @typescript-eslint/no-unsafe-assignment,
+                  @typescript-eslint/no-unsafe-member-access
+                  -- the settings store is not yet typed */
+import { useCallback } from 'react';
+
+import { FormattedMessage } from 'react-intl';
+
+import { useAppSelector, useAppDispatch } from 'mastodon/store';
+
+import { changeSetting } from '../../../actions/settings';
+import SettingToggle from '../../notifications/components/setting_toggle';
+
+export const ColumnSettings: React.FC = () => {
+  const settings = useAppSelector((state) => state.settings.get('home'));
+
+  const dispatch = useAppDispatch();
+  const onChange = useCallback(
+    (key: string, checked: boolean) => {
+      void dispatch(changeSetting(['home', ...key], checked));
+    },
+    [dispatch]
+  );
+
+  return (
+    <div>
+      <span className='column-settings__section'>
+        <FormattedMessage
+          id='home.column_settings.basic'
+          defaultMessage='Basic'
+        />
+      </span>
+
+      <div className='column-settings__row'>
+        <SettingToggle
+          prefix='home_timeline'
+          settings={settings}
+          settingPath={['shows', 'reblog']}
+          onChange={onChange}
+          label={
+            <FormattedMessage
+              id='home.column_settings.show_reblogs'
+              defaultMessage='Show boosts'
+            />
+          }
+        />
+      </div>
+
+      <div className='column-settings__row'>
+        <SettingToggle
+          prefix='home_timeline'
+          settings={settings}
+          settingPath={['shows', 'reply']}
+          onChange={onChange}
+          label={
+            <FormattedMessage
+              id='home.column_settings.show_replies'
+              defaultMessage='Show replies'
+            />
+          }
+        />
+      </div>
+    </div>
+  );
+};
diff --git a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
deleted file mode 100644
index 2af85b6d54..0000000000
--- a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-
-import { FormattedMessage } from 'react-intl';
-
-import { Link } from 'react-router-dom';
-
-import background from 'mastodon/../images/friends-cropped.png';
-import { DismissableBanner } from 'mastodon/components/dismissable_banner';
-
-
-export const ExplorePrompt = () => (
-  <DismissableBanner id='home.explore_prompt'>
-    <img src={background} alt='' className='dismissable-banner__background-image' />
-
-    <h1><FormattedMessage id='home.explore_prompt.title' defaultMessage='This is your home base within Mastodon.' /></h1>
-    <p><FormattedMessage id='home.explore_prompt.body' defaultMessage="Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. It's looking pretty quiet right now, so how about:" /></p>
-
-    <div className='dismissable-banner__message__actions__wrapper'>
-      <div className='dismissable-banner__message__actions'>
-        <Link to='/explore' className='button'><FormattedMessage id='home.actions.go_to_explore' defaultMessage="See what's trending" /></Link>
-        <Link to='/explore/suggestions' className='button button-tertiary'><FormattedMessage id='home.actions.go_to_suggestions' defaultMessage='Find people to follow' /></Link>
-      </div>
-    </div>
-  </DismissableBanner>
-);
diff --git a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.tsx b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.tsx
new file mode 100644
index 0000000000..47113d9b8e
--- /dev/null
+++ b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.tsx
@@ -0,0 +1,46 @@
+import { FormattedMessage } from 'react-intl';
+
+import { Link } from 'react-router-dom';
+
+import background from 'mastodon/../images/friends-cropped.png';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
+
+export const ExplorePrompt = () => (
+  <DismissableBanner id='home.explore_prompt'>
+    <img
+      src={background}
+      alt=''
+      className='dismissable-banner__background-image'
+    />
+
+    <h1>
+      <FormattedMessage
+        id='home.explore_prompt.title'
+        defaultMessage='This is your home base within Mastodon.'
+      />
+    </h1>
+    <p>
+      <FormattedMessage
+        id='home.explore_prompt.body'
+        defaultMessage="Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. It's looking pretty quiet right now, so how about:"
+      />
+    </p>
+
+    <div className='dismissable-banner__message__wrapper'>
+      <div className='dismissable-banner__message__actions'>
+        <Link to='/explore' className='button'>
+          <FormattedMessage
+            id='home.actions.go_to_explore'
+            defaultMessage="See what's trending"
+          />
+        </Link>
+        <Link to='/explore/suggestions' className='button button-tertiary'>
+          <FormattedMessage
+            id='home.actions.go_to_suggestions'
+            defaultMessage='Find people to follow'
+          />
+        </Link>
+      </div>
+    </div>
+  </DismissableBanner>
+);
diff --git a/app/javascript/mastodon/features/home_timeline/containers/column_settings_container.js b/app/javascript/mastodon/features/home_timeline/containers/column_settings_container.js
deleted file mode 100644
index 1ddec6da9c..0000000000
--- a/app/javascript/mastodon/features/home_timeline/containers/column_settings_container.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { connect } from 'react-redux';
-
-import { changeSetting, saveSettings } from '../../../actions/settings';
-import ColumnSettings from '../components/column_settings';
-
-const mapStateToProps = state => ({
-  settings: state.getIn(['settings', 'home']),
-});
-
-const mapDispatchToProps = dispatch => ({
-
-  onChange (key, checked) {
-    dispatch(changeSetting(['home', ...key], checked));
-  },
-
-  onSave () {
-    dispatch(saveSettings());
-  },
-
-});
-
-export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx
index ae98aec0a6..1cd6edd7aa 100644
--- a/app/javascript/mastodon/features/home_timeline/index.jsx
+++ b/app/javascript/mastodon/features/home_timeline/index.jsx
@@ -22,8 +22,8 @@ import Column from '../../components/column';
 import ColumnHeader from '../../components/column_header';
 import StatusListContainer from '../ui/containers/status_list_container';
 
+import { ColumnSettings } from './components/column_settings';
 import { ExplorePrompt } from './components/explore_prompt';
-import ColumnSettingsContainer from './containers/column_settings_container';
 
 const messages = defineMessages({
   title: { id: 'column.home', defaultMessage: 'Home' },
@@ -191,7 +191,7 @@ class HomeTimeline extends PureComponent {
           extraButton={announcementsButton}
           appendContent={hasAnnouncements && showAnnouncements && <AnnouncementsContainer />}
         >
-          <ColumnSettingsContainer />
+          <ColumnSettings />
         </ColumnHeader>
 
         {signedIn ? (