diff --git a/public/offline.html b/public/offline.html new file mode 100644 index 0000000..6b2c8c1 --- /dev/null +++ b/public/offline.html @@ -0,0 +1,50 @@ + + + + + +مدستاگرام + + + + مدستاگرام +

اتصال برقرار نمی‌باشد

+

به نظر می‌رسد به اینترنت وصل نیستید. اتصال خود را بررسی کنید و دوباره تلاش کنید.

+ + + diff --git a/public/service-worker.js b/public/service-worker.js index ff777cb..2a172c4 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -43,10 +43,11 @@ self.addEventListener("notificationclick", (event) => { ); }); -const CACHE_NAME = "pwa-cache-v11"; +const CACHE_NAME = "pwa-cache-v12"; const PRECACHE_URLS = [ "/", + "/offline.html", "/manifest.webmanifest", "/manifest.json", "/images/icons/192x192.png", @@ -82,7 +83,9 @@ self.addEventListener("fetch", (event) => { const url = new URL(event.request.url); if (event.request.mode === "navigate") { - event.respondWith(fetch(event.request)); + event.respondWith( + fetch(event.request).catch(() => caches.match("/offline.html")) + ); return; } diff --git a/src/app/(projects)/academy/[id]/[title]/CourseClient.tsx b/src/app/(projects)/academy/[id]/[title]/CourseClient.tsx index ac39a17..2eddca2 100644 --- a/src/app/(projects)/academy/[id]/[title]/CourseClient.tsx +++ b/src/app/(projects)/academy/[id]/[title]/CourseClient.tsx @@ -655,6 +655,7 @@ useEffect(() => { key={selectedVideo?._id || ""} className="w-full aspect-video" controls + playsInline controlsList="nodownload noplaybackrate" onContextMenu={preventDownload} onKeyDown={preventDownload} diff --git a/src/app/about-us/page.tsx b/src/app/about-us/page.tsx index 6e29c34..7c9b7b0 100644 --- a/src/app/about-us/page.tsx +++ b/src/app/about-us/page.tsx @@ -5,9 +5,17 @@ import RoundedDiv from "@/components/elements/RoundedDiv"; import EditPageHeader from "@/components/settings/EditPageHeader"; import Link from "next/link"; import { useTranslation } from "react-i18next"; +import { isAndroidDevice } from "@/lib/pwa/install"; +import { buildStorageUrl } from "@/components/main/BaseUrl"; +import { ANDROID_APP_VERSION } from "@/lib/pwaConfig"; + +// عین PwaInstallPrompt.tsx: مسیر مستقیمِ فایل APK که بک‌اند بدون روتِ جدید سرو می‌کنه +const ANDROID_APK_URL = buildStorageUrl("/downloads/modstagram.apk"); function AboutUs() { const { t } = useTranslation("common"); + // فقط اندروید — طبق خواسته‌ی صریح کاربر توی iOS این دکمه نمایش داده نشه + const isAndroid = isAndroidDevice(); return ( @@ -23,12 +31,26 @@ function AboutUs() { 02167586 -
- - - {t("aboutPage.sendTicket")} - - +
+
+ + + {t("aboutPage.sendTicket")} + + + {isAndroid ? ( + + + {t("aboutPage.downloadApp")} + + + ) : null} +
+ {isAndroid ? ( + + {t("aboutPage.appVersion", { version: ANDROID_APP_VERSION })} + + ) : null}
diff --git a/src/app/globals.css b/src/app/globals.css index dceb76f..9c05253 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -618,6 +618,7 @@ select { .header-offline { background: linear-gradient(180deg, rgba(220, 38, 38, 0.92) 0%, rgba(185, 28, 28, 0.88) 100%) !important; backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); } .header-syncing .brand-logo { opacity: 0; @@ -631,6 +632,7 @@ select { .tab-active-glass { background: rgba(255, 255, 255, 0.35); backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.55); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5ec39ea..c0affff 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -34,6 +34,7 @@ export async function generateMetadata(): Promise { authors: [{ name: "Modstagram", url: "https://modstagram.com" }], creator: "Modstagram", manifest: "/manifest.webmanifest", + applicationName: site.name, icons: { icon: [ { url: "/favicon.png", type: "image/png", sizes: "32x32" }, @@ -67,8 +68,6 @@ export async function generateMetadata(): Promise { google: "yVjB5yKPchPUtxl33GWVyMvjH6wCEInqEvaH7ZsXXMo", }, other: { - "theme-color": "#FF107D", - "mobile-web-app-capable": "yes", "msapplication-TileColor": "#FF107D", samandehi: "522190795", }, diff --git a/src/app/settings/chats/shop/[shopId]/[buyerId]/page.tsx b/src/app/settings/chats/shop/[shopId]/[buyerId]/page.tsx index d7e7aa3..e8d3eeb 100644 --- a/src/app/settings/chats/shop/[shopId]/[buyerId]/page.tsx +++ b/src/app/settings/chats/shop/[shopId]/[buyerId]/page.tsx @@ -1,17 +1,17 @@ "use client"; import { useEffect, useRef, useState } from "react"; -import { useParams } from "next/navigation"; +import { useParams, useRouter } from "next/navigation"; import Container from "@/components/elements/Container"; import ProfileAvatar from "@/components/main/ProfileAvatar"; import LocalePageShell from "@/components/i18n/LocalePageShell"; import ChatBoldIcon from "@/components/chat/ChatBoldIcon"; import { chatHeaderCircleBtn, chatHeaderInfoPill, chatHeaderGlassStyle } from "@/components/chat/ChatHeader"; import VideoMessageBubble from "@/components/chat/VideoMessageBubble"; -import BackButton from "@/components/ui/BackButton"; import IOSSpinner from "@/components/ui/IOSSpinner"; import useAxios from "@/hooks/useAxios"; import { cn } from "@/lib/utils"; +import { glassBackdropStyle } from "@/lib/glassBackdrop"; import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; import { formatBubbleTime } from "@/lib/chat/formatMessageTime"; import { @@ -58,6 +58,7 @@ export default function ShopChatPage() { const params = useParams<{ shopId: string; buyerId: string }>(); const { shopId, buyerId } = params; const { request } = useAxios(); + const router = useRouter(); const [messages, setMessages] = useState(null); const [counterpart, setCounterpart] = useState(null); @@ -162,12 +163,15 @@ export default function ShopChatPage() { dir="rtl" className="pointer-events-auto mx-auto flex max-w-lg items-center gap-2" > - router.back()} className={chatHeaderCircleBtn} style={chatHeaderGlassStyle} - /> + aria-label={t("chats.actions.back")} + > + +
@@ -291,7 +295,10 @@ export default function ShopChatPage() {
-
+