Add bookmarl_category_needed setting

This commit is contained in:
KMY 2023-08-26 18:27:17 +09:00
parent bd0e2bd796
commit 5a961cc368
13 changed files with 66 additions and 8 deletions

View file

@ -1,6 +1,10 @@
import { bookmarkCategoryNeeded } from 'mastodon/initial_state';
import { makeGetStatus } from 'mastodon/selectors';
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
import { unbookmark } from './interactions';
export const BOOKMARK_CATEGORY_FETCH_REQUEST = 'BOOKMARK_CATEGORY_FETCH_REQUEST'; export const BOOKMARK_CATEGORY_FETCH_REQUEST = 'BOOKMARK_CATEGORY_FETCH_REQUEST';
export const BOOKMARK_CATEGORY_FETCH_SUCCESS = 'BOOKMARK_CATEGORY_FETCH_SUCCESS'; export const BOOKMARK_CATEGORY_FETCH_SUCCESS = 'BOOKMARK_CATEGORY_FETCH_SUCCESS';
@ -330,7 +334,17 @@ export const addToBookmarkCategoryAdder = bookmarkCategoryId => (dispatch, getSt
}; };
export const removeFromBookmarkCategoryAdder = bookmarkCategoryId => (dispatch, getState) => { export const removeFromBookmarkCategoryAdder = bookmarkCategoryId => (dispatch, getState) => {
dispatch(removeFromBookmarkCategory(bookmarkCategoryId, getState().getIn(['bookmarkCategoryAdder', 'statusId']))); if (bookmarkCategoryNeeded) {
const categories = getState().getIn(['bookmarkCategoryAdder', 'bookmarkCategories', 'items']);
if (categories && categories.count() <= 1) {
const status = makeGetStatus()(getState(), { id: getState().getIn(['bookmarkCategoryAdder', 'statusId']) });
dispatch(unbookmark(status));
} else {
dispatch(removeFromBookmarkCategory(bookmarkCategoryId, getState().getIn(['bookmarkCategoryAdder', 'statusId'])));
}
} else {
dispatch(removeFromBookmarkCategory(bookmarkCategoryId, getState().getIn(['bookmarkCategoryAdder', 'statusId'])));
}
}; };
export function expandBookmarkCategoryStatuses(bookmarkCategoryId) { export function expandBookmarkCategoryStatuses(bookmarkCategoryId) {

View file

@ -12,7 +12,7 @@ import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/
import DropdownMenuContainer from '../containers/dropdown_menu_container'; import DropdownMenuContainer from '../containers/dropdown_menu_container';
import EmojiPickerDropdown from '../features/compose/containers/emoji_picker_dropdown_container'; import EmojiPickerDropdown from '../features/compose/containers/emoji_picker_dropdown_container';
import { me } from '../initial_state'; import { bookmarkCategoryNeeded, me } from '../initial_state';
import { IconButton } from './icon_button'; import { IconButton } from './icon_button';
@ -166,13 +166,21 @@ class StatusActionBar extends ImmutablePureComponent {
}; };
handleBookmarkClick = () => { handleBookmarkClick = () => {
this.props.onBookmark(this.props.status); if (bookmarkCategoryNeeded) {
this.handleBookmarkCategoryAdderClick();
} else {
this.props.onBookmark(this.props.status);
}
}; };
handleBookmarkCategoryAdderClick = () => { handleBookmarkCategoryAdderClick = () => {
this.props.onBookmarkCategoryAdder(this.props.status); this.props.onBookmarkCategoryAdder(this.props.status);
}; };
handleBookmarkClickOriginal = () => {
this.props.onBookmark(this.props.status);
};
handleDeleteClick = () => { handleDeleteClick = () => {
this.props.onDelete(this.props.status, this.context.router.history); this.props.onDelete(this.props.status, this.context.router.history);
}; };
@ -305,7 +313,7 @@ class StatusActionBar extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference }); menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference });
} }
menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark), action: this.handleBookmarkClick }); menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark), action: this.handleBookmarkClickOriginal });
menu.push({ text: intl.formatMessage(messages.bookmarkCategory), action: this.handleBookmarkCategoryAdderClick }); menu.push({ text: intl.formatMessage(messages.bookmarkCategory), action: this.handleBookmarkCategoryAdderClick });
if (writtenByMe && pinnableStatus) { if (writtenByMe && pinnableStatus) {

View file

@ -12,7 +12,7 @@ import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/
import { IconButton } from '../../../components/icon_button'; import { IconButton } from '../../../components/icon_button';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { me } from '../../../initial_state'; import { bookmarkCategoryNeeded, me } from '../../../initial_state';
import EmojiPickerDropdown from '../../compose/containers/emoji_picker_dropdown_container'; import EmojiPickerDropdown from '../../compose/containers/emoji_picker_dropdown_container';
const messages = defineMessages({ const messages = defineMessages({
@ -107,7 +107,11 @@ class ActionBar extends PureComponent {
}; };
handleBookmarkClick = (e) => { handleBookmarkClick = (e) => {
this.props.onBookmark(this.props.status, e); if (bookmarkCategoryNeeded) {
this.props.onBookmarkCategoryAdder(this.props.status);
} else {
this.props.onBookmark(this.props.status, e);
}
}; };
handleDeleteClick = () => { handleDeleteClick = () => {

View file

@ -63,7 +63,7 @@ import {
import ColumnHeader from '../../components/column_header'; import ColumnHeader from '../../components/column_header';
import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
import StatusContainer from '../../containers/status_container'; import StatusContainer from '../../containers/status_container';
import { boostModal, deleteModal } from '../../initial_state'; import { bookmarkCategoryNeeded, boostModal, deleteModal } from '../../initial_state';
import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import { makeGetStatus, makeGetPictureInPicture } from '../../selectors';
import Column from '../ui/components/column'; import Column from '../ui/components/column';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
@ -367,6 +367,11 @@ class Status extends ImmutablePureComponent {
}; };
handleBookmarkClick = (status) => { handleBookmarkClick = (status) => {
if (bookmarkCategoryNeeded) {
this.handleBookmarkCategoryAdderClick(status);
return;
}
if (status.get('bookmarked')) { if (status.get('bookmarked')) {
this.props.dispatch(unbookmark(status)); this.props.dispatch(unbookmark(status));
} else { } else {

View file

@ -50,6 +50,7 @@
* @property {boolean} auto_play_gif * @property {boolean} auto_play_gif
* @property {boolean} activity_api_enabled * @property {boolean} activity_api_enabled
* @property {string} admin * @property {string} admin
* @property {boolean} bookmark_category_needed
* @property {boolean=} boost_modal * @property {boolean=} boost_modal
* @property {boolean=} delete_modal * @property {boolean=} delete_modal
* @property {boolean=} disable_swiping * @property {boolean=} disable_swiping
@ -113,6 +114,7 @@ const getMeta = (prop) => initialState?.meta && initialState.meta[prop];
export const activityApiEnabled = getMeta('activity_api_enabled'); export const activityApiEnabled = getMeta('activity_api_enabled');
export const autoPlayGif = getMeta('auto_play_gif'); export const autoPlayGif = getMeta('auto_play_gif');
export const bookmarkCategoryNeeded = getMeta('bookmark_category_needed');
export const boostModal = getMeta('boost_modal'); export const boostModal = getMeta('boost_modal');
export const deleteModal = getMeta('delete_modal'); export const deleteModal = getMeta('delete_modal');
export const disableSwiping = getMeta('disable_swiping'); export const disableSwiping = getMeta('disable_swiping');

View file

@ -20,7 +20,14 @@ import {
const initialState = ImmutableMap(); const initialState = ImmutableMap();
const normalizeBookmarkCategory = (state, category) => state.set(category.id, fromJS(category)); const normalizeBookmarkCategory = (state, category) => {
const old = state.get(category.id);
state = state.set(category.id, fromJS(category));
if (old) {
state = state.setIn([category.id, 'items'], old.get('items'));
}
return state;
};
const normalizeBookmarkCategories = (state, bookmarkCategories) => { const normalizeBookmarkCategories = (state, bookmarkCategories) => {
bookmarkCategories.forEach(bookmarkCategory => { bookmarkCategories.forEach(bookmarkCategory => {

View file

@ -9,6 +9,9 @@ import {
BOOKMARK_CATEGORY_EDITOR_ADD_SUCCESS, BOOKMARK_CATEGORY_EDITOR_ADD_SUCCESS,
BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS, BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS,
} from '../actions/bookmark_categories'; } from '../actions/bookmark_categories';
import {
UNBOOKMARK_SUCCESS,
} from '../actions/interactions';
const initialState = ImmutableMap({ const initialState = ImmutableMap({
statusId: null, statusId: null,
@ -42,6 +45,8 @@ export default function bookmarkCategoryAdderReducer(state = initialState, actio
return state.updateIn(['bookmarkCategories', 'items'], bookmarkCategory => bookmarkCategory.unshift(action.bookmarkCategoryId)); return state.updateIn(['bookmarkCategories', 'items'], bookmarkCategory => bookmarkCategory.unshift(action.bookmarkCategoryId));
case BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS: case BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS:
return state.updateIn(['bookmarkCategories', 'items'], bookmarkCategory => bookmarkCategory.filterNot(item => item === action.bookmarkCategoryId)); return state.updateIn(['bookmarkCategories', 'items'], bookmarkCategory => bookmarkCategory.filterNot(item => item === action.bookmarkCategoryId));
case UNBOOKMARK_SUCCESS:
return action.status.get('id') === state.get('statusId') ? state.setIn(['bookmarkCategories', 'items'], ImmutableList()) : state;
default: default:
return state; return state;
} }

View file

@ -31,6 +31,10 @@ module HasUserSettings
settings['web.enable_login_privacy'] settings['web.enable_login_privacy']
end end
def setting_bookmark_category_needed
settings['web.bookmark_category_needed']
end
def setting_hide_recent_emojis def setting_hide_recent_emojis
settings['web.hide_recent_emojis'] settings['web.hide_recent_emojis']
end end

View file

@ -42,6 +42,7 @@ class UserSettings
setting :use_blurhash, default: true setting :use_blurhash, default: true
setting :use_pending_items, default: false setting :use_pending_items, default: false
setting :use_system_font, default: false setting :use_system_font, default: false
setting :bookmark_category_needed, default: false
setting :disable_swiping, default: false setting :disable_swiping, default: false
setting :delete_modal, default: true setting :delete_modal, default: true
setting :enable_login_privacy, default: false setting :enable_login_privacy, default: false

View file

@ -52,6 +52,7 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:use_blurhash] = object.current_account.user.setting_use_blurhash store[:use_blurhash] = object.current_account.user.setting_use_blurhash
store[:use_pending_items] = object.current_account.user.setting_use_pending_items store[:use_pending_items] = object.current_account.user.setting_use_pending_items
store[:show_trends] = Setting.trends && object.current_account.user.setting_trends store[:show_trends] = Setting.trends && object.current_account.user.setting_trends
store[:bookmark_category_needed] = object.current_account.user.setting_bookmark_category_needed
else else
store[:auto_play_gif] = Setting.auto_play_gif store[:auto_play_gif] = Setting.auto_play_gif
store[:display_media] = Setting.display_media store[:display_media] = Setting.display_media

View file

@ -40,6 +40,9 @@
.fields-group .fields-group
= ff.input :'web.hide_recent_emojis', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_recent_emojis'), hint: false = ff.input :'web.hide_recent_emojis', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_recent_emojis'), hint: false
.fields-group
= ff.input :'web.bookmark_category_needed', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_bookmark_category_needed'), hint: I18n.t('simple_form.hints.defaults.setting_bookmark_category_needed')
%h4= t 'appearance.discovery' %h4= t 'appearance.discovery'
.fields-group .fields-group

View file

@ -61,6 +61,7 @@ en:
scopes: Which APIs the application will be allowed to access. If you select a top-level scope, you don't need to select individual ones. scopes: Which APIs the application will be allowed to access. If you select a top-level scope, you don't need to select individual ones.
setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts) setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts)
setting_always_send_emails: Normally e-mail notifications won't be sent when you are actively using Mastodon setting_always_send_emails: Normally e-mail notifications won't be sent when you are actively using Mastodon
setting_bookmark_category_needed: When removing from all category, unbookmarked automatically
setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click
setting_display_media_default: Hide media marked as sensitive setting_display_media_default: Hide media marked as sensitive
setting_display_media_hide_all: Always hide media setting_display_media_hide_all: Always hide media
@ -218,6 +219,7 @@ en:
setting_always_send_emails: Always send e-mail notifications setting_always_send_emails: Always send e-mail notifications
setting_auto_play_gif: Auto-play animated GIFs setting_auto_play_gif: Auto-play animated GIFs
setting_bio_markdown: Enable profile markdown setting_bio_markdown: Enable profile markdown
setting_bookmark_category_needed: Category selection needed when registering bookmark on web
setting_boost_modal: Show confirmation dialog before boosting setting_boost_modal: Show confirmation dialog before boosting
setting_default_language: Posting language setting_default_language: Posting language
setting_default_privacy: Posting privacy setting_default_privacy: Posting privacy

View file

@ -60,6 +60,7 @@ ja:
setting_send_without_domain_blocks: 管理人が同人コンテンツの配送にふさわしくないと判断したサーバーに、制限に関係なく全ての投稿を配送します。ただし何が起きても自己責任になります setting_send_without_domain_blocks: 管理人が同人コンテンツの配送にふさわしくないと判断したサーバーに、制限に関係なく全ての投稿を配送します。ただし何が起きても自己責任になります
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響) setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
setting_always_send_emails: 通常、Mastodon からメール通知は行われません。 setting_always_send_emails: 通常、Mastodon からメール通知は行われません。
setting_bookmark_category_needed: すべてのカテゴリから削除したとき、ブックマークが自動で外れるようになります
setting_boost_modal: ブーストの公開範囲が指定できるようになります setting_boost_modal: ブーストの公開範囲が指定できるようになります
setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります
setting_disallow_unlisted_public_searchability: この設定を有効にすると、未収載投稿と検索範囲「全て」は両立できず不特定多数からの検索が不可になります。Fedibirdと同じ挙動になります setting_disallow_unlisted_public_searchability: この設定を有効にすると、未収載投稿と検索範囲「全て」は両立できず不特定多数からの検索が不可になります。Fedibirdと同じ挙動になります
@ -227,6 +228,7 @@ ja:
setting_always_send_emails: 常にメール通知を送信する setting_always_send_emails: 常にメール通知を送信する
setting_auto_play_gif: アニメーションGIFを自動再生する setting_auto_play_gif: アニメーションGIFを自動再生する
setting_bio_markdown: プロフィールのMarkdownを有効にする setting_bio_markdown: プロフィールのMarkdownを有効にする
setting_bookmark_category_needed: Webでブックマーク時にカテゴリの選択を必須にする
setting_boost_modal: ブーストする前に確認ダイアログを表示する setting_boost_modal: ブーストする前に確認ダイアログを表示する
setting_default_language: 投稿する言語 setting_default_language: 投稿する言語
setting_default_privacy: 投稿の公開範囲 setting_default_privacy: 投稿の公開範囲