diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index 3e4771dcf..8a78b07a1 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -85,6 +85,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_post_reference_modal, :setting_add_reference_modal, :setting_unselect_reference_modal, + :setting_enable_empty_column, notification_emails: %i(follow follow_request reblog favourite emoji_reaction status_reference mention digest report pending_account trending_tag), interactions: %i(must_be_follower must_be_following must_be_following_dm) ) diff --git a/app/javascript/mastodon/components/column_back_button.js b/app/javascript/mastodon/components/column_back_button.js index d97622705..603e413c7 100644 --- a/app/javascript/mastodon/components/column_back_button.js +++ b/app/javascript/mastodon/components/column_back_button.js @@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; import Icon from 'mastodon/components/icon'; import { createPortal } from 'react-dom'; +import { enableEmptyColumn } from 'mastodon/initial_state'; export default class ColumnBackButton extends React.PureComponent { @@ -22,6 +23,10 @@ export default class ColumnBackButton extends React.PureComponent { } } + handleCloseClick = () => { + this.context.router.history.push('/empty'); + } + render () { const { multiColumn } = this.props; @@ -32,8 +37,15 @@ export default class ColumnBackButton extends React.PureComponent { ); + const backButton = enableEmptyColumn ? ( + + ) : component; + if (multiColumn) { - return component; + return backButton; } else { // The portal container and the component may be rendered to the DOM in // the same React render pass, so the container might not be available at diff --git a/app/javascript/mastodon/components/column_back_button_slim.js b/app/javascript/mastodon/components/column_back_button_slim.js index cc8bfb151..be9ed2e84 100644 --- a/app/javascript/mastodon/components/column_back_button_slim.js +++ b/app/javascript/mastodon/components/column_back_button_slim.js @@ -2,16 +2,26 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import ColumnBackButton from './column_back_button'; import Icon from 'mastodon/components/icon'; +import { enableEmptyColumn } from 'mastodon/initial_state'; export default class ColumnBackButtonSlim extends ColumnBackButton { render () { + const { multiColumn } = this.props; + return (
-
- - -
+ { multiColumn && enableEmptyColumn ? ( +
+ + +
+ ) : ( +
+ + +
+ )}
); } diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js index 236e92296..6fd4f042c 100644 --- a/app/javascript/mastodon/components/column_header.js +++ b/app/javascript/mastodon/components/column_header.js @@ -4,6 +4,7 @@ import { createPortal } from 'react-dom'; import classNames from 'classnames'; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; import Icon from 'mastodon/components/icon'; +import { enableEmptyColumn } from 'mastodon/initial_state'; const messages = defineMessages({ show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' }, @@ -71,6 +72,10 @@ class ColumnHeader extends React.PureComponent { this.historyBack(); } + handleCloseClick = () => { + this.context.router.history.push('/empty'); + } + handleTransitionEnd = () => { this.setState({ animating: false }); } @@ -128,7 +133,12 @@ class ColumnHeader extends React.PureComponent { } if (!pinned && (multiColumn || showBackButton)) { - backButton = ( + backButton = multiColumn && enableEmptyColumn ? ( + + ) : ( + {enableEmptyColumn &&
} } diff --git a/app/javascript/mastodon/features/reactioned/components/header.js b/app/javascript/mastodon/features/reactioned/components/header.js index 5fc2b828a..6efa1497e 100644 --- a/app/javascript/mastodon/features/reactioned/components/header.js +++ b/app/javascript/mastodon/features/reactioned/components/header.js @@ -21,6 +21,10 @@ export default class Header extends ImmutablePureComponent { this.context.router.history.push(`/statuses/${this.props.status.get('id')}`); }; + handleStatusCloseClick = () => { + this.context.router.history.push('/empty'); + } + render () { const { status, hideTabs } = this.props; diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index b0e89d1a1..0683fc660 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -65,8 +65,9 @@ import { FollowRecommendations, Trends, Suggestions, + EmptyColumn, } from './util/async-components'; -import { me } from '../../initial_state'; +import { me, enableEmptyColumn } from '../../initial_state'; import { closeOnboarding, INTRODUCTION_VERSION } from 'mastodon/actions/onboarding'; // Dummy import, to make sure that ends up in the application bundle. @@ -158,7 +159,7 @@ class SwitchingColumnsArea extends React.PureComponent { render () { const { children, mobile } = this.props; - const redirect = mobile ? : ; + const redirect = mobile ? : enableEmptyColumn ? : ; return ( @@ -211,6 +212,8 @@ class SwitchingColumnsArea extends React.PureComponent { + + diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index 3a1d3bf97..6b5549b9e 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -217,3 +217,7 @@ export function Trends () { export function Suggestions () { return import(/* webpackChunkName: "features/suggestions" */'../../suggestions'); } + +export function EmptyColumn () { + return import(/* webpackChunkName: "features/empty" */'../../empty'); +} diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index bce09126a..a2a720eed 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -49,5 +49,6 @@ export const new_features_policy = getMeta('new_features_policy'); export const enableStatusReference = getMeta('enable_status_reference'); export const maxReferences = initialState?.status_references?.max_references; export const matchVisibilityOfReferences = getMeta('match_visibility_of_references'); +export const enableEmptyColumn = getMeta('enable_empty_column'); export default initialState; diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 7689e3c80..e2e3f4e10 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -108,6 +108,7 @@ "column.public": "Federated timeline", "column_back_button.label": "Back", "column_back_button_to_pots.label": "Back to post detail", + "column_close_button.label": "Close", "column_header.hide_settings": "Hide settings", "column_header.moveLeft_settings": "Move column to the left", "column_header.moveRight_settings": "Move column to the right", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 0c0901149..8bf77586a 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -108,6 +108,7 @@ "column.public": "連合タイムライン", "column_back_button.label": "戻る", "column_back_button_to_pots.label": "投稿の詳細に戻る", + "column_close_button.label": "閉じる", "column_header.hide_settings": "設定を隠す", "column_header.moveLeft_settings": "カラムを左に移動する", "column_header.moveRight_settings": "カラムを右に移動する", diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index eda5470a2..8c067c242 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -79,6 +79,7 @@ class UserSettingsDecorator user.settings['enable_status_reference'] = enable_status_reference_preference if change?('setting_enable_status_reference') user.settings['match_visibility_of_references'] = match_visibility_of_references_preference if change?('setting_match_visibility_of_references') user.settings['hexagon_avatar'] = hexagon_avatar_preference if change?('setting_hexagon_avatar') + user.settings['enable_empty_column'] = enable_empty_column_preference if change?('setting_enable_empty_column') end def merged_notification_emails @@ -281,6 +282,10 @@ end boolean_cast_setting 'setting_match_visibility_of_references' end + def enable_empty_column_preference + boolean_cast_setting 'setting_enable_empty_column' + end + def boolean_cast_setting(key) ActiveModel::Type::Boolean.new.cast(settings[key]) end diff --git a/app/models/user.rb b/app/models/user.rb index 9010bde77..e9c2523f8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -136,7 +136,7 @@ class User < ApplicationRecord :theme_instance_ticker, :enable_status_reference, :match_visibility_of_references, :post_reference_modal, :add_reference_modal, :unselect_reference_modal, - :hexagon_avatar, + :hexagon_avatar, :enable_empty_column, to: :settings, prefix: :setting, allow_nil: false diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 4f0c132e0..2bae08577 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -63,6 +63,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:post_reference_modal] = object.current_account.user.setting_post_reference_modal store[:add_reference_modal] = object.current_account.user.setting_add_reference_modal store[:unselect_reference_modal] = object.current_account.user.setting_unselect_reference_modal + store[:enable_empty_column] = object.current_account.user.setting_enable_empty_column else store[:auto_play_gif] = Setting.auto_play_gif diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 17acecb9b..1d6c3a7db 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -31,6 +31,9 @@ .fields-group = f.input :setting_advanced_layout, as: :boolean, wrapper: :with_label, hint: false + .fields-group + = f.input :setting_enable_empty_column, as: :boolean, wrapper: :with_label, fedibird_features: true + %h4= t 'appearance.animations_and_accessibility' .fields-group diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 872199de5..bbfb34f3c 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -59,6 +59,7 @@ en: setting_display_media_default: Hide media marked as sensitive setting_display_media_hide_all: Always hide media setting_display_media_show_all: Always show media + setting_enable_empty_column: The last column is initially hidden and can be closed at will setting_enable_limited_timeline: Enable a limited home to display private and circle and direct message setting_enable_reaction: Enable the reaction display on the timeline and display the reaction button setting_enable_status_reference: Enable the feature where a post references another post @@ -216,6 +217,7 @@ en: setting_display_media_default: Default setting_display_media_hide_all: Hide all setting_display_media_show_all: Show all + setting_enable_empty_column: Enable last column to be closed setting_enable_limited_timeline: Enable limited timeline setting_enable_reaction: Enable reaction setting_enable_status_reference: Enable reference diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 25e6f9840..c6220d48c 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -59,6 +59,7 @@ ja: setting_display_media_default: 閲覧注意としてマークされたメディアは隠す setting_display_media_hide_all: メディアを常に隠す setting_display_media_show_all: メディアを常に表示する + setting_enable_empty_column: 最後のカラムを初期状態で非表示にし、任意に閉じられるようにします setting_enable_limited_timeline: フォロワー限定・サークル・ダイレクトメッセージを表示する限定ホームを有効にします setting_enable_reaction: タイムラインでリアクションの表示を有効にし、リアクションボタンを表示する setting_enable_status_reference: 投稿が別の投稿を参照する機能を有効にします @@ -216,6 +217,7 @@ ja: setting_display_media_default: 標準 setting_display_media_hide_all: 非表示 setting_display_media_show_all: 表示 + setting_enable_empty_column: 最終カラムを閉じられるようにする setting_enable_limited_timeline: 限定ホームを有効にする setting_enable_reaction: リアクションを有効にする setting_enable_status_reference: 参照を有効にする diff --git a/config/settings.yml b/config/settings.yml index 18888f656..3bd234c7c 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -97,6 +97,7 @@ defaults: &defaults add_reference_modal: true unselect_reference_modal: false hexagon_avatar: false + enable_empty_column: false development: <<: *defaults