Refine share flows
Build and push image / build (push) Successful in 1m16s

This commit is contained in:
alexandrev-tibco
2026-05-05 11:50:28 +02:00
parent b8f9345015
commit e52dd7da17
3 changed files with 46 additions and 6 deletions
+23 -3
View File
@@ -7,7 +7,7 @@ import Pitch from "@/components/Pitch";
import PlayerSearch from "@/components/PlayerSearch"; import PlayerSearch from "@/components/PlayerSearch";
import ShareResult from "@/components/ShareResult"; import ShareResult from "@/components/ShareResult";
import StatsPanel from "@/components/StatsPanel"; import StatsPanel from "@/components/StatsPanel";
import { buildShareText, buildShareUrl } from "@/lib/share"; import { buildGlobalStatsShareText, buildShareText, buildShareUrl } from "@/lib/share";
import { import {
DIFFICULTIES, DIFFICULTIES,
MAX_ATTEMPTS, MAX_ATTEMPTS,
@@ -59,6 +59,7 @@ export default function Home() {
[dateKey, progress], [dateKey, progress],
); );
const shareText = useMemo(() => buildShareText(dateKey, progress, t), [dateKey, progress, t]); const shareText = useMemo(() => buildShareText(dateKey, progress, t), [dateKey, progress, t]);
const globalStatsShareText = useMemo(() => buildGlobalStatsShareText(stats, t), [stats, t]);
useEffect(() => { useEffect(() => {
const savedLocale = window.localStorage.getItem("hidden11-locale") as Locale | null; const savedLocale = window.localStorage.getItem("hidden11-locale") as Locale | null;
@@ -190,6 +191,25 @@ export default function Home() {
); );
} }
async function shareGlobalStats() {
const homeUrl = typeof window === "undefined" ? "https://hidden11.app" : window.location.origin.replace(/\/$/, "");
if (navigator.share) {
await navigator.share({
title: "hidden11",
text: globalStatsShareText,
url: homeUrl,
});
return;
}
window.open(
`https://twitter.com/intent/tweet?text=${encodeURIComponent(globalStatsShareText)}&url=${encodeURIComponent(homeUrl)}`,
"_blank",
"noopener,noreferrer",
);
}
const actionButtons = ( const actionButtons = (
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<button <button
@@ -367,7 +387,7 @@ export default function Home() {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
type="button" type="button"
onClick={shareCurrentResult} onClick={shareGlobalStats}
className="h-9 rounded-full bg-emerald-400 px-4 text-xs font-black uppercase tracking-wide text-pitch-950 transition hover:bg-emerald-300" className="h-9 rounded-full bg-emerald-400 px-4 text-xs font-black uppercase tracking-wide text-pitch-950 transition hover:bg-emerald-300"
> >
{t.shareNow} {t.shareNow}
@@ -382,7 +402,7 @@ export default function Home() {
</button> </button>
</div> </div>
</div> </div>
<StatsPanel stats={stats} t={t} /> <StatsPanel showLead={false} stats={stats} t={t} />
</div> </div>
</div> </div>
) : null} ) : null}
+3 -2
View File
@@ -3,18 +3,19 @@ import { formatElapsed } from "@/lib/time";
import type { GlobalStats } from "@/lib/types"; import type { GlobalStats } from "@/lib/types";
type StatsPanelProps = { type StatsPanelProps = {
showLead?: boolean;
stats: GlobalStats; stats: GlobalStats;
t: Dictionary; t: Dictionary;
}; };
export default function StatsPanel({ stats, t }: StatsPanelProps) { export default function StatsPanel({ showLead = true, stats, t }: StatsPanelProps) {
const maxDistribution = Math.max(...Object.values(stats.winDistribution), 1); const maxDistribution = Math.max(...Object.values(stats.winDistribution), 1);
return ( return (
<section className="rounded-lg border border-white/10 bg-white/[0.06] p-4"> <section className="rounded-lg border border-white/10 bg-white/[0.06] p-4">
<div> <div>
<h3 className="text-sm font-black uppercase text-white/55">{t.stats}</h3> <h3 className="text-sm font-black uppercase text-white/55">{t.stats}</h3>
<p className="mt-1 text-sm text-emerald-100">{t.statsLead}</p> {showLead ? <p className="mt-1 text-sm text-emerald-100">{t.statsLead}</p> : null}
</div> </div>
<div className="mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3"> <div className="mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3">
+20 -1
View File
@@ -1,7 +1,7 @@
import { DIFFICULTIES, getPuzzleNumber, MAX_ATTEMPTS, POSITIONS } from "./game-engine"; import { DIFFICULTIES, getPuzzleNumber, MAX_ATTEMPTS, POSITIONS } from "./game-engine";
import type { Dictionary } from "./i18n"; import type { Dictionary } from "./i18n";
import { formatElapsed } from "./time"; import { formatElapsed } from "./time";
import type { DailyProgress, Difficulty } from "./types"; import type { DailyProgress, Difficulty, GlobalStats } from "./types";
const emoji = { const emoji = {
correct: "🟩", correct: "🟩",
@@ -57,6 +57,25 @@ export function buildShareText(dateKey: string, progress: DailyProgress, t: Dict
].join("\n"); ].join("\n");
} }
export function buildGlobalStatsShareText(stats: GlobalStats, t: Dictionary): string {
const homeUrl = "https://hidden11.app";
const bestTime = stats.bestSeconds === null ? "0:00" : formatElapsed(stats.bestSeconds);
return [
"┏━ hidden11.app ━┓",
"⚽ hidden11 global stats",
"",
`${t.played}: ${stats.gamesPlayed}`,
`${t.streak}: ${stats.currentStreak}`,
`${t.maxStreak}: ${stats.maxStreak}`,
`${t.perfectDays}: ${stats.perfectDays}`,
`${t.averageTime}: ${formatElapsed(stats.averageSeconds)}`,
`${t.bestTime}: ${bestTime}`,
"",
`Play: ${homeUrl}`,
].join("\n");
}
export function buildShareUrl(_dateKey: string, _progress: DailyProgress, origin = "https://hidden11.app"): string { export function buildShareUrl(_dateKey: string, _progress: DailyProgress, origin = "https://hidden11.app"): string {
return origin.replace(/\/$/, ""); return origin.replace(/\/$/, "");
} }