@@ -21,15 +21,27 @@ import {
2121import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle" ;
2222import openBlockInSidebar from "roamjs-components/writes/openBlockInSidebar" ;
2323import extractRef from "roamjs-components/util/extractRef" ;
24+ import { getFormattedConfigTree , notify } from "~/utils/discourseConfigRef" ;
2425import {
25- getFormattedConfigTree ,
26- notify ,
27- subscribe ,
28- } from "~/utils/discourseConfigRef" ;
29- import type {
30- LeftSidebarConfig ,
31- LeftSidebarPersonalSectionConfig ,
26+ onSettingChange ,
27+ settingKeys ,
28+ } from "~/components/settings/utils/settingsEmitter" ;
29+ import {
30+ type LeftSidebarConfig ,
31+ type LeftSidebarPersonalSectionConfig ,
32+ mergeGlobalSectionWithAccessor ,
33+ mergePersonalSectionsWithAccessor ,
3234} from "~/utils/getLeftSidebarSettings" ;
35+ import {
36+ getGlobalSetting ,
37+ getPersonalSetting ,
38+ setGlobalSetting ,
39+ setPersonalSetting ,
40+ } from "~/components/settings/utils/accessors" ;
41+ import type {
42+ LeftSidebarGlobalSettings ,
43+ PersonalSection ,
44+ } from "~/components/settings/utils/zodSchema" ;
3345import { createBlock } from "roamjs-components/writes" ;
3446import deleteBlock from "roamjs-components/writes/deleteBlock" ;
3547import getTextByBlockUid from "roamjs-components/queries/getTextByBlockUid" ;
@@ -95,12 +107,18 @@ const toggleFoldedState = ({
95107 setIsOpen,
96108 folded,
97109 parentUid,
110+ isGlobal,
111+ sectionIndex,
98112} : {
99113 isOpen : boolean ;
100114 setIsOpen : Dispatch < SetStateAction < boolean > > ;
101115 folded : { uid ?: string ; value : boolean } ;
102116 parentUid : string ;
117+ isGlobal ?: boolean ;
118+ sectionIndex ?: number ;
103119} ) => {
120+ const newFolded = ! isOpen ;
121+
104122 if ( isOpen ) {
105123 setIsOpen ( false ) ;
106124 if ( folded . uid ) {
@@ -118,6 +136,17 @@ const toggleFoldedState = ({
118136 folded . uid = newUid ;
119137 folded . value = true ;
120138 }
139+
140+ if ( isGlobal ) {
141+ setGlobalSetting ( [ "Left sidebar" , "Settings" , "Folded" ] , newFolded ) ;
142+ } else if ( sectionIndex !== undefined ) {
143+ const sections =
144+ getPersonalSetting < PersonalSection [ ] > ( [ "Left sidebar" ] ) || [ ] ;
145+ if ( sections [ sectionIndex ] ) {
146+ sections [ sectionIndex ] . Settings . Folded = newFolded ;
147+ setPersonalSetting ( [ "Left sidebar" ] , sections ) ;
148+ }
149+ }
121150} ;
122151
123152const SectionChildren = ( {
@@ -160,8 +189,10 @@ const SectionChildren = ({
160189
161190const PersonalSectionItem = ( {
162191 section,
192+ sectionIndex,
163193} : {
164194 section : LeftSidebarPersonalSectionConfig ;
195+ sectionIndex : number ;
165196} ) => {
166197 const titleRef = parseReference ( section . text ) ;
167198 const blockText = useMemo (
@@ -182,6 +213,7 @@ const PersonalSectionItem = ({
182213 setIsOpen,
183214 folded : section . settings . folded ,
184215 parentUid : section . settings . uid || "" ,
216+ sectionIndex,
185217 } ) ;
186218 } ;
187219
@@ -226,9 +258,9 @@ const PersonalSections = ({ config }: { config: LeftSidebarConfig }) => {
226258
227259 return (
228260 < div className = "personal-left-sidebar-sections" >
229- { sections . map ( ( section ) => (
261+ { sections . map ( ( section , index ) => (
230262 < div key = { section . uid } >
231- < PersonalSectionItem section = { section } />
263+ < PersonalSectionItem section = { section } sectionIndex = { index } />
232264 </ div >
233265 ) ) }
234266 </ div >
@@ -253,6 +285,7 @@ const GlobalSection = ({ config }: { config: LeftSidebarConfig["global"] }) => {
253285 setIsOpen,
254286 folded : config . settings . folded ,
255287 parentUid : config . settings . uid ,
288+ isGlobal : true ,
256289 } ) ;
257290 } }
258291 >
@@ -276,22 +309,62 @@ const GlobalSection = ({ config }: { config: LeftSidebarConfig["global"] }) => {
276309 ) ;
277310} ;
278311
312+ // TODO(ENG-1471): Remove old-system merge when migration complete — just use accessor values directly.
313+ // See mergeGlobalSectionWithAccessor/mergePersonalSectionsWithAccessor for why the merge exists.
314+ const buildConfig = ( ) : LeftSidebarConfig => {
315+ // Read VALUES from accessor (handles flag routing + mismatch detection)
316+ const globalValues = getGlobalSetting < LeftSidebarGlobalSettings > ( [
317+ "Left sidebar" ,
318+ ] ) ;
319+ const personalValues = getPersonalSetting < PersonalSection [ ] > ( [
320+ "Left sidebar" ,
321+ ] ) ;
322+
323+ // Read UIDs from old system (needed for fold CRUD during dual-write)
324+ const oldConfig = getFormattedConfigTree ( ) . leftSidebar ;
325+
326+ return {
327+ uid : oldConfig . uid ,
328+ favoritesMigrated : oldConfig . favoritesMigrated ,
329+ sidebarMigrated : oldConfig . sidebarMigrated ,
330+ global : mergeGlobalSectionWithAccessor ( oldConfig . global , globalValues ) ,
331+ personal : {
332+ uid : oldConfig . personal . uid ,
333+ sections : mergePersonalSectionsWithAccessor (
334+ oldConfig . personal . sections ,
335+ personalValues ,
336+ ) ,
337+ } ,
338+ allPersonalSections : oldConfig . allPersonalSections ,
339+ } ;
340+ } ;
341+
279342export const useConfig = ( ) => {
280- const [ config , setConfig ] = useState (
281- ( ) => getFormattedConfigTree ( ) . leftSidebar ,
282- ) ;
343+ const [ config , setConfig ] = useState ( ( ) => buildConfig ( ) ) ;
283344 useEffect ( ( ) => {
284345 const handleUpdate = ( ) => {
285- setConfig ( getFormattedConfigTree ( ) . leftSidebar ) ;
346+ refreshConfigTree ( ) ;
347+ setConfig ( buildConfig ( ) ) ;
286348 } ;
287- const unsubscribe = subscribe ( handleUpdate ) ;
349+ const unsubGlobal = onSettingChange (
350+ settingKeys . globalLeftSidebar ,
351+ handleUpdate ,
352+ ) ;
353+ const unsubPersonal = onSettingChange (
354+ settingKeys . personalLeftSidebar ,
355+ handleUpdate ,
356+ ) ;
288357 return ( ) => {
289- unsubscribe ( ) ;
358+ unsubGlobal ( ) ;
359+ unsubPersonal ( ) ;
290360 } ;
291361 } , [ ] ) ;
292362 return { config, setConfig } ;
293363} ;
294364
365+ // TODO(ENG-1471): refreshAndNotify still needed by settings panels
366+ // (LeftSidebarGlobalSettings, LeftSidebarPersonalSettings) for old-system CRUD.
367+ // Remove when settings panels also read via accessors + emitter.
295368export const refreshAndNotify = ( ) => {
296369 refreshConfigTree ( ) ;
297370 notify ( ) ;
0 commit comments