From beeada6814ae9af5146047c73608682bd8366a47 Mon Sep 17 00:00:00 2001 From: AliReza Date: Mon, 12 Oct 2026 21:05:53 +0330 Subject: [PATCH] =?UTF-8?q?Offline=20wording:=20"=D8=A7=DB=8C=D9=86=D8=AA?= =?UTF-8?q?=D8=B1=D9=86=D8=AA=20=D9=85=D8=AA=D8=B5=D9=84=20=D9=86=DB=8C?= =?UTF-8?q?=D8=B3=D8=AA"=20under=20the=20app's=20splash=20image=20(Android?= =?UTF-8?q?)=20and=20in=20web=20error=20messages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- android/README.md | 4 ++-- android/app/src/main/AndroidManifest.xml | 2 +- android/app/src/main/java/com/tadrisino/app/MainActivity.kt | 6 +++--- src/lib/errors.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/README.md b/android/README.md index 8baf0f9..3f476c1 100644 --- a/android/README.md +++ b/android/README.md @@ -22,7 +22,7 @@ | `isPaymentPage` + `paysInApp()` | درگاهِ زرین‌پال داخلِ خودِ اپ باز می‌شود. اپِ فعلی آن را به مرورگرِ گوشی می‌دهد که Referer نمی‌فرستد و زرین‌پال بی‌Referer «دسترسی از این دامنه مجاز نمی‌باشد» می‌دهد؛ فعلاً فرانت از راهِ `pay.html` (با `http://`) دورش می‌زند | «پرداخت» با کارتِ بانکی: صفحه‌ی زرین‌پال و بانک داخلِ اپ، و بعد از پرداخت برگشت به اپ با پیامِ «پرداخت موفق بود» (PaymentResult). دکمه‌ی برگشت وسطِ صفحه‌ی بانک چه می‌کند را هم ببین | | اسپلشِ یک‌مرحله‌ای: `installSplashScreen()` + `setKeepOnScreenCondition` + `TadrisinoAndroid.appReady()` (`446cf36`، `ab02bb4`) | اپِ فعلی سه تکه می‌شود: اسپلشِ اندروید ← WebViewِ سفیدِ خالی ← اسپلشِ وب (آیکون + نام) ← خانه. با APKِ تازه اسپلشِ بومی تا اولین صفحه‌ی واقعیِ وب می‌ماند و مستقیم می‌رود روی همان صفحه؛ اسپلشِ وب داخلِ اپ نامرئی است (در APKِ قدیمی فقط آیکونِ بی‌نام). فرانت `appReady` را بعد از اولین صفحه‌ی غیر‌boot صدا می‌زند و APKِ قدیمی آن را ندارد، پس بی‌اثر است | روی گوشی: باز کردنِ اپ با اینترنت باید آیکون ← خانه باشد، بی‌سفیدی و بی‌تصویرِ دوم؛ اندازه‌ی آیکون روی اندروید ۱۲+ (`drawable/splash_icon.xml`: ۲۸۸dp، حاشیه ۲۲٪) | | خریدِ اشتراک از کافه‌بازار: کلیدِ RSA، `bazaarBuy` (`subscribeProduct`)، قیمتِ پیشخان (`bazaarPrices`)، «تخفیف پویا»؛ `versionCode` ۲ | بی‌این‌ها از بازار هیچ خریدی ممکن نیست (APKهای قبلی کلید نداشتند) | داخلِ اپ ← فروشگاه ← اشتراکِ سه‌ماهه: «کارتِ بانکی» پیش‌فرض، کاشیِ «کافه‌بازار» فعال با قیمتِ بازار زیرِ آن؛ خرید با حسابِ تست، برگشت با «اشتراکت فعاله»؛ در `/admin/payment/order/` سفارشِ بازار «پرداخت‌شده». یک بار هم «انصراف» در صفحه‌ی بازار | -| صفحه‌ی بی‌اتصال: `onReceivedError`/`onReceivedHttpError` ← همان تصویر + «اینترنت قطع است / کند است؛ در حال اتصال…»، تلاشِ دوباره هر ۵ ثانیه، و مجوزِ `ACCESS_NETWORK_STATE` | کاربر هرگز صفحه‌ی خطای WebView یا متنِ فنی نمی‌بیند. اتصالِ کند (بی‌خطا) عمداً هیچ متنِ اضافه نمی‌آورد و روی اسپلش می‌ماند | هواپیما روشن ← باز کردنِ اپ ← خاموش کردن: باید خودش وصل شود. سرورِ ۵۰۲ (مثلاً nginx خاموش) هم همین صفحه. اگر صفحه لود شد ولی ۱۵ ثانیه `appReady` نیامد، لاگِ ERROR و رهاشدنِ اسپلش (باگِ JS) | +| صفحه‌ی بی‌اتصال: `onReceivedError`/`onReceivedHttpError` ← همان تصویر + «اینترنت متصل نیست / کند است؛ در حال اتصال…»، تلاشِ دوباره هر ۵ ثانیه، و مجوزِ `ACCESS_NETWORK_STATE` | کاربر هرگز صفحه‌ی خطای WebView یا متنِ فنی نمی‌بیند. اتصالِ کند (بی‌خطا) عمداً هیچ متنِ اضافه نمی‌آورد و روی اسپلش می‌ماند | هواپیما روشن ← باز کردنِ اپ ← خاموش کردن: باید خودش وصل شود. سرورِ ۵۰۲ (مثلاً nginx خاموش) هم همین صفحه. اگر صفحه لود شد ولی ۱۵ ثانیه `appReady` نیامد، لاگِ ERROR و رهاشدنِ اسپلش (باگِ JS) | **اسپلش و بی‌اینترنتی همه کارِ APK است (مالک، ۲۰۲۶-۱۰-۱۱، با اپِ نصب‌شده امتحان شد).** چیزی که روی گوشی دیده می‌شود از وب قابل رفع نیست، چون وب هنوز بار نشده یا اصلاً نمی‌رسد: @@ -31,7 +31,7 @@ فقط **سفید** می‌ماند و هیچ پیامی نیست، چون HTML هرگز نرسیده و هیچ کدِ ما اجرا نمی‌شود. علتِ دقیقِ آن سفیدی (HTML نرسیده یا API نرسیده) روی فیلترشکن بازتولید **نشد**؛ APKِ تازه هر دو را با همان صفحه‌ی بی‌اتصال می‌پوشاند. - APKِ تازه (دو ردیفِ بالا) باید: ۱) با اینترنت، اسپلشِ بومی مستقیم به خانه برود و وسطش هیچ‌چیز نیفتد؛ ۲) بی‌اینترنت یا - کند، **زیرِ همان تصویرِ ثابت** بگوید «اینترنت قطع است / کند است»، نه سفید و نه متنِ خطا. + کند، **زیرِ همان تصویرِ ثابت** بگوید «اینترنت متصل نیست / کند است»، نه سفید و نه متنِ خطا. - آزمونِ پذیرش روی گوشی، پیش از انتشار: اینترنتِ عادی؛ هواپیما؛ فیلترشکنِ روشن (همان که سفید می‌داد)؛ اینترنتِ خیلی کند. در هیچ‌کدام نباید سفیدِ خالی یا صفحه‌ی خطای WebView دیده شود. diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 52596a3..bc9e101 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/android/app/src/main/java/com/tadrisino/app/MainActivity.kt b/android/app/src/main/java/com/tadrisino/app/MainActivity.kt index 327d9bd..850b400 100644 --- a/android/app/src/main/java/com/tadrisino/app/MainActivity.kt +++ b/android/app/src/main/java/com/tadrisino/app/MainActivity.kt @@ -93,7 +93,7 @@ class MainActivity : AppCompatActivity() { FrameLayout.LayoutParams(dp(288), dp(288), Gravity.CENTER)) addView(TextView(context).apply { offlineText = this - text = "اینترنت قطع است" + text = "اینترنت متصل نیست" setTextColor(Color.parseColor("#1a1a2e")) setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) layoutDirection = View.LAYOUT_DIRECTION_RTL @@ -102,7 +102,7 @@ class MainActivity : AppCompatActivity() { .apply { topMargin = dp(150) }) } - /** هیچ متنِ فنیِ خطا نشان داده نمی‌شود؛ فقط یکی از دو جمله: «قطع است» (شبکه‌ای نیست) یا «کند است». */ + /** هیچ متنِ فنیِ خطا نشان داده نمی‌شود؛ فقط یکی از دو جمله: «متصل نیست» (شبکه‌ای نیست) یا «کند است». */ private fun hasInternet(): Boolean { val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val caps = cm.getNetworkCapabilities(cm.activeNetwork) ?: return false @@ -110,7 +110,7 @@ class MainActivity : AppCompatActivity() { } private fun showOffline() { - offlineText.text = if (hasInternet()) "اینترنت کند است؛ در حال اتصال…" else "اینترنت قطع است؛ در حال اتصال…" + offlineText.text = if (hasInternet()) "اینترنت کند است؛ در حال اتصال…" else "اینترنت متصل نیست؛ در حال اتصال…" if (!offlineShown) { offlineShown = true webView.visibility = View.INVISIBLE // صفحه‌ی خطای پیش‌فرضِ WebView دیده نشود diff --git a/src/lib/errors.ts b/src/lib/errors.ts index 4c46b9e..3722aef 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -10,8 +10,8 @@ const PERSIAN = /[\u0600-\u06FF]/; export function friendlyError(err: unknown, fallback = 'یه مشکلی پیش اومد، دوباره امتحان کن'): string { if (!(err instanceof ApiError)) return fallback; if (err.isNetwork) { - if (typeof navigator !== 'undefined' && navigator.onLine === false) return 'اینترنت قطع است؛ اتصالت رو چک کن و دوباره امتحان کن'; - return err.timedOut ? 'اینترنت کند است؛ کمی صبر کن و دوباره امتحان کن' : 'اینترنت قطع یا ناپایدار است؛ دوباره امتحان کن'; + if (typeof navigator !== 'undefined' && navigator.onLine === false) return 'اینترنت متصل نیست؛ اتصالت رو چک کن و دوباره امتحان کن'; + return err.timedOut ? 'اینترنت کند است؛ کمی صبر کن و دوباره امتحان کن' : 'اینترنت متصل نیست یا ناپایداره؛ دوباره امتحان کن'; } if (err.isRateLimited) return err.detail && PERSIAN.test(err.detail) && !err.detail.startsWith('خطا') ? err.detail : 'زیادی تلاش کردی؛ چند لحظه صبر کن'; if (err.isProviderDown) return 'این سرویس الان در دسترس نیست؛ کمی بعد دوباره امتحان کن';