first commit

This commit is contained in:
2026-07-21 16:50:58 +02:00
commit 256599626e
407 changed files with 30489 additions and 0 deletions
@@ -0,0 +1,93 @@
import { Capacitor } from "@capacitor/core";
import { Share } from "@capacitor/share";
import { trackEvent } from "../../infra/analytics";
export type RecipeShareDeps = Readonly<{
title: string;
body: string;
url: string;
variantIdForTrack: string;
strings: { shareCopied: string; shareCopyFailed: string };
setShareFeedback: (msg: string | null) => void;
clearShareFeedbackTimer: () => void;
flashShareFeedback: (message: string) => void;
}>;
/**
* Partage recette : Share natif (Capacitor / Web Share API) avec repli presse-papiers.
* Effets de bord analytics conservés ici pour garder lUI découplée du détail des plateformes.
*/
export async function shareRecipeWithFallback(deps: RecipeShareDeps): Promise<void> {
const trackShareSuccess = () => {
trackEvent("recipe", "share", deps.variantIdForTrack);
};
if (Capacitor.isNativePlatform()) {
try {
await Share.share({
title: deps.title,
text: deps.body,
url: deps.url || undefined,
dialogTitle: deps.title
});
deps.clearShareFeedbackTimer();
deps.setShareFeedback(null);
trackShareSuccess();
return;
} catch (error: unknown) {
if (error instanceof DOMException && error.name === "AbortError") return;
const msg =
error instanceof Error
? error.message
: typeof error === "string"
? error
: "";
if (/cancel/i.test(msg) || msg.toLowerCase().includes("user did not share")) return;
}
}
const shareWithNative = async () => {
const basePayload: ShareData = { title: deps.title, text: deps.body };
if (deps.url) {
const withUrl: ShareData = { ...basePayload, url: deps.url };
if (typeof navigator.canShare !== "function" || navigator.canShare(withUrl)) {
await navigator.share(withUrl);
return;
}
}
await navigator.share(basePayload);
};
if (typeof navigator.share === "function") {
try {
await shareWithNative();
deps.clearShareFeedbackTimer();
deps.setShareFeedback(null);
trackShareSuccess();
return;
} catch (error: unknown) {
const name =
error instanceof Error || error instanceof DOMException
? error.name
: typeof error === "object" &&
error !== null &&
"name" in error &&
typeof (error as { name: unknown }).name === "string"
? (error as { name: string }).name
: "";
if (name === "AbortError") return;
}
}
try {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(deps.body);
deps.flashShareFeedback(deps.strings.shareCopied);
trackShareSuccess();
} else {
deps.flashShareFeedback(deps.strings.shareCopyFailed);
}
} catch {
deps.flashShareFeedback(deps.strings.shareCopyFailed);
}
}