mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 10:09:26 +02:00
Compare commits
3 Commits
fix/317
...
mobile/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21f931d3ea | ||
|
|
58253f11b7 | ||
|
|
0535de9ae9 |
@@ -24,7 +24,6 @@ import Animated, { FadeInDown, FadeOutDown } from "react-native-reanimated";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Notice } from "../../../components/ui/notice";
|
||||
import Paragraph from "../../../components/ui/typography/paragraph";
|
||||
import PremiumService from "../../../services/premium";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { AppFontSize } from "../../../utils/size";
|
||||
import { Group } from "./group";
|
||||
@@ -41,7 +40,7 @@ export const ConfigureToolbar = () => {
|
||||
|
||||
const renderGroups = () => {
|
||||
return data?.map((item, index) => (
|
||||
<Group key={`group-${index}`} item={item} index={index} />
|
||||
<Group key={`group-${index}-${item.length}`} item={item} index={index} />
|
||||
));
|
||||
};
|
||||
|
||||
@@ -131,6 +130,7 @@ export const ConfigureToolbar = () => {
|
||||
style={{
|
||||
flex: 1
|
||||
}}
|
||||
key={preset}
|
||||
scrollEventThrottle={13}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
|
||||
@@ -31,7 +31,7 @@ import { renderTool } from "./common";
|
||||
import { DraggableItem, useDragState } from "./state";
|
||||
import ToolSheet from "./tool-sheet";
|
||||
|
||||
import { useIsFeatureAvailable } from "@notesnook/common";
|
||||
import { isFeatureAvailable, useIsFeatureAvailable } from "@notesnook/common";
|
||||
import type { ToolId } from "@notesnook/editor";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
@@ -64,78 +64,87 @@ export const Group = ({
|
||||
const { colors } = useThemeColors();
|
||||
const featureAvailable = useIsFeatureAvailable("customToolbarPreset");
|
||||
|
||||
const onDrop = (data: DraxDragWithReceiverEventData) => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
const isDroppedAbove = data.receiver.receiveOffsetRatio.y < 0.5;
|
||||
const dragged = data.dragged.payload;
|
||||
const reciever = data.receiver.payload;
|
||||
const _data = useDragState.getState().data.slice();
|
||||
|
||||
if (dragged.type === "group") {
|
||||
const fromIndex = dragged.index;
|
||||
const toIndex = isDroppedAbove
|
||||
? Math.max(0, reciever.index)
|
||||
: reciever.index + 1;
|
||||
|
||||
_data.splice(
|
||||
toIndex > fromIndex ? toIndex - 1 : toIndex,
|
||||
0,
|
||||
_data.splice(fromIndex, 1)[0]
|
||||
);
|
||||
}
|
||||
|
||||
// Always insert sub group at the end of the group.
|
||||
if (dragged.type === "subgroup") {
|
||||
const fromIndex = dragged.index;
|
||||
|
||||
const insertAt = _data[reciever.index] as string[];
|
||||
const insertFrom = _data[dragged.groupIndex] as string[];
|
||||
|
||||
if (typeof insertAt[insertAt.length - 1] !== "string") {
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
const onDrop = React.useCallback(
|
||||
(data: DraxDragWithReceiverEventData) => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error || strings.featureNotAvailable()
|
||||
});
|
||||
return;
|
||||
}
|
||||
insertAt.push(insertFrom.splice(fromIndex, 1)[0]);
|
||||
}
|
||||
const isDroppedAbove = data.receiver.receiveOffsetRatio.y < 0.5;
|
||||
const dragged = data.dragged.payload;
|
||||
const reciever = data.receiver.payload;
|
||||
const _data = useDragState.getState().data.slice();
|
||||
|
||||
if (dragged.type === "tool") {
|
||||
const insertFrom =
|
||||
typeof dragged.parentIndex === "number"
|
||||
? (_data[dragged.parentIndex][dragged.groupIndex] as string[])
|
||||
: (_data[dragged.groupIndex] as string[]);
|
||||
_data[groupIndex].push(insertFrom.splice(dragged.index, 1)[0] as ToolId);
|
||||
}
|
||||
if (dragged.type === "group") {
|
||||
const fromIndex = dragged.index;
|
||||
const toIndex = isDroppedAbove
|
||||
? Math.max(0, reciever.index)
|
||||
: reciever.index + 1;
|
||||
|
||||
setData(_data);
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
};
|
||||
_data.splice(
|
||||
toIndex > fromIndex ? toIndex - 1 : toIndex,
|
||||
0,
|
||||
_data.splice(fromIndex, 1)[0]
|
||||
);
|
||||
}
|
||||
|
||||
const onRecieveData = (data: DraxDragWithReceiverEventData) => {
|
||||
setRecieving(true);
|
||||
if (data.dragged.payload.type !== "group")
|
||||
return setRecievePosition("below");
|
||||
if (data.receiver.receiveOffsetRatio.y < 0.5) {
|
||||
setRecievePosition("above");
|
||||
} else {
|
||||
setRecievePosition("below");
|
||||
}
|
||||
};
|
||||
// Always insert sub group at the end of the group.
|
||||
if (dragged.type === "subgroup") {
|
||||
const fromIndex = dragged.index;
|
||||
|
||||
const insertAt = _data[reciever.index] as string[];
|
||||
const insertFrom = _data[dragged.groupIndex] as string[];
|
||||
|
||||
if (typeof insertAt[insertAt.length - 1] !== "string") {
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
}
|
||||
insertAt.push(insertFrom.splice(fromIndex, 1)[0]);
|
||||
}
|
||||
|
||||
if (dragged.type === "tool") {
|
||||
const insertFrom =
|
||||
typeof dragged.parentIndex === "number"
|
||||
? (_data[dragged.parentIndex][dragged.groupIndex] as string[])
|
||||
: (_data[dragged.groupIndex] as string[]);
|
||||
_data[groupIndex].push(
|
||||
insertFrom.splice(dragged.index, 1)[0] as ToolId
|
||||
);
|
||||
}
|
||||
|
||||
setData(_data);
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
},
|
||||
[featureAvailable]
|
||||
);
|
||||
|
||||
const onRecieveData = React.useCallback(
|
||||
(data: DraxDragWithReceiverEventData) => {
|
||||
setRecieving(true);
|
||||
if (data.dragged.payload.type !== "group")
|
||||
return setRecievePosition("below");
|
||||
if (data.receiver.receiveOffsetRatio.y < 0.5) {
|
||||
setRecievePosition("above");
|
||||
} else {
|
||||
setRecievePosition("below");
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
name: "minus",
|
||||
onPress: () => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
onPress: async () => {
|
||||
const feature = await isFeatureAvailable("customToolbarPreset");
|
||||
if (!feature.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
message: feature?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -157,11 +166,12 @@ export const Group = ({
|
||||
},
|
||||
{
|
||||
name: "plus",
|
||||
onPress: () => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
onPress: async () => {
|
||||
const feature = await isFeatureAvailable("customToolbarPreset");
|
||||
if (!feature.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
message: feature?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ export default function ToolSheet({
|
||||
fwdRef: RefObject<ActionSheetRef>;
|
||||
}) {
|
||||
const { colors } = useThemeColors();
|
||||
const data = useDragState((state) => state.data);
|
||||
const ungrouped = getUngroupedTools(data) as ToolId[];
|
||||
const [data] = useDragState((state) => [state.data]);
|
||||
const ungrouped = getUngroupedTools( data) as ToolId[];
|
||||
|
||||
const renderTool = React.useCallback(
|
||||
(item: ToolId) => {
|
||||
@@ -114,7 +114,7 @@ export default function ToolSheet({
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
maxHeight: "100%",
|
||||
maxHeight: 400,
|
||||
padding: DefaultAppStyles.GAP
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -33,7 +33,7 @@ import { DraggableItem, useDragState } from "./state";
|
||||
import ToolSheet from "./tool-sheet";
|
||||
import { findToolById, getToolIcon } from "./toolbar-definition";
|
||||
|
||||
import { useIsFeatureAvailable } from "@notesnook/common";
|
||||
import { isFeatureAvailable, useIsFeatureAvailable } from "@notesnook/common";
|
||||
import type { ToolId } from "@notesnook/editor";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
@@ -78,11 +78,12 @@ export const Tool = ({
|
||||
? [
|
||||
{
|
||||
name: "minus",
|
||||
onPress: () => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
onPress: async () => {
|
||||
const feature = await isFeatureAvailable("customToolbarPreset");
|
||||
if (!feature.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
message: feature?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -102,11 +103,12 @@ export const Tool = ({
|
||||
},
|
||||
{
|
||||
name: "plus",
|
||||
onPress: () => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
onPress: async () => {
|
||||
const feature = await isFeatureAvailable("customToolbarPreset");
|
||||
if (!feature.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
message: feature?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -122,11 +124,12 @@ export const Tool = ({
|
||||
: [
|
||||
{
|
||||
name: "minus",
|
||||
onPress: () => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
onPress: async () => {
|
||||
const feature = await isFeatureAvailable("customToolbarPreset");
|
||||
if (!feature.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
message: feature?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +154,7 @@ export const Tool = ({
|
||||
if (parentIndex === undefined && !isSubgroup) {
|
||||
btns.unshift({
|
||||
name: "unfold-less-horizontal",
|
||||
onPress: () => {
|
||||
onPress: async () => {
|
||||
if (groupIndex === undefined) return;
|
||||
const _data = useDragState.getState().data.slice();
|
||||
const hasSubGroup = Array.isArray(
|
||||
@@ -267,6 +270,7 @@ export const Tool = ({
|
||||
style={{
|
||||
paddingLeft: 30
|
||||
}}
|
||||
key={`subgroup-${item.length}-${groupIndex}-${index}-${parentIndex}`}
|
||||
>
|
||||
{renderGroup({ index, item, parentIndex: groupIndex })}
|
||||
</View>
|
||||
@@ -290,63 +294,69 @@ export const Tool = ({
|
||||
]
|
||||
);
|
||||
|
||||
const onDrop = (data: DraxDragWithReceiverEventData) => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
const isDroppedAbove = data.receiver.receiveOffsetRatio.y < 0.5;
|
||||
const dragged = data.dragged.payload;
|
||||
const reciever = data.receiver.payload;
|
||||
const _data = useDragState.getState().data?.slice();
|
||||
if (!_data) return;
|
||||
const isFromSubgroup = typeof dragged?.parentIndex === "number";
|
||||
const isDroppedAtSubgroup = typeof reciever?.parentIndex === "number";
|
||||
|
||||
if (dragged.type === "tool") {
|
||||
const fromIndex = dragged.index;
|
||||
const toIndex = isDroppedAbove
|
||||
? Math.max(0, reciever.index)
|
||||
: reciever.index + 1;
|
||||
|
||||
const insertAt = isDroppedAtSubgroup
|
||||
? (_data[reciever.parentIndex][reciever.groupIndex] as string[])
|
||||
: (_data[reciever.groupIndex] as string[]);
|
||||
const insertFrom = isFromSubgroup
|
||||
? (_data[dragged.parentIndex][dragged.groupIndex] as string[])
|
||||
: (_data[dragged.groupIndex] as string[]);
|
||||
insertAt.splice(
|
||||
toIndex > fromIndex ? toIndex - 1 : toIndex,
|
||||
0,
|
||||
insertFrom.splice(fromIndex, 1)[0]
|
||||
);
|
||||
|
||||
// Remove the group or subgroup if it is empty.
|
||||
if (insertFrom.length === 0) {
|
||||
isFromSubgroup
|
||||
? _data[dragged.parentIndex].splice(
|
||||
_data[dragged.parentIndex].length - 1,
|
||||
1
|
||||
)
|
||||
: _data.splice(dragged.groupIndex, 1);
|
||||
const onDrop = React.useCallback(
|
||||
(data: DraxDragWithReceiverEventData) => {
|
||||
if (!featureAvailable?.isAllowed) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: featureAvailable?.error || strings.featureNotAvailable()
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
setData(_data);
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
};
|
||||
const isDroppedAbove = data.receiver.receiveOffsetRatio.y < 0.5;
|
||||
const dragged = data.dragged.payload;
|
||||
const reciever = data.receiver.payload;
|
||||
const _data = useDragState.getState().data?.slice();
|
||||
if (!_data) return;
|
||||
const isFromSubgroup = typeof dragged?.parentIndex === "number";
|
||||
const isDroppedAtSubgroup = typeof reciever?.parentIndex === "number";
|
||||
|
||||
const onRecieveData = (data: DraxDragWithReceiverEventData) => {
|
||||
setRecieving(true);
|
||||
if (data.receiver.receiveOffsetRatio.y < 0.5) {
|
||||
setRecievePosition("above");
|
||||
} else {
|
||||
setRecievePosition("below");
|
||||
}
|
||||
};
|
||||
if (dragged.type === "tool") {
|
||||
const fromIndex = dragged.index;
|
||||
const toIndex = isDroppedAbove
|
||||
? Math.max(0, reciever.index)
|
||||
: reciever.index + 1;
|
||||
|
||||
const insertAt = isDroppedAtSubgroup
|
||||
? (_data[reciever.parentIndex][reciever.groupIndex] as string[])
|
||||
: (_data[reciever.groupIndex] as string[]);
|
||||
const insertFrom = isFromSubgroup
|
||||
? (_data[dragged.parentIndex][dragged.groupIndex] as string[])
|
||||
: (_data[dragged.groupIndex] as string[]);
|
||||
insertAt.splice(
|
||||
toIndex > fromIndex ? toIndex - 1 : toIndex,
|
||||
0,
|
||||
insertFrom.splice(fromIndex, 1)[0]
|
||||
);
|
||||
|
||||
// Remove the group or subgroup if it is empty.
|
||||
if (insertFrom.length === 0) {
|
||||
isFromSubgroup
|
||||
? _data[dragged.parentIndex].splice(
|
||||
_data[dragged.parentIndex].length - 1,
|
||||
1
|
||||
)
|
||||
: _data.splice(dragged.groupIndex, 1);
|
||||
}
|
||||
}
|
||||
setData(_data);
|
||||
setRecieving(false);
|
||||
return data.dragAbsolutePosition;
|
||||
},
|
||||
[featureAvailable]
|
||||
);
|
||||
|
||||
const onRecieveData = React.useCallback(
|
||||
(data: DraxDragWithReceiverEventData) => {
|
||||
setRecieving(true);
|
||||
if (data.receiver.receiveOffsetRatio.y < 0.5) {
|
||||
setRecievePosition("above");
|
||||
} else {
|
||||
setRecievePosition("below");
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<Animated.View layout={Layout}>
|
||||
|
||||
@@ -25,18 +25,18 @@ import {
|
||||
} from "@notesnook/editor/dist/cjs/toolbar/tool-definitions";
|
||||
import { ToolId } from "@notesnook/editor";
|
||||
|
||||
export const tools = getAllTools() as any;
|
||||
export const tools = () => getAllTools();
|
||||
export const presets: { [name: string]: ToolbarGroupDefinition[] } = {
|
||||
default: getDefaultPresets().default as any,
|
||||
minimal: getDefaultPresets().minimal as any,
|
||||
custom: []
|
||||
};
|
||||
|
||||
export function findToolById(id: keyof typeof tools): {
|
||||
export function findToolById(id: keyof ReturnType<typeof tools> ): {
|
||||
title: string;
|
||||
icon: string;
|
||||
} {
|
||||
return tools[id];
|
||||
return tools()[id];
|
||||
}
|
||||
|
||||
export function getToolIcon(id: ToolId, color: string) {
|
||||
@@ -51,13 +51,14 @@ export function getToolIcon(id: ToolId, color: string) {
|
||||
|
||||
export function getUngroupedTools(
|
||||
toolDefinition: (string | string[])[][]
|
||||
): string[] {
|
||||
const keys = Object.keys(tools);
|
||||
): string[] {
|
||||
const allTools = tools();
|
||||
const keys = Object.keys(allTools);
|
||||
|
||||
const ungrouped = [];
|
||||
const toolString = JSON.stringify(toolDefinition);
|
||||
for (const key of keys) {
|
||||
if (tools[key as ToolId].conditional) continue;
|
||||
if ((allTools[key as ToolId] as any).conditional) continue;
|
||||
if (!toolString.includes(key)) ungrouped.push(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { ToolbarDefinition, ToolDefinition } from "./types.js";
|
||||
import { ToolId } from "./tools/index.js";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
const tools: Record<ToolId, ToolDefinition> = {
|
||||
const tools = (): Record<ToolId, ToolDefinition> => ({
|
||||
none: {
|
||||
icon: "none",
|
||||
title: ""
|
||||
@@ -356,14 +356,14 @@ const tools: Record<ToolId, ToolDefinition> = {
|
||||
title: strings.exportCsv(),
|
||||
conditional: true
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export function getToolDefinition(id: ToolId) {
|
||||
return tools[id];
|
||||
return tools()[id];
|
||||
}
|
||||
|
||||
export function getAllTools() {
|
||||
return tools;
|
||||
return tools();
|
||||
}
|
||||
|
||||
export function getDefaultPresets() {
|
||||
|
||||
@@ -6555,6 +6555,10 @@ msgstr "This error usually means the database file is either corrupt or it could
|
||||
msgid "This error usually means the search index is corrupted."
|
||||
msgstr "This error usually means the search index is corrupted."
|
||||
|
||||
#: src/strings.ts:2643
|
||||
msgid "This feature is not available on this plan."
|
||||
msgstr "This feature is not available on this plan."
|
||||
|
||||
#: src/strings.ts:1934
|
||||
msgid "This image cannot be previewed"
|
||||
msgstr "This image cannot be previewed"
|
||||
|
||||
@@ -6514,6 +6514,10 @@ msgstr ""
|
||||
msgid "This error usually means the search index is corrupted."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2643
|
||||
msgid "This feature is not available on this plan."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:1934
|
||||
msgid "This image cannot be previewed"
|
||||
msgstr ""
|
||||
|
||||
@@ -2639,5 +2639,6 @@ Use this if changes from other devices are not appearing on this device. This wi
|
||||
confirmationEmailSent: () => t`Confirmation email sent`,
|
||||
back: () => t`Back`,
|
||||
invalidRecoveryKey: () =>
|
||||
t`Invalid recovery key. Make sure to input your account recovery key, not a 2FA recovery code.`
|
||||
t`Invalid recovery key. Make sure to input your account recovery key, not a 2FA recovery code.`,
|
||||
featureNotAvailable: () => t`This feature is not available on this plan.`
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user