@@ -6,15 +6,15 @@ import { Status } from '../Statuses/Status';
66import type { StatusCollection } from '../Statuses/StatusCollection' ;
77import { createStatusRegistryReport } from '../Statuses/StatusRegistryReport' ;
88import { i18n } from '../i18n/i18n' ;
9- import { renameKeyInRecordPreservingOrder } from '../lib/RecordHelpers' ;
109import * as Themes from './Themes' ;
11- import { type HeadingState , type Settings , TASK_FORMATS } from './Settings' ;
10+ import { type HeadingState , type IncludesMap , type Settings , TASK_FORMATS } from './Settings' ;
1211import { getSettings , isFeatureEnabled , updateGeneralSetting , updateSettings } from './Settings' ;
1312import { GlobalFilter } from './GlobalFilter' ;
1413import { StatusSettings } from './StatusSettings' ;
1514
1615import { CustomStatusModal } from './CustomStatusModal' ;
1716import { GlobalQuery } from './GlobalQuery' ;
17+ import { IncludesSettingsService } from './IncludesSettingsService' ;
1818
1919export class SettingsTab extends PluginSettingTab {
2020 // If the UI needs a more complex setting you can create a
@@ -26,6 +26,7 @@ export class SettingsTab extends PluginSettingTab {
2626 } ;
2727
2828 private readonly plugin : TasksPlugin ;
29+ private readonly includesSettingsService = new IncludesSettingsService ( ) ;
2930
3031 constructor ( { plugin } : { plugin : TasksPlugin } ) {
3132 super ( plugin . app , plugin ) ;
@@ -662,13 +663,10 @@ export class SettingsTab extends PluginSettingTab {
662663 // Handle renaming an include
663664 const commitRename = async ( ) => {
664665 if ( newKey && newKey !== key ) {
665- const newIncludes = renameKeyInRecordPreservingOrder ( settings . includes , key , newKey ) ;
666- updateSettings ( { includes : newIncludes } ) ;
667- await this . plugin . saveSettings ( ) ;
668-
669- // Refresh settings after replacing the includes object to avoid stale data in the next render.
670- Object . assign ( settings , getSettings ( ) ) ;
671- renderIncludes ( ) ;
666+ const updatedIncludes = this . includesSettingsService . renameInclude ( settings . includes , key , newKey ) ;
667+ if ( updatedIncludes ) {
668+ await this . saveIncludesSettings ( updatedIncludes , settings , renderIncludes ) ;
669+ }
672670 }
673671 } ;
674672
@@ -689,9 +687,12 @@ export class SettingsTab extends PluginSettingTab {
689687 this . setupAutoResizingTextarea ( textArea ) ;
690688
691689 return textArea . onChange ( async ( newValue ) => {
692- settings . includes [ key ] = newValue ;
693- updateSettings ( { includes : settings . includes } ) ;
694- await this . plugin . saveSettings ( ) ;
690+ const updatedIncludes = this . includesSettingsService . updateIncludeValue (
691+ settings . includes ,
692+ key ,
693+ newValue ,
694+ ) ;
695+ await this . saveIncludesSettings ( updatedIncludes , settings , null ) ;
695696 } ) ;
696697 } ) ;
697698
@@ -700,10 +701,8 @@ export class SettingsTab extends PluginSettingTab {
700701 btn . setIcon ( 'cross' )
701702 . setTooltip ( 'Delete' )
702703 . onClick ( async ( ) => {
703- delete settings . includes [ key ] ;
704- updateSettings ( { includes : settings . includes } ) ;
705- await this . plugin . saveSettings ( ) ;
706- renderIncludes ( ) ;
704+ const updatedIncludes = this . includesSettingsService . deleteInclude ( settings . includes , key ) ;
705+ await this . saveIncludesSettings ( updatedIncludes , settings , renderIncludes ) ;
707706 } ) ;
708707 } ) ;
709708 }
@@ -726,22 +725,34 @@ export class SettingsTab extends PluginSettingTab {
726725 btn . setButtonText ( 'Add new include' )
727726 . setCta ( )
728727 . onClick ( async ( ) => {
729- const newKey = this . generateUniqueIncludeKey ( settings ) ;
730- settings . includes [ newKey ] = '' ;
731- updateSettings ( { includes : settings . includes } ) ;
732- await this . plugin . saveSettings ( ) ;
733- renderIncludes ( ) ;
728+ const { includes : updatedIncludes } = this . includesSettingsService . addInclude ( settings . includes ) ;
729+ await this . saveIncludesSettings ( updatedIncludes , settings , renderIncludes ) ;
734730 } ) ;
735731 } ) ;
736732 }
737733
738- private generateUniqueIncludeKey ( settings : Settings ) {
739- const baseKey = 'new_key' ;
740- let suffix = 1 ;
741- while ( Object . prototype . hasOwnProperty . call ( settings . includes , `${ baseKey } _${ suffix } ` ) ) {
742- suffix ++ ;
734+ /**
735+ * Updates settings with new includes and refreshes UI if needed
736+ * @param updatedIncludes The new includes map
737+ * @param settings The current settings object to update
738+ * @param refreshView Callback to refresh the view (pass null if no refresh is needed)
739+ */
740+ private async saveIncludesSettings (
741+ updatedIncludes : IncludesMap ,
742+ settings : Settings ,
743+ refreshView : ( ( ) => void ) | null ,
744+ ) : Promise < void > {
745+ // Update the settings in storage
746+ updateSettings ( { includes : updatedIncludes } ) ;
747+ await this . plugin . saveSettings ( ) ;
748+
749+ // Update the local settings object to reflect the changes
750+ settings . includes = { ...updatedIncludes } ;
751+
752+ // Refresh the view if a callback was provided
753+ if ( refreshView ) {
754+ refreshView ( ) ;
743755 }
744- return `${ baseKey } _${ suffix } ` ;
745756 }
746757
747758 private static renderFolderArray ( folders : string [ ] ) : string {
0 commit comments