mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	can't allow opening externally on attachment list
This commit is contained in:
		
							parent
							
								
									cc02546ed3
								
							
						
					
					
						commit
						8284c673f9
					
				@ -76,6 +76,10 @@ class AppContext extends Component {
 | 
			
		||||
        $("body").append($renderedWidget);
 | 
			
		||||
 | 
			
		||||
        $renderedWidget.on('click', "[data-trigger-command]", function() {
 | 
			
		||||
            if ($(this).hasClass("disabled")) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const commandName = $(this).attr('data-trigger-command');
 | 
			
		||||
            const $component = $(this).closest(".component");
 | 
			
		||||
            const component = $component.prop("component");
 | 
			
		||||
 | 
			
		||||
@ -4,11 +4,9 @@ import noteTooltipService from './services/note_tooltip.js';
 | 
			
		||||
import bundleService from "./services/bundle.js";
 | 
			
		||||
import noteAutocompleteService from './services/note_autocomplete.js';
 | 
			
		||||
import macInit from './services/mac_init.js';
 | 
			
		||||
import contextMenu from "./menus/context_menu.js";
 | 
			
		||||
import electronContextMenu from "./menus/electron_context_menu.js";
 | 
			
		||||
import DesktopLayout from "./layouts/desktop_layout.js";
 | 
			
		||||
import glob from "./services/glob.js";
 | 
			
		||||
import zoomService from './components/zoom.js';
 | 
			
		||||
import options from "./services/options.js";
 | 
			
		||||
 | 
			
		||||
bundleService.getWidgetBundlesByParent().then(widgetBundles => {
 | 
			
		||||
    appContext.setLayout(new DesktopLayout(widgetBundles));
 | 
			
		||||
@ -18,9 +16,8 @@ bundleService.getWidgetBundlesByParent().then(widgetBundles => {
 | 
			
		||||
glob.setupGlobs();
 | 
			
		||||
 | 
			
		||||
if (utils.isElectron()) {
 | 
			
		||||
    utils.dynamicRequire('electron').ipcRenderer.on('globalShortcut', async function(event, actionName) {
 | 
			
		||||
        appContext.triggerCommand(actionName);
 | 
			
		||||
    });
 | 
			
		||||
    utils.dynamicRequire('electron').ipcRenderer.on('globalShortcut',
 | 
			
		||||
        async (event, actionName) => appContext.triggerCommand(actionName));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macInit.init();
 | 
			
		||||
@ -30,131 +27,5 @@ noteTooltipService.setupGlobalTooltip();
 | 
			
		||||
noteAutocompleteService.init();
 | 
			
		||||
 | 
			
		||||
if (utils.isElectron()) {
 | 
			
		||||
    const electron = utils.dynamicRequire('electron');
 | 
			
		||||
 | 
			
		||||
    const remote = utils.dynamicRequire('@electron/remote');
 | 
			
		||||
    const {webContents} = remote.getCurrentWindow();
 | 
			
		||||
 | 
			
		||||
    webContents.on('context-menu', (event, params) => {
 | 
			
		||||
        const {editFlags} = params;
 | 
			
		||||
        const hasText = params.selectionText.trim().length > 0;
 | 
			
		||||
        const isMac = process.platform === "darwin";
 | 
			
		||||
        const platformModifier = isMac ? 'Meta' : 'Ctrl';
 | 
			
		||||
 | 
			
		||||
        const items = [];
 | 
			
		||||
 | 
			
		||||
        if (params.misspelledWord) {
 | 
			
		||||
            for (const suggestion of params.dictionarySuggestions) {
 | 
			
		||||
                items.push({
 | 
			
		||||
                    title: suggestion,
 | 
			
		||||
                    command: "replaceMisspelling",
 | 
			
		||||
                    spellingSuggestion: suggestion,
 | 
			
		||||
                    uiIcon: "bx bx-empty"
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            items.push({
 | 
			
		||||
                title: `Add "${params.misspelledWord}" to dictionary`,
 | 
			
		||||
                uiIcon: "bx bx-plus",
 | 
			
		||||
                handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            items.push({ title: `----` });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canCut && hasText,
 | 
			
		||||
                title: `Cut <kbd>${platformModifier}+X`,
 | 
			
		||||
                uiIcon: "bx bx-cut",
 | 
			
		||||
                handler: () => webContents.cut()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable || hasText) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canCopy && hasText,
 | 
			
		||||
                title: `Copy <kbd>${platformModifier}+C`,
 | 
			
		||||
                uiIcon: "bx bx-copy",
 | 
			
		||||
                handler: () => webContents.copy()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') {
 | 
			
		||||
            items.push({
 | 
			
		||||
                title: `Copy link`,
 | 
			
		||||
                uiIcon: "bx bx-copy",
 | 
			
		||||
                handler: () => {
 | 
			
		||||
                    electron.clipboard.write({
 | 
			
		||||
                        bookmark: params.linkText,
 | 
			
		||||
                        text: params.linkURL
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Paste <kbd>${platformModifier}+V`,
 | 
			
		||||
                uiIcon: "bx bx-paste",
 | 
			
		||||
                handler: () => webContents.paste()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Paste as plain text <kbd>${platformModifier}+Shift+V`,
 | 
			
		||||
                uiIcon: "bx bx-paste",
 | 
			
		||||
                handler: () => webContents.pasteAndMatchStyle()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hasText) {
 | 
			
		||||
            const shortenedSelection = params.selectionText.length > 15
 | 
			
		||||
                ? (`${params.selectionText.substr(0, 13)}…`)
 | 
			
		||||
                : params.selectionText;
 | 
			
		||||
 | 
			
		||||
            // Read the search engine from the options and fallback to DuckDuckGo if the option is not set.
 | 
			
		||||
            const customSearchEngineName = options.get("customSearchEngineName");
 | 
			
		||||
            const customSearchEngineUrl = options.get("customSearchEngineUrl");
 | 
			
		||||
            let searchEngineName;
 | 
			
		||||
            let searchEngineUrl;
 | 
			
		||||
            if (customSearchEngineName && customSearchEngineUrl) {
 | 
			
		||||
                searchEngineName = customSearchEngineName;
 | 
			
		||||
                searchEngineUrl = customSearchEngineUrl;
 | 
			
		||||
            } else {
 | 
			
		||||
                searchEngineName = "Duckduckgo";
 | 
			
		||||
                searchEngineUrl = "https://duckduckgo.com/?q={keyword}";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Replace the placeholder with the real search keyword.
 | 
			
		||||
            let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
 | 
			
		||||
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Search for "${shortenedSelection}" with ${searchEngineName}`,
 | 
			
		||||
                uiIcon: "bx bx-search-alt",
 | 
			
		||||
                handler: () => electron.shell.openExternal(searchUrl)
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (items.length === 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const zoomLevel = zoomService.getCurrentZoom();
 | 
			
		||||
 | 
			
		||||
        contextMenu.show({
 | 
			
		||||
            x: params.x / zoomLevel,
 | 
			
		||||
            y: params.y / zoomLevel,
 | 
			
		||||
            items,
 | 
			
		||||
            selectMenuItemHandler: ({command, spellingSuggestion}) => {
 | 
			
		||||
                if (command === 'replaceMisspelling') {
 | 
			
		||||
                    webContents.insertText(spellingSuggestion);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    electronContextMenu.setupContextMenu();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										138
									
								
								src/public/app/menus/electron_context_menu.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/public/app/menus/electron_context_menu.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,138 @@
 | 
			
		||||
import utils from "../services/utils.js";
 | 
			
		||||
import options from "../services/options.js";
 | 
			
		||||
import zoomService from "../components/zoom.js";
 | 
			
		||||
import contextMenu from "./context_menu.js";
 | 
			
		||||
 | 
			
		||||
function setupContextMenu() {
 | 
			
		||||
    const electron = utils.dynamicRequire('electron');
 | 
			
		||||
 | 
			
		||||
    const remote = utils.dynamicRequire('@electron/remote');
 | 
			
		||||
    const {webContents} = remote.getCurrentWindow();
 | 
			
		||||
 | 
			
		||||
    webContents.on('context-menu', (event, params) => {
 | 
			
		||||
        const {editFlags} = params;
 | 
			
		||||
        const hasText = params.selectionText.trim().length > 0;
 | 
			
		||||
        const isMac = process.platform === "darwin";
 | 
			
		||||
        const platformModifier = isMac ? 'Meta' : 'Ctrl';
 | 
			
		||||
 | 
			
		||||
        const items = [];
 | 
			
		||||
 | 
			
		||||
        if (params.misspelledWord) {
 | 
			
		||||
            for (const suggestion of params.dictionarySuggestions) {
 | 
			
		||||
                items.push({
 | 
			
		||||
                    title: suggestion,
 | 
			
		||||
                    command: "replaceMisspelling",
 | 
			
		||||
                    spellingSuggestion: suggestion,
 | 
			
		||||
                    uiIcon: "bx bx-empty"
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            items.push({
 | 
			
		||||
                title: `Add "${params.misspelledWord}" to dictionary`,
 | 
			
		||||
                uiIcon: "bx bx-plus",
 | 
			
		||||
                handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            items.push({ title: `----` });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canCut && hasText,
 | 
			
		||||
                title: `Cut <kbd>${platformModifier}+X`,
 | 
			
		||||
                uiIcon: "bx bx-cut",
 | 
			
		||||
                handler: () => webContents.cut()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable || hasText) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canCopy && hasText,
 | 
			
		||||
                title: `Copy <kbd>${platformModifier}+C`,
 | 
			
		||||
                uiIcon: "bx bx-copy",
 | 
			
		||||
                handler: () => webContents.copy()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') {
 | 
			
		||||
            items.push({
 | 
			
		||||
                title: `Copy link`,
 | 
			
		||||
                uiIcon: "bx bx-copy",
 | 
			
		||||
                handler: () => {
 | 
			
		||||
                    electron.clipboard.write({
 | 
			
		||||
                        bookmark: params.linkText,
 | 
			
		||||
                        text: params.linkURL
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Paste <kbd>${platformModifier}+V`,
 | 
			
		||||
                uiIcon: "bx bx-paste",
 | 
			
		||||
                handler: () => webContents.paste()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.isEditable) {
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Paste as plain text <kbd>${platformModifier}+Shift+V`,
 | 
			
		||||
                uiIcon: "bx bx-paste",
 | 
			
		||||
                handler: () => webContents.pasteAndMatchStyle()
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hasText) {
 | 
			
		||||
            const shortenedSelection = params.selectionText.length > 15
 | 
			
		||||
                ? (`${params.selectionText.substr(0, 13)}…`)
 | 
			
		||||
                : params.selectionText;
 | 
			
		||||
 | 
			
		||||
            // Read the search engine from the options and fallback to DuckDuckGo if the option is not set.
 | 
			
		||||
            const customSearchEngineName = options.get("customSearchEngineName");
 | 
			
		||||
            const customSearchEngineUrl = options.get("customSearchEngineUrl");
 | 
			
		||||
            let searchEngineName;
 | 
			
		||||
            let searchEngineUrl;
 | 
			
		||||
            if (customSearchEngineName && customSearchEngineUrl) {
 | 
			
		||||
                searchEngineName = customSearchEngineName;
 | 
			
		||||
                searchEngineUrl = customSearchEngineUrl;
 | 
			
		||||
            } else {
 | 
			
		||||
                searchEngineName = "Duckduckgo";
 | 
			
		||||
                searchEngineUrl = "https://duckduckgo.com/?q={keyword}";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Replace the placeholder with the real search keyword.
 | 
			
		||||
            let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
 | 
			
		||||
 | 
			
		||||
            items.push({
 | 
			
		||||
                enabled: editFlags.canPaste,
 | 
			
		||||
                title: `Search for "${shortenedSelection}" with ${searchEngineName}`,
 | 
			
		||||
                uiIcon: "bx bx-search-alt",
 | 
			
		||||
                handler: () => electron.shell.openExternal(searchUrl)
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (items.length === 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const zoomLevel = zoomService.getCurrentZoom();
 | 
			
		||||
 | 
			
		||||
        contextMenu.show({
 | 
			
		||||
            x: params.x / zoomLevel,
 | 
			
		||||
            y: params.y / zoomLevel,
 | 
			
		||||
            items,
 | 
			
		||||
            selectMenuItemHandler: ({command, spellingSuggestion}) => {
 | 
			
		||||
                if (command === 'replaceMisspelling') {
 | 
			
		||||
                    webContents.insertText(spellingSuggestion);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    setupContextMenu
 | 
			
		||||
};
 | 
			
		||||
@ -27,7 +27,7 @@ async function mouseEnterHandler() {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // this is to avoid showing tooltip from inside CKEditor link editor dialog
 | 
			
		||||
    // this is to avoid showing tooltip from inside the CKEditor link editor dialog
 | 
			
		||||
    if ($link.closest(".ck-link-actions").length) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -67,13 +67,13 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class AttachmentDetailWidget extends BasicWidget {
 | 
			
		||||
    constructor(attachment) {
 | 
			
		||||
    constructor(attachment, isFullDetail) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.contentSized();
 | 
			
		||||
        this.attachment = attachment;
 | 
			
		||||
        this.attachmentActionsWidget = new AttachmentActionsWidget(attachment);
 | 
			
		||||
        this.isFullDetail = true;
 | 
			
		||||
        this.attachmentActionsWidget = new AttachmentActionsWidget(attachment, isFullDetail);
 | 
			
		||||
        this.isFullDetail = isFullDetail;
 | 
			
		||||
        this.child(this.attachmentActionsWidget);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,10 +29,8 @@ const TPL = `
 | 
			
		||||
        aria-expanded="false" class="icon-action icon-action-always-border bx bx-dots-vertical-rounded"></button>
 | 
			
		||||
 | 
			
		||||
    <div class="dropdown-menu dropdown-menu-right">
 | 
			
		||||
        <a data-trigger-command="openAttachment" class="dropdown-item">Open</a>
 | 
			
		||||
        <a data-trigger-command="openAttachmentExternally" class="dropdown-item"
 | 
			
		||||
           title="File will be open in an external application and watched for changes. You'll then be able to upload the modified version back to Trilium.">
 | 
			
		||||
            Open externally</a>
 | 
			
		||||
        <a data-trigger-command="openAttachment" class="dropdown-item"
 | 
			
		||||
            title="File will be open in an external application and watched for changes. You'll then be able to upload the modified version back to Trilium.">Open externally</a>
 | 
			
		||||
        <a data-trigger-command="downloadAttachment" class="dropdown-item">Download</a>
 | 
			
		||||
        <a data-trigger-command="uploadNewAttachmentRevision" class="dropdown-item">Upload new revision</a>
 | 
			
		||||
        <a data-trigger-command="copyAttachmentReferenceToClipboard" class="dropdown-item">Copy reference to clipboard</a>
 | 
			
		||||
@ -44,10 +42,11 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class AttachmentActionsWidget extends BasicWidget {
 | 
			
		||||
    constructor(attachment) {
 | 
			
		||||
    constructor(attachment, isFullDetail) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.attachment = attachment;
 | 
			
		||||
        this.isFullDetail = isFullDetail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get attachmentId() {
 | 
			
		||||
@ -83,6 +82,17 @@ export default class AttachmentActionsWidget extends BasicWidget {
 | 
			
		||||
                toastService.showError("Upload of a new attachment revision failed.");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (!this.isFullDetail) {
 | 
			
		||||
            // we deactivate this button because the WatchedFileUpdateStatusWidget assumes only one visible attachment
 | 
			
		||||
            // in a note context, so it doesn't work in a list
 | 
			
		||||
            const $openAttachmentButton = this.$widget.find("[data-trigger-command='openAttachment']");
 | 
			
		||||
            $openAttachmentButton
 | 
			
		||||
                .addClass("disabled")
 | 
			
		||||
                .append($('<span class="disabled-tooltip"> (?)</span>')
 | 
			
		||||
                    .attr("title", "Opening attachment externally is available only from the detail page, please first click on the attachment detail first and repeat the action.")
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async openAttachmentCommand() {
 | 
			
		||||
@ -101,10 +111,6 @@ export default class AttachmentActionsWidget extends BasicWidget {
 | 
			
		||||
        this.parent.copyAttachmentReferenceToClipboard();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async openAttachmentExternallyCommand() {
 | 
			
		||||
        await openService.openAttachmentExternally(this.attachmentId, this.attachment.mime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async deleteAttachmentCommand() {
 | 
			
		||||
        if (!await dialogService.confirm(`Are you sure you want to delete attachment '${this.attachment.title}'?`)) {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@ -37,8 +37,7 @@ export default class AttachmentDetailTypeWidget extends TypeWidget {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const attachmentDetailWidget = new AttachmentDetailWidget(attachment);
 | 
			
		||||
        attachmentDetailWidget.isFullDetail = true;
 | 
			
		||||
        const attachmentDetailWidget = new AttachmentDetailWidget(attachment, true);
 | 
			
		||||
        this.child(attachmentDetailWidget);
 | 
			
		||||
 | 
			
		||||
        this.$wrapper.append(attachmentDetailWidget.render());
 | 
			
		||||
 | 
			
		||||
@ -39,8 +39,7 @@ export default class AttachmentListTypeWidget extends TypeWidget {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const attachment of attachments) {
 | 
			
		||||
            const attachmentDetailWidget = new AttachmentDetailWidget(attachment);
 | 
			
		||||
            attachmentDetailWidget.isFullDetail = false;
 | 
			
		||||
            const attachmentDetailWidget = new AttachmentDetailWidget(attachment, false);
 | 
			
		||||
 | 
			
		||||
            this.child(attachmentDetailWidget);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@ const TPL = `
 | 
			
		||||
    </style>
 | 
			
		||||
    
 | 
			
		||||
    <p>File <code class="file-path"></code> has been last modified on <span class="file-last-modified"></span>.</p> 
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    <div style="display: flex; flex-direction: row; justify-content: space-evenly;">
 | 
			
		||||
        <button class="btn btn-sm file-upload-button">Upload modified file</button>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
@ -195,6 +195,12 @@ div.ui-tooltip {
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dropdown-menu .disabled .disabled-tooltip {
 | 
			
		||||
    pointer-events: all;
 | 
			
		||||
    color: var(--menu-text-color);
 | 
			
		||||
    cursor: help;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dropdown-menu a:hover:not(.disabled), .dropdown-item:hover:not(.disabled) {
 | 
			
		||||
    color: var(--hover-item-text-color) !important;
 | 
			
		||||
    background-color: var(--hover-item-background-color) !important;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user