diff --git a/app/assets/javascripts/components/AttachedFilesPopover/AttachedFilesButton.tsx b/app/assets/javascripts/components/AttachedFilesPopover/AttachedFilesButton.tsx index 4ec4a7b36..acaa042b8 100644 --- a/app/assets/javascripts/components/AttachedFilesPopover/AttachedFilesButton.tsx +++ b/app/assets/javascripts/components/AttachedFilesPopover/AttachedFilesButton.tsx @@ -12,7 +12,13 @@ import { FunctionComponent } from 'preact'; import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { Icon } from '../Icon'; import { useCloseOnClickOutside } from '../utils'; -import { ChallengeReason, ContentType, SNFile } from '@standardnotes/snjs'; +import { + ChallengeReason, + ContentType, + FeatureIdentifier, + FeatureStatus, + SNFile, +} from '@standardnotes/snjs'; import { confirmDialog } from '@/services/alertService'; import { addToast, dismissToast, ToastType } from '@standardnotes/stylekit'; import { StreamingFileReader } from '@standardnotes/filepicker'; @@ -21,6 +27,7 @@ import { PopoverFileItemActionType, } from './PopoverFileItemAction'; import { AttachedFilesPopover, PopoverTabs } from './AttachedFilesPopover'; +import { usePremiumModal } from '../Premium/usePremiumModal'; type Props = { application: WebApplication; @@ -28,8 +35,26 @@ type Props = { onClickPreprocessing?: () => Promise; }; +const createDragOverlay = () => { + if (document.getElementById('drag-overlay')) { + return; + } + + const overlayElementTemplate = + '
'; + const overlayFragment = document + .createRange() + .createContextualFragment(overlayElementTemplate); + document.body.appendChild(overlayFragment); +}; + +const removeDragOverlay = () => { + document.getElementById('drag-overlay')?.remove(); +}; + export const AttachedFilesButton: FunctionComponent = observer( ({ application, appState, onClickPreprocessing }) => { + const premiumModal = usePremiumModal(); const note = Object.values(appState.notes.selectedNotes)[0]; const [open, setOpen] = useState(false); @@ -69,6 +94,14 @@ export const AttachedFilesButton: FunctionComponent = observer( }, [application, reloadAttachedFilesCount]); const toggleAttachedFilesMenu = useCallback(async () => { + if ( + application.features.getFeatureStatus(FeatureIdentifier.Files) !== + FeatureStatus.Entitled + ) { + premiumModal.activate('Files'); + return; + } + const rect = buttonRef.current?.getBoundingClientRect(); if (rect) { const { clientHeight } = document.documentElement; @@ -98,7 +131,7 @@ export const AttachedFilesButton: FunctionComponent = observer( setOpen(newOpenState); } - }, [onClickPreprocessing, open]); + }, [application.features, onClickPreprocessing, open, premiumModal]); const deleteFile = async (file: SNFile) => { const shouldDelete = await confirmDialog({ @@ -230,6 +263,7 @@ export const AttachedFilesButton: FunctionComponent = observer( if (event.dataTransfer?.items.length) { setIsDraggingFiles(true); + createDragOverlay(); if (!open) { toggleAttachedFilesMenu(); } @@ -248,6 +282,8 @@ export const AttachedFilesButton: FunctionComponent = observer( return; } + removeDragOverlay(); + setIsDraggingFiles(false); }; @@ -257,6 +293,7 @@ export const AttachedFilesButton: FunctionComponent = observer( event.stopPropagation(); setIsDraggingFiles(false); + removeDragOverlay(); if (event.dataTransfer?.items.length) { Array.from(event.dataTransfer.items).forEach(async (item) => { diff --git a/app/assets/javascripts/components/NoteView/NoteView.tsx b/app/assets/javascripts/components/NoteView/NoteView.tsx index 33d8f21bb..01a8df836 100644 --- a/app/assets/javascripts/components/NoteView/NoteView.tsx +++ b/app/assets/javascripts/components/NoteView/NoteView.tsx @@ -12,13 +12,10 @@ import { ComponentMutator, PayloadSource, ComponentViewer, - ComponentManagerEvent, TransactionalMutation, ItemMutator, ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction, NoteViewController, - FeatureIdentifier, - FeatureStatus, } from '@standardnotes/snjs'; import { debounce, isDesktopApplication } from '@/utils'; import { KeyboardModifier, KeyboardKey } from '@/services/ioService'; @@ -103,7 +100,6 @@ type State = { editorTitle: string; editorText: string; isDesktop?: boolean; - isEntitledToFiles: boolean; lockText: string; marginResizersEnabled?: boolean; monospaceFont?: boolean; @@ -172,9 +168,6 @@ export class NoteView extends PureComponent { editorText: '', editorTitle: '', isDesktop: isDesktopApplication(), - isEntitledToFiles: - this.application.features.getFeatureStatus(FeatureIdentifier.Files) === - FeatureStatus.Entitled, lockText: 'Note Editing Disabled', noteStatus: undefined, noteLocked: this.controller.note.locked, @@ -328,15 +321,6 @@ export class NoteView extends PureComponent { /** @override */ async onAppEvent(eventName: ApplicationEvent) { switch (eventName) { - case ApplicationEvent.FeaturesUpdated: - case ApplicationEvent.UserRolesChanged: - this.setState({ - isEntitledToFiles: - this.application.features.getFeatureStatus( - FeatureIdentifier.Files - ) === FeatureStatus.Entitled, - }); - break; case ApplicationEvent.PreferencesChanged: this.reloadPreferences(); break; @@ -1043,18 +1027,17 @@ export class NoteView extends PureComponent { )} - {this.state.isEntitledToFiles && - window.enabledUnfinishedFeatures && ( -
- -
- )} + {window.enabledUnfinishedFeatures && ( +
+ +
+ )}