mobile: more fixes

This commit is contained in:
Ammar Ahmed
2025-02-18 12:09:34 +05:00
committed by Abdullah Atta
parent 446841e0f5
commit f804d7848f
6 changed files with 297 additions and 135 deletions

View File

@@ -56,12 +56,7 @@ const DialogButtons = ({
}
]}
>
{loading ? (
<ActivityIndicator
color={colors.primary.accent}
size={AppFontSize.lg}
/>
) : doneText ? (
{doneText ? (
<View
style={{
flexDirection: "row",
@@ -101,6 +96,7 @@ const DialogButtons = ({
style={{
marginLeft: 10
}}
loading={loading}
bold
type={positiveType || "transparent"}
title={positiveTitle}

View File

@@ -45,6 +45,7 @@ export const Dialog = ({ context = "global" }) => {
const { colors } = useThemeColors();
const [visible, setVisible] = useState(false);
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
const values = useRef({
inputValue: undefined
});
@@ -73,14 +74,23 @@ export const Dialog = ({ context = "global" }) => {
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
inputRef.current?.blur();
let result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
setLoading(true);
let result;
try {
result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
} catch (e) {
/** Empty */
}
setLoading(false);
if (result === false) {
return;
}
}
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
@@ -226,6 +236,7 @@ export const Dialog = ({ context = "global" }) => {
<DialogButtons
onPressNegative={onNegativePress}
onPressPositive={dialogInfo.positivePress && onPressPositive}
loading={loading}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}

View File

@@ -46,6 +46,7 @@ import ExportNotesSheet from "../sheets/export-notes";
import ManageTagsSheet from "../sheets/manage-tags";
import { MoveNotebookSheet } from "../sheets/move-notebook";
import { IconButton } from "../ui/icon-button";
import NativeTooltip from "../../utils/tooltip";
export const SelectionHeader = React.memo(
({
@@ -69,7 +70,7 @@ export const SelectionHeader = React.memo(
const allSelected =
items?.placeholders?.length === selectedItemsList.length;
const focusedRouteId = useNavigationStore((state) => state.focusedRouteId);
console.log(focusedRouteId, "focusedRouteId");
useEffect(() => {
if (selectionMode) {
fluidTabsRef.current?.lock();
@@ -169,116 +170,148 @@ export const SelectionHeader = React.memo(
color={allSelected ? colors.primary.accent : colors.primary.icon}
name="select-all"
/>
{!selectedItemsList.length
? null
: [
{
title: strings.move(),
onPress: async () => {
const ids = selectedItemsList;
const notebooks = await db.notebooks.all.items(ids);
MoveNotebookSheet.present(notebooks);
},
visible: renderedInRoute === "Notebooks",
icon: "arrow-right-bold-box-outline"
},
{
title: strings.manageTags(),
onPress: async () => {
await sleep(100);
ManageTagsSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "pound"
},
{
title: strings.export(),
onPress: async () => {
await sleep(100);
ExportNotesSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "export"
},
{
title: strings.linkNotebook(),
onPress: async () => {
await sleep(100);
MoveNoteSheet.present();
},
visible: type === "note",
icon: "plus"
},
{
title: strings.unlinkNotebook(),
onPress: async () => {
if (!id) return;
await db.notes.removeFromNotebook(id, ...selectedItemsList);
updateNotebook(id);
Navigation.queueRoutesForUpdate();
clearSelection();
},
visible: renderedInRoute === "Notebook",
icon: "minus"
},
{
title: strings.unfavorite(),
onPress: addToFavorite,
visible: focusedRouteId === "Favorites",
icon: "star-off"
},
{
title: strings.moveToTrash(),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible: type === "note" || type === "notebook",
icon: "delete"
},
{
title: strings.doActions.delete.unknown(
type!,
selectedItemsList.length
),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible:
type !== "trash" && type !== "note" && type !== "notebook",
icon: "delete"
},
{
title: strings.restore(),
onPress: restoreItem,
visible: type === "trash",
icon: "delete-restore"
},
{
title: strings.delete(),
onPress: deleteItem,
visible: type === "trash",
icon: "delete"
}
].map((item) =>
: (focusedRouteId === "Monographs"
? [
{
title: strings.unpublish(),
onPress: () => {
presentDialog({
title: strings.doActions.unpublish.note(
selectedItemsList.length
),
positiveText: strings.unpublish(),
negativeText: strings.cancel(),
positivePress: async () => {
for (const id of selectedItemsList) {
await db.monographs.unpublish(id);
}
Navigation.queueRoutesForUpdate();
clearSelection();
},
positiveType: "errorShade"
});
},
visible: true,
icon: "delete"
}
]
: [
{
title: strings.move(),
onPress: async () => {
const ids = selectedItemsList;
const notebooks = await db.notebooks.all.items(ids);
MoveNotebookSheet.present(notebooks);
},
visible: renderedInRoute === "Notebooks",
icon: "arrow-right-bold-box-outline"
},
{
title: strings.manageTags(),
onPress: async () => {
await sleep(100);
ManageTagsSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "pound"
},
{
title: strings.export(),
onPress: async () => {
await sleep(100);
ExportNotesSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "export"
},
{
title: strings.linkNotebook(),
onPress: async () => {
await sleep(100);
MoveNoteSheet.present();
},
visible: type === "note",
icon: "plus"
},
{
title: strings.unlinkNotebook(),
onPress: async () => {
if (!id) return;
await db.notes.removeFromNotebook(
id,
...selectedItemsList
);
updateNotebook(id);
Navigation.queueRoutesForUpdate();
clearSelection();
},
visible: renderedInRoute === "Notebook",
icon: "minus"
},
{
title: strings.unfavorite(),
onPress: addToFavorite,
visible: focusedRouteId === "Favorites",
icon: "star-off"
},
{
title: strings.moveToTrash(),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible: type === "note" || type === "notebook",
icon: "delete"
},
{
title: strings.doActions.delete.unknown(
type!,
selectedItemsList.length
),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible:
type !== "trash" &&
type !== "note" &&
type !== "notebook",
icon: "delete"
},
{
title: strings.restore(),
onPress: restoreItem,
visible: type === "trash",
icon: "delete-restore"
},
{
title: strings.delete(),
onPress: deleteItem,
visible: type === "trash",
icon: "delete"
}
]
).map((item) =>
!item.visible ? null : (
<IconButton
size={AppFontSize.lg}
type="plain"
tooltipText={item.title}
tooltipPosition={NativeTooltip.POSITIONS.TOP}
testID={`select-${item.icon}`}
name={item.icon}
key={item.title}

View File

@@ -18,10 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import React, { useRef } from "react";
import { ColorValue, GestureResponderEvent, TextStyle } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { RGB_Linear_Shade, hexToRGBA } from "../../../utils/colors";
import { hexToRGBA, RGB_Linear_Shade } from "../../../utils/colors";
import { AppFontSize } from "../../../utils/size";
import NativeTooltip from "../../../utils/tooltip";
import { Pressable, PressableProps } from "../pressable";
@@ -58,6 +58,7 @@ export const IconButton = ({
...restProps
}: IconButtonProps) => {
const { colors } = useThemeColors();
const localRef = useRef(null);
const _onLongPress = (event: GestureResponderEvent) => {
if (onLongPress) {
@@ -65,14 +66,20 @@ export const IconButton = ({
return;
}
if (tooltipText) {
NativeTooltip.show(event, tooltipText, tooltipPosition);
NativeTooltip.show(
{
target: fwdRef?.current || localRef.current
},
tooltipText,
tooltipPosition
);
}
};
return (
<Pressable
{...restProps}
fwdRef={fwdRef}
fwdRef={fwdRef || localRef}
onPress={onPress}
hitSlop={{ top: top, left: left, right: right, bottom: bottom }}
onLongPress={_onLongPress}

View File

@@ -119,6 +119,7 @@ const NotesPage = ({
const onRequestUpdate = React.useCallback(
async (data?: NotesScreenParams) => {
if (
params.current.item.id &&
useNavigationStore.getState().focusedRouteId !==
params.current.item.id &&
!data
@@ -187,7 +188,7 @@ const NotesPage = ({
return (
<>
<SelectionHeader
id={route.params?.item?.id}
id={route.params?.item?.id || route.name}
items={notes}
type="note"
renderedInRoute={route.name}
@@ -216,9 +217,7 @@ const NotesPage = ({
items: selector
});
}}
// accentColor={accentColor}
onPressDefaultRightButton={onPressFloatingButton}
// rightButtons={rightButtons?.(params?.current)}
/>
<DelayLayout color={accentColor} wait={loadingNotes}>

View File

@@ -16,7 +16,126 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Platform } from "react-native";
import { findNodeHandle, NativeModules, Platform } from "react-native";
import { fluidTabsRef } from "./global-refs";
import { AppFontSize } from "./size";
const { RNTooltips } = NativeModules;
type TooltipShowOptions = {
text: string;
position: number;
align: number;
autoHide: boolean;
duration: number;
clickToHide: boolean;
corner: number;
tintColor: string;
textColor: string;
textSize: number;
gravity: number;
arrow: boolean;
shadow: boolean;
onHide: () => void;
};
class Tooltips {
static POSITION: {
LEFT: 1;
RIGHT: 2;
TOP: 3;
BOTTOM: 4;
};
static ALIGN: {
START: 1;
CENTER: 2;
END: 3;
};
static GRAVITY: {
START: 1;
CENTER: 2;
END: 3;
};
static defaultProps = {
text: "",
position: 4,
align: 2,
autoHide: true,
duration: Platform.OS === "android" ? 4000 : 4,
clickToHide: false,
corner: Platform.OS === "android" ? 30 : 0,
tintColor: "#1F7C82",
textColor: "#FFFFFF",
textSize: 12,
gravity: 2,
arrow: true,
shadow: true
};
static Show(target: any, parent: any, props: Partial<TooltipShowOptions>) {
if (typeof target !== "number") {
target = findNodeHandle(target);
}
if (typeof parent !== "number") {
parent = findNodeHandle(parent);
}
if (props.text === undefined) {
props.text = Tooltips.defaultProps.text;
}
if (props.position === undefined) {
props.position = Tooltips.defaultProps.position;
}
if (props.align === undefined) {
props.align = Tooltips.defaultProps.align;
}
if (props.autoHide === undefined) {
props.autoHide = Tooltips.defaultProps.autoHide;
}
if (props.duration === undefined) {
props.duration = Tooltips.defaultProps.duration;
}
if (props.clickToHide === undefined) {
props.clickToHide = Tooltips.defaultProps.clickToHide;
}
if (props.corner === undefined) {
props.corner = Tooltips.defaultProps.corner;
}
if (props.tintColor === undefined) {
props.tintColor = Tooltips.defaultProps.tintColor;
}
if (props.textColor === undefined) {
props.textColor = Tooltips.defaultProps.textColor;
}
if (props.textSize === undefined) {
props.textSize = Tooltips.defaultProps.textSize;
}
if (props.gravity === undefined) {
props.gravity = Tooltips.defaultProps.gravity;
}
if (props.shadow === undefined) {
props.shadow = Tooltips.defaultProps.shadow;
}
if (props.arrow === undefined) {
props.arrow = Tooltips.defaultProps.arrow;
}
RNTooltips.Show(target, parent, props, () => {
props.onHide && props.onHide();
});
}
static Dismiss(target: any) {
if (typeof target !== "number") {
target = findNodeHandle(target);
}
RNTooltips.Dismiss(target);
}
}
export const POSITIONS = {
LEFT: 1,
@@ -24,26 +143,23 @@ export const POSITIONS = {
TOP: 3,
BOTTOM: 4
};
let RNTooltips: any;
let prevTarget: any = null;
function show(event: any, text: string, position = 2) {
const fluidTabsRef = require("./global-refs").fluidTabsRef;
if (!RNTooltips) {
RNTooltips = require("react-native-tooltips").default;
}
if (!event._targetInst?.ref?.current) return;
prevTarget && RNTooltips.Dismiss(prevTarget);
if (!event.target) return;
prevTarget && Tooltips.Dismiss(prevTarget);
prevTarget = null;
prevTarget = event._targetInst.ref.current;
RNTooltips.Show(prevTarget, fluidTabsRef.current?.node?.current, {
prevTarget = event.target;
Tooltips.Show(prevTarget, fluidTabsRef.current?.node.current, {
text: text,
tintColor: "#000000",
corner: Platform.OS === "ios" ? 5 : 40,
textSize: 14,
textSize: AppFontSize.md,
position: position,
duration: 1000,
duration: 2000,
autoHide: true,
clickToHide: true
clickToHide: true,
shadow: true
});
}