From 3ef15a2b8d374341bbdb5befc8dd90391c3ce9e1 Mon Sep 17 00:00:00 2001 From: tianma-if Date: Fri, 24 Jul 2026 10:05:32 +0800 Subject: [PATCH] fix: polish mobile transitions and Mermaid rendering --- apps/mobile/app.json | 4 +- apps/mobile/src/components/MobileMermaid.tsx | 5 ++- apps/mobile/src/lib/mobile-mermaid.test.ts | 7 ++++ apps/mobile/src/lib/mobile-mermaid.ts | 9 +++++ apps/mobile/src/screens/WorkspaceScreen.tsx | 40 +++++++++++++++----- package.json | 2 +- 6 files changed, 52 insertions(+), 15 deletions(-) diff --git a/apps/mobile/app.json b/apps/mobile/app.json index bf41ebea..59400a03 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -3,7 +3,7 @@ "name": "EdgeEver", "slug": "edgeever", "scheme": "edgeever", - "version": "1.5.14", + "version": "1.5.16", "runtimeVersion": { "policy": "appVersion" }, @@ -28,7 +28,7 @@ }, "android": { "package": "org.edgeever.mobile", - "versionCode": 35, + "versionCode": 36, "adaptiveIcon": { "backgroundColor": "#d1fae5", "backgroundImage": "./assets/icon.png", diff --git a/apps/mobile/src/components/MobileMermaid.tsx b/apps/mobile/src/components/MobileMermaid.tsx index 55919055..c902fbb4 100644 --- a/apps/mobile/src/components/MobileMermaid.tsx +++ b/apps/mobile/src/components/MobileMermaid.tsx @@ -2,7 +2,7 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, use import { StyleSheet, Text, useWindowDimensions, View } from "react-native"; import { SvgXml } from "react-native-svg"; import LocalTiptapEditor from "./LocalTiptapEditor"; -import { getMermaidSvgAspectRatio } from "../lib/mobile-mermaid"; +import { getMermaidSvgAspectRatio, sanitizeMobileMermaidSvg } from "../lib/mobile-mermaid"; type MermaidResult = { source: string; svg: string | null }; type MermaidContextValue = { @@ -109,9 +109,10 @@ export const MobileMermaidDiagram = ({ const aspectRatio = getMermaidSvgAspectRatio(svg); const availableWidth = Math.max(1, width - 32); const height = Math.min(440, Math.max(120, availableWidth / aspectRatio)); + const nativeSvg = sanitizeMobileMermaidSvg(svg); return ( - + ); }; diff --git a/apps/mobile/src/lib/mobile-mermaid.test.ts b/apps/mobile/src/lib/mobile-mermaid.test.ts index d419588b..1f022b5c 100644 --- a/apps/mobile/src/lib/mobile-mermaid.test.ts +++ b/apps/mobile/src/lib/mobile-mermaid.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { getMermaidSvgAspectRatio, getMobileMarkdownFenceLanguage, + sanitizeMobileMermaidSvg, trimMobileMarkdownFenceContent, } from "./mobile-mermaid"; @@ -20,4 +21,10 @@ describe("mobile Mermaid rendering", () => { expect(getMermaidSvgAspectRatio('')).toBe(2); expect(getMermaidSvgAspectRatio("")).toBe(1.6); }); + + test("normalizes SVG 2 marker orientation for react-native-svg", () => { + expect(sanitizeMobileMermaidSvg('')).toBe(''); + expect(sanitizeMobileMermaidSvg("")).toBe(""); + expect(sanitizeMobileMermaidSvg('')).toBe(''); + }); }); diff --git a/apps/mobile/src/lib/mobile-mermaid.ts b/apps/mobile/src/lib/mobile-mermaid.ts index 4f1beb60..dc77afc8 100644 --- a/apps/mobile/src/lib/mobile-mermaid.ts +++ b/apps/mobile/src/lib/mobile-mermaid.ts @@ -4,6 +4,15 @@ export const getMobileMarkdownFenceLanguage = (sourceInfo: unknown) => export const trimMobileMarkdownFenceContent = (content: string) => content.endsWith("\n") ? content.slice(0, -1) : content; +/** + * Mermaid uses the SVG 2 `auto-start-reverse` marker orientation for arrows. + * Browsers support it, but react-native-svg parses marker `orient` as a + * numeric angle and crashes while drawing the SVG. `auto` keeps the arrow + * direction compatible on native without changing the Mermaid source. + */ +export const sanitizeMobileMermaidSvg = (svg: string) => + svg.replace(/(\borient\s*=\s*)(["'])auto-start-reverse\2/gi, "$1$2auto$2"); + export const getMermaidSvgAspectRatio = (svg: string) => { const viewBox = /viewBox=["']\s*[-\d.]+\s+[-\d.]+\s+([\d.]+)\s+([\d.]+)\s*["']/i.exec(svg); const width = Number(viewBox?.[1]); diff --git a/apps/mobile/src/screens/WorkspaceScreen.tsx b/apps/mobile/src/screens/WorkspaceScreen.tsx index ca097385..a02cea27 100644 --- a/apps/mobile/src/screens/WorkspaceScreen.tsx +++ b/apps/mobile/src/screens/WorkspaceScreen.tsx @@ -77,7 +77,7 @@ import { type ViewStyle, } from "react-native"; import { Gesture, GestureDetector } from "react-native-gesture-handler"; -import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated"; +import Animated, { FadeInDown, FadeOutUp, LinearTransition, runOnJS, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated"; import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context"; import { Alert, Pressable, Text, TextInput } from "../components/LocalizedText"; import Markdown, { type ASTNode, type RenderRules } from "react-native-markdown-display"; @@ -1115,7 +1115,7 @@ export const WorkspaceScreen = () => { /> ) : null} - {selectedMemoId ? { onRichEdit={(memo) => void openRichEditor(memo)} onOpenRevisions={setRevisionMemo} onRestore={(memo) => restoreMemoMutation.mutate(memo)} - visible - /> : null} + visible={Boolean(selectedMemoId)} + /> {editorRuntimeWarm ? ( { }} /> : null} - {createOpen ? { }} onQueued={runAutomaticSync} syncQueueScope={syncQueueScope} - visible - /> : null} + visible={createOpen} + /> {selectionMoveOpen ? void requestClose()} presentationStyle="fullScreen" visible={visible}> + void requestClose()} presentationStyle="fullScreen" visible={visible}> void requestClose()} style={styles.createMemoBackButton}> @@ -5299,9 +5299,23 @@ const MemoCard = memo(function MemoCard({ }) { const localePreference = useMobileLocalePreference(); const memoTitle = memo.title?.trim() || DEFAULT_MEMO_TITLE; + const pressScale = useSharedValue(1); + const pressAnimatedStyle = useAnimatedStyle(() => ({ + transform: [{ scale: pressScale.value }], + })); return ( - + {selectionMode ? ( { + pressScale.value = withTiming(0.985, { duration: 100 }); + }} + onPressOut={() => { + pressScale.value = withTiming(1, { duration: 160 }); + }} style={[styles.memoCardContent, listDensity === "compact" && styles.memoCardContentCompact, selectionMode && styles.memoCardContentWithSelection]} > @@ -5345,7 +5365,7 @@ const MemoCard = memo(function MemoCard({ ))} - + ); }, (previous, next) => previous.memo === next.memo && diff --git a/package.json b/package.json index a6276896..17a9a808 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "edgeever", - "version": "1.5.15", + "version": "1.5.16", "private": true, "type": "module", "workspaces": [