@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks"
22import { useNoteContext , useNoteProperty , useStaticTooltipWithKeyboardShortcut , useTriliumEvents } from "../react/hooks" ;
33import "./style.css" ;
44
5- import { numberObjectsInPlace } from "../../services/utils" ;
5+ import { Indexed , numberObjectsInPlace } from "../../services/utils" ;
66import { EventNames } from "../../components/app_context" ;
77import NoteActions from "./NoteActions" ;
88import { KeyboardActionNames } from "@triliumnext/commons" ;
@@ -11,30 +11,47 @@ import { TabConfiguration, TitleContext } from "./ribbon-interface";
1111
1212const TAB_CONFIGURATION = numberObjectsInPlace < TabConfiguration > ( RIBBON_TAB_DEFINITIONS ) ;
1313
14+ interface ComputedTab extends Indexed < TabConfiguration > {
15+ shouldShow : boolean ;
16+ }
17+
1418export default function Ribbon ( ) {
15- const { note, ntxId, hoistedNoteId, notePath, noteContext, componentId } = useNoteContext ( ) ;
19+ const { note, ntxId, hoistedNoteId, notePath, noteContext, componentId, isReadOnlyTemporarilyDisabled } = useNoteContext ( ) ;
1620 const noteType = useNoteProperty ( note , "type" ) ;
17- const titleContext : TitleContext = { note } ;
1821 const [ activeTabIndex , setActiveTabIndex ] = useState < number | undefined > ( ) ;
19- const computedTabs = useMemo (
20- ( ) => TAB_CONFIGURATION . map ( tab => {
21- const shouldShow = typeof tab . show === "boolean" ? tab . show : tab . show ?.( titleContext ) ;
22- return {
22+ const [ computedTabs , setComputedTabs ] = useState < ComputedTab [ ] > ( ) ;
23+ const titleContext : TitleContext = useMemo ( ( ) => ( {
24+ note,
25+ noteContext
26+ } ) , [ note , noteContext ] ) ;
27+
28+ async function refresh ( ) {
29+ const computedTabs : ComputedTab [ ] = [ ] ;
30+ for ( const tab of TAB_CONFIGURATION ) {
31+ const shouldShow = await shouldShowTab ( tab . show , titleContext ) ;
32+ computedTabs . push ( {
2333 ...tab ,
24- shouldShow
25- }
26- } ) ,
27- [ titleContext , note , noteType ] ) ;
34+ shouldShow : ! ! shouldShow
35+ } ) ;
36+ }
37+ setComputedTabs ( computedTabs ) ;
38+ }
39+
40+ useEffect ( ( ) => {
41+ refresh ( ) ;
42+ } , [ note , noteType , isReadOnlyTemporarilyDisabled ] ) ;
2843
2944 // Automatically activate the first ribbon tab that needs to be activated whenever a note changes.
3045 useEffect ( ( ) => {
46+ if ( ! computedTabs ) return ;
3147 const tabToActivate = computedTabs . find ( tab => tab . shouldShow && ( typeof tab . activate === "boolean" ? tab . activate : tab . activate ?.( titleContext ) ) ) ;
3248 setActiveTabIndex ( tabToActivate ?. index ) ;
33- } , [ note ?. noteId ] ) ;
49+ } , [ computedTabs , note ?. noteId ] ) ;
3450
3551 // Register keyboard shortcuts.
3652 const eventsToListenTo = useMemo ( ( ) => TAB_CONFIGURATION . filter ( config => config . toggleCommand ) . map ( config => config . toggleCommand ) as EventNames [ ] , [ ] ) ;
3753 useTriliumEvents ( eventsToListenTo , useCallback ( ( e , toggleCommand ) => {
54+ if ( ! computedTabs ) return ;
3855 const correspondingTab = computedTabs . find ( tab => tab . toggleCommand === toggleCommand ) ;
3956 if ( correspondingTab ) {
4057 if ( activeTabIndex !== correspondingTab . index ) {
@@ -51,7 +68,7 @@ export default function Ribbon() {
5168 < >
5269 < div className = "ribbon-top-row" >
5370 < div className = "ribbon-tab-container" >
54- { computedTabs . map ( ( { title, icon, index, toggleCommand, shouldShow } ) => (
71+ { computedTabs && computedTabs . map ( ( { title, icon, index, toggleCommand, shouldShow } ) => (
5572 shouldShow && < RibbonTab
5673 icon = { icon }
5774 title = { typeof title === "string" ? title : title ( titleContext ) }
@@ -74,7 +91,7 @@ export default function Ribbon() {
7491 </ div >
7592
7693 < div className = "ribbon-body-container" >
77- { computedTabs . map ( tab => {
94+ { computedTabs && computedTabs . map ( tab => {
7895 const isActive = tab . index === activeTabIndex ;
7996 if ( ! isActive && ! tab . stayInDom ) {
8097 return ;
@@ -129,3 +146,9 @@ function RibbonTab({ icon, title, active, onClick, toggleCommand }: { icon: stri
129146 )
130147}
131148
149+ export async function shouldShowTab ( showConfig : boolean | ( ( context : TitleContext ) => Promise < boolean | null | undefined > | boolean | null | undefined ) , context : TitleContext ) {
150+ if ( showConfig === null || showConfig === undefined ) return true ;
151+ if ( typeof showConfig === "boolean" ) return showConfig ;
152+ if ( "then" in showConfig ) return await showConfig ( context ) ;
153+ return showConfig ( context ) ;
154+ }
0 commit comments