feat: show alert when changing to non-interchangeable editor (#834)
This commit is contained in:
@@ -277,10 +277,10 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
<EditorAccordionMenu
|
||||
application={application}
|
||||
closeOnBlur={closeOnBlur}
|
||||
currentEditor={selectedEditor}
|
||||
groups={editorMenuGroups}
|
||||
isOpen={changeEditorMenuOpen}
|
||||
selectComponent={selectComponent}
|
||||
selectedEditor={selectedEditor}
|
||||
/>
|
||||
</PremiumModalProvider>
|
||||
</DisclosurePanel>
|
||||
|
||||
@@ -15,7 +15,7 @@ type EditorAccordionMenuProps = {
|
||||
groups: EditorMenuGroup[];
|
||||
isOpen: boolean;
|
||||
selectComponent: (component: SNComponent | null) => Promise<void>;
|
||||
selectedEditor: SNComponent | undefined;
|
||||
currentEditor: SNComponent | undefined;
|
||||
};
|
||||
|
||||
const getGroupId = (group: EditorMenuGroup) =>
|
||||
@@ -25,6 +25,9 @@ const getGroupBtnId = (groupId: string) => groupId + '-button';
|
||||
|
||||
const isElementHidden = (element: Element) => !element.clientHeight;
|
||||
|
||||
const isElementFocused = (element: Element | null) =>
|
||||
element === document.activeElement;
|
||||
|
||||
export const EditorAccordionMenu: FunctionComponent<
|
||||
EditorAccordionMenuProps
|
||||
> = ({
|
||||
@@ -33,16 +36,22 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
groups,
|
||||
isOpen,
|
||||
selectComponent,
|
||||
selectedEditor,
|
||||
currentEditor,
|
||||
}) => {
|
||||
const [activeGroupId, setActiveGroupId] = useState('');
|
||||
const menuItemRefs = useRef<(HTMLButtonElement | null)[]>([]);
|
||||
const premiumModal = usePremiumModal();
|
||||
|
||||
const addRefToMenuItems = (button: HTMLButtonElement | null) => {
|
||||
if (!menuItemRefs.current?.includes(button) && button) {
|
||||
menuItemRefs.current.push(button);
|
||||
}
|
||||
};
|
||||
|
||||
const isSelectedEditor = useCallback(
|
||||
(item: EditorMenuItem) => {
|
||||
if (selectedEditor) {
|
||||
if (item?.component?.identifier === selectedEditor.identifier) {
|
||||
if (currentEditor) {
|
||||
if (item?.component?.identifier === currentEditor.identifier) {
|
||||
return true;
|
||||
}
|
||||
} else if (item.name === PLAIN_EDITOR_NAME) {
|
||||
@@ -50,7 +59,7 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[selectedEditor]
|
||||
[currentEditor]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -62,13 +71,10 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
const newActiveGroupId = getGroupId(activeGroup);
|
||||
setActiveGroupId(newActiveGroupId);
|
||||
}
|
||||
}, [groups, selectedEditor, isSelectedEditor]);
|
||||
}, [groups, currentEditor, isSelectedEditor]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isOpen &&
|
||||
!menuItemRefs.current.some((btn) => btn === document.activeElement)
|
||||
) {
|
||||
if (isOpen && !menuItemRefs.current.some(isElementFocused)) {
|
||||
const selectedEditor = groups
|
||||
.map((group) => group.items)
|
||||
.flat()
|
||||
@@ -96,8 +102,7 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
items = items.filter((btn) => btn?.id);
|
||||
}
|
||||
|
||||
const currentItemIndex =
|
||||
items.findIndex((btn) => btn === document.activeElement) ?? 0;
|
||||
const currentItemIndex = items.findIndex(isElementFocused) ?? 0;
|
||||
|
||||
if (e.key === KeyboardKey.Up) {
|
||||
let previousItemIndex = currentItemIndex - 1;
|
||||
@@ -146,26 +151,50 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
}
|
||||
};
|
||||
|
||||
const selectEditor = (item: EditorMenuItem) => {
|
||||
if (item.component) {
|
||||
selectComponent(item.component);
|
||||
} else if (item.isPremiumFeature) {
|
||||
premiumModal.activate(item.name);
|
||||
} else {
|
||||
selectComponent(null);
|
||||
const selectEditor = async (itemToBeSelected: EditorMenuItem) => {
|
||||
let shouldSelectEditor = true;
|
||||
|
||||
if (itemToBeSelected.component) {
|
||||
const changeRequiresAlert =
|
||||
application.componentManager.doesEditorChangeRequireAlert(
|
||||
currentEditor,
|
||||
itemToBeSelected.component
|
||||
);
|
||||
|
||||
if (changeRequiresAlert) {
|
||||
shouldSelectEditor =
|
||||
await application.componentManager.showEditorChangeAlert();
|
||||
}
|
||||
}
|
||||
|
||||
if (itemToBeSelected.isPremiumFeature) {
|
||||
premiumModal.activate(itemToBeSelected.name);
|
||||
shouldSelectEditor = false;
|
||||
}
|
||||
|
||||
if (shouldSelectEditor) {
|
||||
selectComponent(itemToBeSelected.component ?? null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{groups.map((group) => {
|
||||
if (!group.items || !group.items.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const groupId = getGroupId(group);
|
||||
const buttonId = getGroupBtnId(groupId);
|
||||
const contentId = `${groupId}-content`;
|
||||
|
||||
if (!group.items || !group.items.length) {
|
||||
return null;
|
||||
}
|
||||
const toggleGroup = () => {
|
||||
if (activeGroupId !== groupId) {
|
||||
setActiveGroupId(groupId);
|
||||
} else {
|
||||
setActiveGroupId('');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment key={groupId}>
|
||||
@@ -182,19 +211,9 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
className="sn-dropdown-item focus:bg-info-backdrop justify-between py-3"
|
||||
id={buttonId}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (activeGroupId !== groupId) {
|
||||
setActiveGroupId(groupId);
|
||||
} else {
|
||||
setActiveGroupId('');
|
||||
}
|
||||
}}
|
||||
onClick={toggleGroup}
|
||||
onBlur={closeOnBlur}
|
||||
ref={(button) => {
|
||||
if (!menuItemRefs.current?.includes(button) && button) {
|
||||
menuItemRefs.current.push(button);
|
||||
}
|
||||
}}
|
||||
ref={addRefToMenuItems}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
{group.icon && (
|
||||
@@ -222,26 +241,21 @@ export const EditorAccordionMenu: FunctionComponent<
|
||||
>
|
||||
<div role="radiogroup">
|
||||
{group.items.map((item) => {
|
||||
const onClickEditorItem = () => {
|
||||
selectEditor(item);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
role="radio"
|
||||
data-item-name={item.name}
|
||||
onClick={() => {
|
||||
selectEditor(item);
|
||||
}}
|
||||
onClick={onClickEditorItem}
|
||||
className={`sn-dropdown-item py-2 text-input focus:bg-info-backdrop focus:shadow-none ${
|
||||
item.isPremiumFeature && 'justify-between'
|
||||
}`}
|
||||
aria-checked={false}
|
||||
onBlur={closeOnBlur}
|
||||
ref={(button) => {
|
||||
if (
|
||||
!menuItemRefs.current?.includes(button) &&
|
||||
button
|
||||
) {
|
||||
menuItemRefs.current.push(button);
|
||||
}
|
||||
}}
|
||||
ref={addRefToMenuItems}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"@reach/tooltip": "^0.16.2",
|
||||
"@standardnotes/components": "1.4.4",
|
||||
"@standardnotes/features": "1.26.1",
|
||||
"@standardnotes/snjs": "2.46.0",
|
||||
"@standardnotes/snjs": "2.47.0",
|
||||
"@standardnotes/settings": "^1.10.0",
|
||||
"@standardnotes/sncrypto-web": "1.6.0",
|
||||
"mobx": "^6.3.5",
|
||||
|
||||
@@ -2655,10 +2655,10 @@
|
||||
buffer "^6.0.3"
|
||||
libsodium-wrappers "^0.7.9"
|
||||
|
||||
"@standardnotes/snjs@2.46.0":
|
||||
version "2.46.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.46.0.tgz#7e4242df8cd0408fde243e1048536fa19ea6c5d9"
|
||||
integrity sha512-lKCW6/Q3HaDdaI6VJ31m6GyIy6TgHyGesdUQzbMFtZPEhHDjySqFCyIaQy0ZVdAMB7X/HFxREtxwAwG5wfVVvw==
|
||||
"@standardnotes/snjs@2.47.0":
|
||||
version "2.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.47.0.tgz#cba45c9c8d3d94366a0d575a7fdad1d580b5fc7a"
|
||||
integrity sha512-ylfRsHRj3llzqQqVQK3/FC79PR/frExRDHsqZZoiLhozI5NX6LUmjLkZbbFg9SrTtjFrW13QyS022TZvnWxZPA==
|
||||
dependencies:
|
||||
"@standardnotes/auth" "^3.15.3"
|
||||
"@standardnotes/common" "^1.8.0"
|
||||
|
||||
Reference in New Issue
Block a user