fix(android): encode brackets in note image export URIs
This commit is contained in:
1 parent
aa1efec65a
commit
20ae6ddf2b
3 files changed
+29
-2
No files matched your search
@@ -1,5 +1,25 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { planMobileNoteImageRender } from "./mobile-note-image-export";
|
||||
import { PathUtilities } from "../../node_modules/expo-file-system/src/pathUtilities";
|
||||
import { buildImageExportBasename } from "@edgeever/shared/note-image-card";
|
||||
import { encodeMobileNoteImageFileUri, planMobileNoteImageRender } from "./mobile-note-image-export";
|
||||
|
||||
describe("mobile note image file URI", () => {
|
||||
test.each(["png", "jpg"])("preserves bracketed titles for %s exports through Expo path joining", (extension) => {
|
||||
const filename = `${buildImageExportBasename("[Serv00.com] Account activation tuuki", "Untitled")}.${extension}`;
|
||||
const uri = encodeMobileNoteImageFileUri(PathUtilities.join("file:///cache/exports/request-1/", filename));
|
||||
expect(uri).toBe(`file:///cache/exports/request-1/%5BServ00.com%5D%20Account%20activation%20tuuki.${extension}`);
|
||||
// File's constructor joins the URI once more before handing it to Android.
|
||||
expect(PathUtilities.join(uri)).toBe(uri);
|
||||
expect(decodeURIComponent(new URL(uri).pathname.split("/").at(-1)!)).toBe(filename);
|
||||
});
|
||||
|
||||
test.each(["中文 [标题] 100% #1.png", "literal %5Bname%5D.png", "普通笔记.jpg"])("preserves the filename %s without double encoding", (filename) => {
|
||||
const uri = encodeMobileNoteImageFileUri(PathUtilities.join("file:///cache/exports/", filename));
|
||||
expect(uri).not.toMatch(/[\[\]]/);
|
||||
expect(decodeURIComponent(new URL(uri).pathname.split("/").at(-1)!)).toBe(filename);
|
||||
expect(encodeMobileNoteImageFileUri(uri)).toBe(uri);
|
||||
});
|
||||
});
|
||||
|
||||
describe("planMobileNoteImageRender", () => {
|
||||
test("keeps a short card at full quality", () => {
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export { planNativeNoteImageRender as planMobileNoteImageRender } from "@edgeever/shared/note-image-card";
|
||||
|
||||
// Expo's path joiner escapes spaces and percent signs, but leaves brackets raw.
|
||||
// Android's java.net.URI rejects those in a path. Escape only brackets here so
|
||||
// existing percent escapes stay intact and the actual filename is preserved.
|
||||
export const encodeMobileNoteImageFileUri = (uri: string): string =>
|
||||
uri.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
|
||||
@@ -26,6 +26,7 @@ import { getMobileNoteImageFontLabel } from "../lib/note-image-font-options";
|
||||
import { MobileResourceActions } from "../components/MobileResourceActions";
|
||||
import { ZoomableImagePreview } from "../components/ZoomableImagePreview";
|
||||
import type { ImageSize } from "../lib/mobile-image-zoom";
|
||||
import { encodeMobileNoteImageFileUri } from "../lib/mobile-note-image-export";
|
||||
import { SAFE_DOM_WEBVIEW_PROPS } from "../lib/mobile-dom";
|
||||
import { getNextMobileNoteSearchIndex } from "../lib/mobile-note-search";
|
||||
import { hasMobilePoster, hasMobileInfographic, hasMobileStructuredTable, hasMobileVisualDiagram, resolveMobileMemoViewerContent } from "../lib/mobile-diagram";
|
||||
@@ -972,7 +973,7 @@ export const MemoDetailModal = ({
|
||||
// earlier export when different notes share the same download filename.
|
||||
const directory = new Directory(Paths.cache, "edgeever-note-exports", event.requestId);
|
||||
if (!directory.exists) directory.create({ idempotent: true, intermediates: true });
|
||||
const file = new File(directory, event.filename);
|
||||
const file = new File(encodeMobileNoteImageFileUri(Paths.join(directory, event.filename)));
|
||||
if (file.exists) file.delete();
|
||||
file.create({ overwrite: true, intermediates: true });
|
||||
file.write(decodeBase64Chunks(imageExportChunksRef.current));
|
||||
|
||||
Reference in new issue
Block a user