mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	launcher improvements
This commit is contained in:
		| @@ -15,14 +15,14 @@ export default class ShortcutComponent extends Component { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bindNoteShortcutHandler(attr) { |     bindNoteShortcutHandler(label) { | ||||||
|         const handler = () => appContext.tabManager.getActiveContext().setNote(attr.noteId); |         const handler = () => appContext.tabManager.getActiveContext().setNote(label.noteId); | ||||||
|         const namespace = attr.attributeId; |         const namespace = label.attributeId; | ||||||
|  |  | ||||||
|         if (attr.isDeleted) { |         if (label.isDeleted) { | ||||||
|             shortcutService.removeGlobalShortcut(namespace); |             shortcutService.removeGlobalShortcut(namespace); | ||||||
|         } else { |         } else { | ||||||
|             shortcutService.bindGlobalShortcut(attr.value, handler, namespace); |             shortcutService.bindGlobalShortcut(label.value, handler, namespace); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								src/public/app/doc_notes/launchbar_command_launcher.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/public/app/doc_notes/launchbar_command_launcher.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | <p>Keyboard shortcut for this launcher action can be configured in Options -> Shortcuts.</p> | ||||||
| @@ -36,9 +36,9 @@ export default class LauncherContextMenu { | |||||||
|         const canBeReset = note.noteId.startsWith("lb_"); |         const canBeReset = note.noteId.startsWith("lb_"); | ||||||
|  |  | ||||||
|         return [ |         return [ | ||||||
|             (isVisibleRoot || isAvailableRoot) ? { title: 'Add note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null, |             (isVisibleRoot || isAvailableRoot) ? { title: 'Add a note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null, | ||||||
|             (isVisibleRoot || isAvailableRoot) ? { title: 'Add script launcher', command: 'addScriptLauncher', uiIcon: "bx bx-plus" } : null, |             (isVisibleRoot || isAvailableRoot) ? { title: 'Add a script launcher', command: 'addScriptLauncher', uiIcon: "bx bx-plus" } : null, | ||||||
|             (isVisibleRoot || isAvailableRoot) ? { title: 'Add widget launcher', command: 'addWidgetLauncher', uiIcon: "bx bx-plus" } : null, |             (isVisibleRoot || isAvailableRoot) ? { title: 'Add a custom widget', command: 'addWidgetLauncher', uiIcon: "bx bx-plus" } : null, | ||||||
|             (isVisibleRoot || isAvailableRoot) ? { title: 'Add spacer', command: 'addSpacerLauncher', uiIcon: "bx bx-plus" } : null, |             (isVisibleRoot || isAvailableRoot) ? { title: 'Add spacer', command: 'addSpacerLauncher', uiIcon: "bx bx-plus" } : null, | ||||||
|             (isVisibleRoot || isAvailableRoot) ? { title: "----" } : null, |             (isVisibleRoot || isAvailableRoot) ? { title: "----" } : null, | ||||||
|             { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", enabled: canBeDeleted }, |             { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", enabled: canBeDeleted }, | ||||||
| @@ -54,7 +54,7 @@ export default class LauncherContextMenu { | |||||||
|     async selectMenuItemHandler({command}) { |     async selectMenuItemHandler({command}) { | ||||||
|         if (command === 'resetLauncher') { |         if (command === 'resetLauncher') { | ||||||
|             const confirmed = await dialogService.confirm(`Do you really want to reset "${this.node.title}"?  |             const confirmed = await dialogService.confirm(`Do you really want to reset "${this.node.title}"?  | ||||||
|                        All data / settings in this launcher (and its children) will be lost  |                        All data / settings in this note (and its children) will be lost  | ||||||
|                        and the launcher will be returned to its original location.`); |                        and the launcher will be returned to its original location.`); | ||||||
|  |  | ||||||
|             if (confirmed) { |             if (confirmed) { | ||||||
|   | |||||||
							
								
								
									
										149
									
								
								src/public/app/widgets/containers/launcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/public/app/widgets/containers/launcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | |||||||
|  | import ButtonWidget from "../buttons/button_widget.js"; | ||||||
|  | import dialogService from "../../services/dialog.js"; | ||||||
|  | import appContext from "../../components/app_context.js"; | ||||||
|  | import CalendarWidget from "../buttons/calendar.js"; | ||||||
|  | import SpacerWidget from "../spacer.js"; | ||||||
|  | import BookmarkButtons from "../bookmark_buttons.js"; | ||||||
|  | import ProtectedSessionStatusWidget from "../buttons/protected_session_status.js"; | ||||||
|  | import SyncStatusWidget from "../sync_status.js"; | ||||||
|  | import BackInHistoryButtonWidget from "../buttons/history/history_back.js"; | ||||||
|  | import ForwardInHistoryButtonWidget from "../buttons/history/history_forward.js"; | ||||||
|  | import BasicWidget from "../basic_widget.js"; | ||||||
|  | import shortcutService from "../../services/shortcuts.js"; | ||||||
|  |  | ||||||
|  | export default class LauncherWidget extends BasicWidget { | ||||||
|  |     constructor(launcherNote) { | ||||||
|  |         super(); | ||||||
|  |  | ||||||
|  |         if (launcherNote.type !== 'launcher') { | ||||||
|  |             throw new Error(`Note '${this.note.noteId}' '${this.note.title}' is not a launcher even though it's in the launcher subtree`); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.note = launcherNote; | ||||||
|  |         this.innerWidget = null; | ||||||
|  |         this.handler = null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     isEnabled() { | ||||||
|  |         return this.innerWidget.isEnabled(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     doRender() { | ||||||
|  |         this.$widget = this.innerWidget.render(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async initLauncher() { | ||||||
|  |         const launcherType = this.note.getLabelValue("launcherType"); | ||||||
|  |  | ||||||
|  |         if (launcherType === 'command') { | ||||||
|  |             this.handler = () => this.triggerCommand(this.note.getLabelValue("command")); | ||||||
|  |  | ||||||
|  |             this.innerWidget = new ButtonWidget() | ||||||
|  |                 .title(this.note.title) | ||||||
|  |                 .icon(this.note.getIcon()) | ||||||
|  |                 .onClick(this.handler); | ||||||
|  |         } else if (launcherType === 'note') { | ||||||
|  |             // we're intentionally displaying the launcher title and icon instead of the target | ||||||
|  |             // e.g. you want to make launchers to 2 mermaid diagrams which both have mermaid icon (ok), | ||||||
|  |             // but on the launchpad you want them distinguishable. | ||||||
|  |             // for titles, the note titles may follow a different scheme than maybe desirable on the launchpad | ||||||
|  |             // another reason is the discrepancy between what user sees on the launchpad and in the config (esp. icons). | ||||||
|  |             // The only (but major) downside is more work in setting up the typical case where you actually want to have both title and icon in sync. | ||||||
|  |  | ||||||
|  |             this.handler = () => { | ||||||
|  |                 const targetNoteId = this.note.getRelationValue('targetNote'); | ||||||
|  |  | ||||||
|  |                 if (!targetNoteId) { | ||||||
|  |                     dialogService.info("This launcher doesn't define target note."); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 appContext.tabManager.openTabWithNoteWithHoisting(targetNoteId, true) | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             this.innerWidget = new ButtonWidget() | ||||||
|  |                 .title(this.note.title) | ||||||
|  |                 .icon(this.note.getIcon()) | ||||||
|  |                 .onClick(this.handler); | ||||||
|  |         } else if (launcherType === 'script') { | ||||||
|  |             this.handler = async () => { | ||||||
|  |                 const script = await this.note.getRelationTarget('script'); | ||||||
|  |  | ||||||
|  |                 await script.executeScript(); | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             this.innerWidget = new ButtonWidget() | ||||||
|  |                 .title(this.note.title) | ||||||
|  |                 .icon(this.note.getIcon()) | ||||||
|  |                 .onClick(this.handler); | ||||||
|  |         } else if (launcherType === 'customWidget') { | ||||||
|  |             const widget = await this.note.getRelationTarget('widget'); | ||||||
|  |  | ||||||
|  |             if (widget) { | ||||||
|  |                 this.innerWidget = await widget.executeScript(); | ||||||
|  |             } else { | ||||||
|  |                 throw new Error(`Could not initiate custom widget of launcher '${this.note.noteId}' '${this.note.title}`); | ||||||
|  |             } | ||||||
|  |         } else if (launcherType === 'builtinWidget') { | ||||||
|  |             const builtinWidget = this.note.getLabelValue("builtinWidget"); | ||||||
|  |  | ||||||
|  |             if (builtinWidget) { | ||||||
|  |                 if (builtinWidget === 'calendar') { | ||||||
|  |                     this.innerWidget = new CalendarWidget(this.note.title, this.note.getIcon()); | ||||||
|  |                 } else if (builtinWidget === 'spacer') { | ||||||
|  |                     // || has to be inside since 0 is a valid value | ||||||
|  |                     const baseSize = parseInt(this.note.getLabelValue("baseSize") || "40"); | ||||||
|  |                     const growthFactor = parseInt(this.note.getLabelValue("growthFactor") || "100"); | ||||||
|  |  | ||||||
|  |                     this.innerWidget = new SpacerWidget(baseSize, growthFactor); | ||||||
|  |                 } else if (builtinWidget === 'bookmarks') { | ||||||
|  |                     this.innerWidget = new BookmarkButtons(); | ||||||
|  |                 } else if (builtinWidget === 'protectedSession') { | ||||||
|  |                     this.innerWidget = new ProtectedSessionStatusWidget(); | ||||||
|  |                 } else if (builtinWidget === 'syncStatus') { | ||||||
|  |                     this.innerWidget = new SyncStatusWidget(); | ||||||
|  |                 } else if (builtinWidget === 'backInHistoryButton') { | ||||||
|  |                     this.innerWidget = new BackInHistoryButtonWidget(); | ||||||
|  |                 } else if (builtinWidget === 'forwardInHistoryButton') { | ||||||
|  |                     this.innerWidget = new ForwardInHistoryButtonWidget(); | ||||||
|  |                 } else { | ||||||
|  |                     throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${this.note.noteId} "${this.note.title}"`); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             throw new Error(`Unrecognized launcher type '${launcherType}' for launcher '${this.note.noteId}' title ${this.note.title}`); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!this.innerWidget) { | ||||||
|  |             throw new Error(`Unknown initialization error for note '${this.note.noteId}', title '${this.note.title}'`); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (const label of this.note.getLabels('keyboardShortcut')) { | ||||||
|  |             this.bindNoteShortcutHandler(label); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.child(this.innerWidget); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bindNoteShortcutHandler(label) { | ||||||
|  |         if (!this.handler) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const namespace = label.attributeId; | ||||||
|  |  | ||||||
|  |         if (label.isDeleted) { | ||||||
|  |             shortcutService.removeGlobalShortcut(namespace); | ||||||
|  |         } else { | ||||||
|  |             shortcutService.bindGlobalShortcut(label.value, this.handler, namespace); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     entitiesReloadedEvent({loadResults}) { | ||||||
|  |         for (const attr of loadResults.getAttributes()) { | ||||||
|  |             if (attr.noteId === this.note.noteId && attr.type === 'label' && attr.name === 'keyboardShortcut') { | ||||||
|  |                 this.bindNoteShortcutHandler(attr); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,15 +1,7 @@ | |||||||
| import FlexContainer from "./flex_container.js"; | import FlexContainer from "./flex_container.js"; | ||||||
| import froca from "../../services/froca.js"; | import froca from "../../services/froca.js"; | ||||||
| import ButtonWidget from "../buttons/button_widget.js"; |  | ||||||
| import CalendarWidget from "../buttons/calendar.js"; |  | ||||||
| import appContext from "../../components/app_context.js"; | import appContext from "../../components/app_context.js"; | ||||||
| import SpacerWidget from "../spacer.js"; | import LauncherWidget from "./launcher.js"; | ||||||
| import BookmarkButtons from "../bookmark_buttons.js"; |  | ||||||
| import ProtectedSessionStatusWidget from "../buttons/protected_session_status.js"; |  | ||||||
| import SyncStatusWidget from "../sync_status.js"; |  | ||||||
| import BackInHistoryButtonWidget from "../buttons/history/history_back.js"; |  | ||||||
| import ForwardInHistoryButtonWidget from "../buttons/history/history_forward.js"; |  | ||||||
| import dialogService from "../../services/dialog.js"; |  | ||||||
|  |  | ||||||
| export default class LauncherContainer extends FlexContainer { | export default class LauncherContainer extends FlexContainer { | ||||||
|     constructor() { |     constructor() { | ||||||
| @@ -35,7 +27,16 @@ export default class LauncherContainer extends FlexContainer { | |||||||
|  |  | ||||||
|         await Promise.allSettled( |         await Promise.allSettled( | ||||||
|             (await visibleLaunchersRoot.getChildNotes()) |             (await visibleLaunchersRoot.getChildNotes()) | ||||||
|                 .map(launcher => this.initLauncher(launcher)) |                 .map(async launcherNote => { | ||||||
|  |                     try { | ||||||
|  |                         const launcherWidget = new LauncherWidget(launcherNote); | ||||||
|  |                         await launcherWidget.initLauncher(); | ||||||
|  |                         this.child(launcherWidget); | ||||||
|  |                     } | ||||||
|  |                     catch (e) { | ||||||
|  |                         console.error(e.message); | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         this.$widget.empty(); |         this.$widget.empty(); | ||||||
| @@ -59,93 +60,6 @@ export default class LauncherContainer extends FlexContainer { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async initLauncher(launcher) { |  | ||||||
|         try { |  | ||||||
|             if (launcher.type !== 'launcher') { |  | ||||||
|                 console.warn(`Note ${launcher.noteId} is not a launcher even though it's in launcher subtree`); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             const launcherType = launcher.getLabelValue("launcherType"); |  | ||||||
|  |  | ||||||
|             if (launcherType === 'command') { |  | ||||||
|                 this.child(new ButtonWidget() |  | ||||||
|                     .title(launcher.title) |  | ||||||
|                     .icon(launcher.getIcon()) |  | ||||||
|                     .command(launcher.getLabelValue("command"))); |  | ||||||
|             } else if (launcherType === 'note') { |  | ||||||
|                 // we're intentionally displaying the launcher title and icon instead of the target |  | ||||||
|                 // e.g. you want to make launchers to 2 mermaid diagrams which both have mermaid icon (ok), |  | ||||||
|                 // but on the launchpad you want them distinguishable. |  | ||||||
|                 // for titles, the note titles may follow a different scheme than maybe desirable on the launchpad |  | ||||||
|                 // another reason is the discrepancy between what user sees on the launchpad and in the config (esp. icons). |  | ||||||
|                 // The only (but major) downside is more work in setting up the typical case where you actually want to have both title and icon in sync. |  | ||||||
|  |  | ||||||
|                 this.child(new ButtonWidget() |  | ||||||
|                     .title(launcher.title) |  | ||||||
|                     .icon(launcher.getIcon()) |  | ||||||
|                     .onClick(() => { |  | ||||||
|                         const targetNoteId = launcher.getRelationValue('targetNote'); |  | ||||||
|  |  | ||||||
|                         if (!targetNoteId) { |  | ||||||
|                             dialogService.info("This launcher doesn't define target note."); |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         appContext.tabManager.openTabWithNoteWithHoisting(targetNoteId, true) |  | ||||||
|                     })); |  | ||||||
|             } else if (launcherType === 'script') { |  | ||||||
|                 this.child(new ButtonWidget() |  | ||||||
|                     .title(launcher.title) |  | ||||||
|                     .icon(launcher.getIcon()) |  | ||||||
|                     .onClick(async () => { |  | ||||||
|                         const script = await launcher.getRelationTarget('script'); |  | ||||||
|  |  | ||||||
|                         await script.executeScript(); |  | ||||||
|                     })); |  | ||||||
|             } else if (launcherType === 'customWidget') { |  | ||||||
|                 const widget = await launcher.getRelationTarget('widget'); |  | ||||||
|  |  | ||||||
|                 if (widget) { |  | ||||||
|                     const res = await widget.executeScript(); |  | ||||||
|  |  | ||||||
|                     this.child(res); |  | ||||||
|                 } |  | ||||||
|             } else if (launcherType === 'builtinWidget') { |  | ||||||
|                 const builtinWidget = launcher.getLabelValue("builtinWidget"); |  | ||||||
|  |  | ||||||
|                 if (builtinWidget) { |  | ||||||
|                     if (builtinWidget === 'calendar') { |  | ||||||
|                         this.child(new CalendarWidget(launcher.title, launcher.getIcon())); |  | ||||||
|                     } else if (builtinWidget === 'spacer') { |  | ||||||
|                         // || has to be inside since 0 is a valid value |  | ||||||
|                         const baseSize = parseInt(launcher.getLabelValue("baseSize") || "40"); |  | ||||||
|                         const growthFactor = parseInt(launcher.getLabelValue("growthFactor") || "100"); |  | ||||||
|  |  | ||||||
|                         this.child(new SpacerWidget(baseSize, growthFactor)); |  | ||||||
|                     } else if (builtinWidget === 'bookmarks') { |  | ||||||
|                         this.child(new BookmarkButtons()); |  | ||||||
|                     } else if (builtinWidget === 'protectedSession') { |  | ||||||
|                         this.child(new ProtectedSessionStatusWidget()); |  | ||||||
|                     } else if (builtinWidget === 'syncStatus') { |  | ||||||
|                         this.child(new SyncStatusWidget()); |  | ||||||
|                     } else if (builtinWidget === 'backInHistoryButton') { |  | ||||||
|                         this.child(new BackInHistoryButtonWidget()); |  | ||||||
|                     } else if (builtinWidget === 'forwardInHistoryButton') { |  | ||||||
|                         this.child(new ForwardInHistoryButtonWidget()); |  | ||||||
|                     } else { |  | ||||||
|                         console.warn(`Unrecognized builtin widget ${builtinWidget} for launcher ${launcher.noteId} "${launcher.title}"`); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 console.warn(`Unrecognized launcher type ${launcherType} for launcher '${launcher.noteId}' title ${launcher.title}`); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         catch (e) { |  | ||||||
|             console.error(`Initialization of launcher '${launcher.noteId}' with title '${launcher.title}' failed with error: ${e.message} ${e.stack}`); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     entitiesReloadedEvent({loadResults}) { |     entitiesReloadedEvent({loadResults}) { | ||||||
|         if (loadResults.getNoteIds().find(noteId => froca.notes[noteId]?.isLaunchBarConfig()) |         if (loadResults.getNoteIds().find(noteId => froca.notes[noteId]?.isLaunchBarConfig()) | ||||||
|             || loadResults.getBranches().find(branch => branch.parentNoteId.startsWith("lb_")) |             || loadResults.getBranches().find(branch => branch.parentNoteId.startsWith("lb_")) | ||||||
|   | |||||||
| @@ -8,10 +8,10 @@ function getKeyboardActions() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function getShortcutsForNotes() { | function getShortcutsForNotes() { | ||||||
|     const attrs = becca.findAttributes('label', 'keyboardShortcut'); |     const labels = becca.findAttributes('label', 'keyboardShortcut'); | ||||||
|  |  | ||||||
|     // launchers have different handling |     // launchers have different handling | ||||||
|     return attrs.filter(attr => becca.getNote(attr.noteId)?.type !== 'launcher'); |     return labels.filter(attr => becca.getNote(attr.noteId)?.type !== 'launcher'); | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
| @@ -474,16 +474,14 @@ function createLauncherTemplates() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(LBTPL_BASE in becca.notes)) { |     if (!(LBTPL_BASE in becca.notes)) { | ||||||
|         const tpl = noteService.createNewNote({ |         noteService.createNewNote({ | ||||||
|             branchId: LBTPL_BASE, |             branchId: LBTPL_BASE, | ||||||
|             noteId: LBTPL_BASE, |             noteId: LBTPL_BASE, | ||||||
|             title: 'Launch bar base launcher', |             title: 'Launch bar base launcher', | ||||||
|             type: 'doc', |             type: 'doc', | ||||||
|             content: '', |             content: '', | ||||||
|             parentNoteId: getHiddenRoot().noteId |             parentNoteId: getHiddenRoot().noteId | ||||||
|         }).note; |         }); | ||||||
|  |  | ||||||
|         tpl.addLabel('label:keyboardLauncher', 'promoted,text'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(LBTPL_COMMAND in becca.notes)) { |     if (!(LBTPL_COMMAND in becca.notes)) { | ||||||
| @@ -498,6 +496,7 @@ function createLauncherTemplates() { | |||||||
|  |  | ||||||
|         tpl.addRelation('template', LBTPL_BASE); |         tpl.addRelation('template', LBTPL_BASE); | ||||||
|         tpl.addLabel('launcherType', 'command'); |         tpl.addLabel('launcherType', 'command'); | ||||||
|  |         tpl.addLabel('docName', 'launchbar_command_launcher'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(LBTPL_NOTE_LAUNCHER in becca.notes)) { |     if (!(LBTPL_NOTE_LAUNCHER in becca.notes)) { | ||||||
| @@ -514,6 +513,7 @@ function createLauncherTemplates() { | |||||||
|         tpl.addLabel('launcherType', 'note'); |         tpl.addLabel('launcherType', 'note'); | ||||||
|         tpl.addLabel('relation:targetNote', 'promoted'); |         tpl.addLabel('relation:targetNote', 'promoted'); | ||||||
|         tpl.addLabel('docName', 'launchbar_note_launcher'); |         tpl.addLabel('docName', 'launchbar_note_launcher'); | ||||||
|  |         tpl.addLabel('label:keyboardShortcut', 'promoted,text'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(LBTPL_SCRIPT in becca.notes)) { |     if (!(LBTPL_SCRIPT in becca.notes)) { | ||||||
| @@ -530,6 +530,7 @@ function createLauncherTemplates() { | |||||||
|         tpl.addLabel('launcherType', 'script'); |         tpl.addLabel('launcherType', 'script'); | ||||||
|         tpl.addLabel('relation:script', 'promoted'); |         tpl.addLabel('relation:script', 'promoted'); | ||||||
|         tpl.addLabel('docName', 'launchbar_script_launcher'); |         tpl.addLabel('docName', 'launchbar_script_launcher'); | ||||||
|  |         tpl.addLabel('label:keyboardShortcut', 'promoted,text'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(LBTPL_BUILTIN_WIDGET in becca.notes)) { |     if (!(LBTPL_BUILTIN_WIDGET in becca.notes)) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user