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