11/* eslint-disable @typescript-eslint/naming-convention */
2- import React , {
3- useCallback ,
4- useEffect ,
5- useMemo ,
6- useRef ,
7- useState ,
8- } from "react" ;
2+ import React , { useCallback , useEffect , useRef , useState } from "react" ;
93import ReactDOM from "react-dom" ;
104import {
115 Collapse ,
@@ -21,29 +15,23 @@ import {
2115import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle" ;
2216import openBlockInSidebar from "roamjs-components/writes/openBlockInSidebar" ;
2317import extractRef from "roamjs-components/util/extractRef" ;
24- import {
25- getFormattedConfigTree ,
26- notify ,
27- subscribe ,
28- } from "~/utils/discourseConfigRef" ;
29- import type {
30- LeftSidebarConfig ,
31- LeftSidebarPersonalSectionConfig ,
32- } from "~/utils/getLeftSidebarSettings" ;
18+ import { getFormattedConfigTree } from "~/utils/discourseConfigRef" ;
3319import { createBlock } from "roamjs-components/writes" ;
34- import deleteBlock from "roamjs-components/writes/deleteBlock" ;
3520import getTextByBlockUid from "roamjs-components/queries/getTextByBlockUid" ;
3621import refreshConfigTree from "~/utils/refreshConfigTree" ;
37- import { Dispatch , SetStateAction } from "react" ;
3822import { SettingsDialog } from "./settings/Settings" ;
3923import { OnloadArgs } from "roamjs-components/types" ;
4024import renderOverlay from "roamjs-components/util/renderOverlay" ;
4125import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid" ;
4226import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage" ;
4327import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid" ;
44- import { migrateLeftSidebarSettings } from "~/utils/migrateLeftSidebarSettings" ;
45- import { useLeftSidebarGlobalSettings } from "./settings/utils/hooks" ;
46- import { setGlobalSetting } from "./settings/utils/accessors" ;
28+ import {
29+ useLeftSidebarGlobalSettings ,
30+ useLeftSidebarPersonalSettings ,
31+ } from "./settings/utils/hooks" ;
32+ import { getGlobalSetting , setGlobalSetting , setPersonalSetting } from "./settings/utils/accessors" ;
33+ import type { LeftSidebarGlobalSettings } from "./settings/utils/zodSchema" ;
34+ import type { PersonalSection } from "./settings/utils/zodSchema" ;
4735
4836const parseReference = ( text : string ) => {
4937 const extracted = extractRef ( text ) ;
@@ -87,36 +75,6 @@ const openTarget = async (e: React.MouseEvent, targetUid: string) => {
8775 }
8876} ;
8977
90- const toggleFoldedState = ( {
91- isOpen,
92- setIsOpen,
93- folded,
94- parentUid,
95- } : {
96- isOpen : boolean ;
97- setIsOpen : Dispatch < SetStateAction < boolean > > ;
98- folded : { uid ?: string ; value : boolean } ;
99- parentUid : string ;
100- } ) => {
101- if ( isOpen ) {
102- setIsOpen ( false ) ;
103- if ( folded . uid ) {
104- void deleteBlock ( folded . uid ) ;
105- folded . uid = undefined ;
106- folded . value = false ;
107- }
108- } else {
109- setIsOpen ( true ) ;
110- const newUid = window . roamAlphaAPI . util . generateUID ( ) ;
111- void createBlock ( {
112- parentUid,
113- node : { text : "Folded" , uid : newUid } ,
114- } ) ;
115- folded . uid = newUid ;
116- folded . value = true ;
117- }
118- } ;
119-
12078const SectionChildren = ( {
12179 childrenNodes,
12280 truncateAt,
@@ -156,31 +114,32 @@ const SectionChildren = ({
156114} ;
157115
158116const PersonalSectionItem = ( {
117+ sectionName,
159118 section,
119+ onToggleFolded,
160120} : {
161- section : LeftSidebarPersonalSectionConfig ;
121+ sectionName : string ;
122+ section : PersonalSection ;
123+ onToggleFolded : ( sectionName : string ) => void ;
162124} ) => {
163- const titleRef = parseReference ( section . text ) ;
164- const blockText = useMemo (
165- ( ) =>
166- titleRef . type === "block" ? getTextByBlockUid ( titleRef . uid ) : undefined ,
167- [ titleRef ] ,
168- ) ;
169- const truncateAt = section . settings ?. truncateResult . value ;
170- const [ isOpen , setIsOpen ] = useState < boolean > (
171- ! ! section . settings ?. folded . value || false ,
172- ) ;
125+ const truncateAt = section . Settings ?. [ "Truncate-result?" ] ;
126+ const [ isOpen , setIsOpen ] = useState < boolean > ( section . Settings ?. Folded ?? false ) ;
173127
174- const handleChevronClick = ( ) => {
175- if ( ! section . settings ) return ;
176-
177- toggleFoldedState ( {
178- isOpen,
179- setIsOpen,
180- folded : section . settings . folded ,
181- parentUid : section . settings . uid || "" ,
182- } ) ;
183- } ;
128+ useEffect ( ( ) => {
129+ setIsOpen ( section . Settings ?. Folded ?? false ) ;
130+ } , [ section . Settings ?. Folded ] ) ;
131+
132+ const handleChevronClick = useCallback ( ( ) => {
133+ const newState = ! isOpen ;
134+ setIsOpen ( newState ) ;
135+ onToggleFolded ( sectionName ) ;
136+ } , [ isOpen , sectionName , onToggleFolded ] ) ;
137+
138+ const childrenNodes = section . Children . map ( ( child ) => ( {
139+ uid : child . Page ,
140+ text : child . Page ,
141+ alias : child . Alias ? { value : child . Alias } : undefined ,
142+ } ) ) ;
184143
185144 return (
186145 < >
@@ -189,14 +148,14 @@ const PersonalSectionItem = ({
189148 < div
190149 className = "flex items-center"
191150 onClick = { ( ) => {
192- if ( ( section . children ? .length || 0 ) > 0 ) {
151+ if ( section . Children . length > 0 ) {
193152 handleChevronClick ( ) ;
194153 }
195154 } }
196155 >
197- { ( blockText || titleRef . display ) . toUpperCase ( ) }
156+ { sectionName . toUpperCase ( ) }
198157 </ div >
199- { ( section . children ? .length || 0 ) > 0 && (
158+ { section . Children . length > 0 && (
200159 < span
201160 className = "sidebar-title-button-chevron p-1"
202161 onClick = { handleChevronClick }
@@ -207,25 +166,37 @@ const PersonalSectionItem = ({
207166 </ div >
208167 </ div >
209168 < Collapse isOpen = { isOpen } >
210- < SectionChildren
211- childrenNodes = { section . children || [ ] }
212- truncateAt = { truncateAt }
213- />
169+ < SectionChildren childrenNodes = { childrenNodes } truncateAt = { truncateAt } />
214170 </ Collapse >
215171 </ >
216172 ) ;
217173} ;
218174
219- const PersonalSections = ( { config } : { config : LeftSidebarConfig } ) => {
220- const sections = config . personal . sections || [ ] ;
175+ const PersonalSections = ( ) => {
176+ const personalSettings = useLeftSidebarPersonalSettings ( ) ;
177+ const sections = Object . entries ( personalSettings ) ;
178+
179+ const handleToggleFolded = useCallback (
180+ ( sectionName : string ) => {
181+ const section = personalSettings [ sectionName ] ;
182+ if ( ! section ) return ;
183+ const newFolded = ! section . Settings . Folded ;
184+ setPersonalSetting ( [ "Left Sidebar" , sectionName , "Settings" , "Folded" ] , newFolded ) ;
185+ } ,
186+ [ personalSettings ] ,
187+ ) ;
221188
222189 if ( ! sections . length ) return null ;
223190
224191 return (
225192 < div className = "personal-left-sidebar-sections" >
226- { sections . map ( ( section ) => (
227- < div key = { section . uid } >
228- < PersonalSectionItem section = { section } />
193+ { sections . map ( ( [ name , section ] ) => (
194+ < div key = { name } >
195+ < PersonalSectionItem
196+ sectionName = { name }
197+ section = { section }
198+ onToggleFolded = { handleToggleFolded }
199+ />
229200 </ div >
230201 ) ) }
231202 </ div >
@@ -284,27 +255,6 @@ const GlobalSection = () => {
284255 ) ;
285256} ;
286257
287- export const useConfig = ( ) => {
288- const [ config , setConfig ] = useState (
289- ( ) => getFormattedConfigTree ( ) . leftSidebar ,
290- ) ;
291- useEffect ( ( ) => {
292- const handleUpdate = ( ) => {
293- setConfig ( getFormattedConfigTree ( ) . leftSidebar ) ;
294- } ;
295- const unsubscribe = subscribe ( handleUpdate ) ;
296- return ( ) => {
297- unsubscribe ( ) ;
298- } ;
299- } , [ ] ) ;
300- return { config, setConfig } ;
301- } ;
302-
303- export const refreshAndNotify = ( ) => {
304- refreshConfigTree ( ) ;
305- notify ( ) ;
306- } ;
307-
308258const FavoritesPopover = ( { onloadArgs } : { onloadArgs : OnloadArgs } ) => {
309259 const [ isMenuOpen , setIsMenuOpen ] = useState ( false ) ;
310260 const menuTriggerRef = useRef < HTMLSpanElement | null > ( null ) ;
@@ -416,13 +366,11 @@ const FavoritesPopover = ({ onloadArgs }: { onloadArgs: OnloadArgs }) => {
416366} ;
417367
418368const LeftSidebarView = ( { onloadArgs } : { onloadArgs : OnloadArgs } ) => {
419- const { config } = useConfig ( ) ;
420-
421369 return (
422370 < >
423371 < FavoritesPopover onloadArgs = { onloadArgs } />
424372 < GlobalSection />
425- < PersonalSections config = { config } />
373+ < PersonalSections />
426374 </ >
427375 ) ;
428376} ;
@@ -435,31 +383,23 @@ const migrateFavorites = async () => {
435383 const configPageUid = getPageUidByPageTitle ( DISCOURSE_CONFIG_PAGE_TITLE ) ;
436384 if ( ! configPageUid ) return ;
437385
438- let leftSidebarUid = config . uid ;
439- if ( leftSidebarUid ) {
440- const leftSidebarTree = getBasicTreeByParentUid ( leftSidebarUid ) ;
441- const hasAnyPersonalSection = leftSidebarTree . some ( ( node ) =>
442- node . text . endsWith ( "/Personal-Section" ) ,
443- ) ;
444- if ( hasAnyPersonalSection ) {
445- await createBlock ( {
446- parentUid : leftSidebarUid ,
447- node : { text : "Favorites Migrated" } ,
448- } ) ;
449- refreshConfigTree ( ) ;
450- return ;
451- }
452- }
453-
454386 const results = window . roamAlphaAPI . q ( `
455- [:find ?uid
387+ [:find ?uid
456388 :where [?e :page/sidebar]
457389 [?e :block/uid ?uid]]
458390 ` ) ;
459- const favorites = ( results as string [ ] [ ] ) . map ( ( [ uid ] ) => ( {
460- uid,
461- } ) ) ;
391+ const favorites = ( results as string [ ] [ ] ) . map ( ( [ uid ] ) => uid ) ;
392+
393+ const currentSettings = getGlobalSetting < LeftSidebarGlobalSettings > ( [ "Left Sidebar" ] ) ;
394+ const existingChildren = new Set ( currentSettings ?. Children || [ ] ) ;
395+ const newFavorites = favorites . filter ( ( uid ) => ! existingChildren . has ( uid ) ) ;
396+
397+ if ( newFavorites . length > 0 ) {
398+ const mergedChildren = [ ...( currentSettings ?. Children || [ ] ) , ...newFavorites ] ;
399+ setGlobalSetting ( [ "Left Sidebar" , "Children" ] , mergedChildren ) ;
400+ }
462401
402+ let leftSidebarUid = config . uid ;
463403 if ( ! leftSidebarUid ) {
464404 const tree = getBasicTreeByParentUid ( configPageUid ) ;
465405 const found = tree . find ( ( n ) => n . text === "Left Sidebar" ) ;
@@ -473,47 +413,6 @@ const migrateFavorites = async () => {
473413 }
474414 }
475415
476- let globalSectionUid = config . global . uid ;
477- if ( ! globalSectionUid ) {
478- const tree = getBasicTreeByParentUid ( leftSidebarUid ) ;
479- const found = tree . find ( ( n ) => n . text === "Global-Section" ) ;
480- if ( found ) {
481- globalSectionUid = found . uid ;
482- } else {
483- globalSectionUid = await createBlock ( {
484- parentUid : leftSidebarUid ,
485- node : { text : "Global-Section" } ,
486- } ) ;
487- }
488- }
489-
490- let childrenUid = config . global . childrenUid ;
491- if ( ! childrenUid ) {
492- const tree = getBasicTreeByParentUid ( globalSectionUid ) ;
493- const found = tree . find ( ( n ) => n . text === "Children" ) ;
494- if ( found ) {
495- childrenUid = found . uid ;
496- } else {
497- childrenUid = await createBlock ( {
498- parentUid : globalSectionUid ,
499- node : { text : "Children" } ,
500- } ) ;
501- }
502- }
503-
504- const childrenTree = getBasicTreeByParentUid ( childrenUid ) ;
505- const existingTexts = new Set ( childrenTree . map ( ( c ) => c . text ) ) ;
506- const newFavorites = favorites . filter ( ( { uid } ) => ! existingTexts . has ( uid ) ) ;
507-
508- if ( newFavorites . length > 0 ) {
509- await Promise . all (
510- newFavorites . map ( ( { uid } ) =>
511- createBlock ( { parentUid : childrenUid , node : { text : uid } } ) ,
512- ) ,
513- ) ;
514- refreshAndNotify ( ) ;
515- }
516-
517416 await createBlock ( {
518417 parentUid : leftSidebarUid ,
519418 node : { text : "Favorites Migrated" } ,
@@ -539,7 +438,6 @@ export const mountLeftSidebar = async (
539438 let root = wrapper . querySelector ( `#${ id } ` ) as HTMLDivElement ;
540439 if ( ! root ) {
541440 await migrateFavorites ( ) ;
542- await migrateLeftSidebarSettings ( ) ;
543441 wrapper . innerHTML = "" ;
544442 root = document . createElement ( "div" ) ;
545443 root . id = id ;
0 commit comments