The selected companion everywhere, each with a small trait; next-APK notes

- state/companion.ts: one store for the chosen companion (also in localStorage so splash/login show it).
  BrandMark (the orange «π» tile) now shows the companion's symbol (Σ Δ π ω) in its colour; screen-header
  mascots, loaders and empty/error states default to it; the assistant is «از {name} بپرس» with its face,
  colour and wording; the shop, lesson and quiz «ask» buttons name it; the active tab takes its tint.
- Traits, all client-side and light: Σ sigma keeps a running tally of correct answers in the quiz header;
  Δ delta shows a flame «×N» chip and an extra buzz for answers in a row; π pi gives a short solving tip
  after a wrong answer; ω omega throws gold confetti at the end of every island whatever the score.
  Each companion's «correct» sound is pitched differently; confetti uses its colours. Characters screen
  lists each trait.
- android/README.md: what MainActivity.kt has that the installed APK lacks (vibrate bridge, media gesture,
  in-app gateway + paysInApp), what to check on a phone after building, signing owner, Bazaar policy note.

Checked in headless Chrome with Sigma, Delta and Omega selected (home, assistant, shop, characters, quiz).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-10 18:51:19 +03:30
parent 737414f246
commit 8a61cb25b8
21 changed files with 256 additions and 69 deletions

View File

@@ -5,15 +5,40 @@
محصولِ دیجیتال را فقط از راهِ خودش می‌پذیرد. باقیِ اپ همان فرانتِ وب است و با دیپلویِ
فرانت به‌روز می‌شود، بی‌آن‌که نسخه‌ی تازه‌ی اپ لازم باشد.
> ⚠️ **این پروژه هنوز یک بار هم build نشده.** روی ماشینی نوشته شد که Android SDK نداشت
> (۲۰۲۶-۱۰-۰۳). APIِ Poolakey از README خودِ کتابخانه است. اولین کار: باز کردن در Android
> Studio، build، و یک خریدِ واقعی روی گوشی.
> **ساخت و امضا با هم‌تیمی است (MH-W90، m.hassanabadi)** با روشِ امضای خودش (`my-release-key.keystore` +
> propertyهای Gradle)؛ تصمیمِ مالک این است که همان روش بماند. پیش از دست زدن به امضا از مالک بپرس و هرگز
> keystore را commit نکن. `applicationId` واقعی `com.tadrisino.math.app` است (از APKِ ساخته‌شده با aapt2).
> هیچ خریدِ واقعیِ بازار هنوز آزموده نشده.
## نسخه‌ی بعدیِ APK — چه چیزی در کد هست و در اپِ نصب‌شده نیست
این‌ها در `MainActivity.kt` نوشته شده‌اند (۱۴۰۵-۰۷، `468f5b2` و `737414f`) ولی هیچ‌کدام build نشده‌اند؛ اپی که الان روی
گوشی‌هاست بدونِ آن‌هاست. فرانت با هر دو نسخه کار می‌کند (اگر پل نبود، راهِ قدیم را می‌رود).
| تغییر | چرا | بعد از build روی گوشی بسنج |
|---|---|---|
| `TadrisinoAndroid.vibrate(patternJson)` با Vibratorِ گوشی | `navigator.vibrate` در WebView همیشه کار نمی‌کند؛ مالک گفت اپ لرزش ندارد | انتخابِ گزینه‌ی آزمون، جوابِ درست/غلط، پایانِ جزیره و صفحه‌ی «روزِ پیاپی» باید بلرزند؛ با خاموش کردنِ «صداها» در پروفایل نه |
| `mediaPlaybackRequiresUserGesture = false` | صداهای رابط بعد از پاسخِ سرور پخش می‌شوند، نه در لحظه‌ی لمس | صدای جوابِ درست/غلط و پایانِ تمرین |
| `isPaymentPage` + `paysInApp()` | درگاهِ زرین‌پال داخلِ خودِ اپ باز می‌شود. اپِ فعلی آن را به مرورگرِ گوشی می‌دهد که Referer نمی‌فرستد و زرین‌پال بی‌Referer «دسترسی از این دامنه مجاز نمی‌باشد» می‌دهد؛ فعلاً فرانت از راهِ `pay.html` (با `http://`) دورش می‌زند | «پرداخت» با کارتِ بانکی: صفحه‌ی زرین‌پال و بانک داخلِ اپ، و بعد از پرداخت برگشت به اپ با پیامِ «پرداخت موفق بود» (PaymentResult). دکمه‌ی برگشت وسطِ صفحه‌ی بانک چه می‌کند را هم ببین |
پیشنهادهایی که هنوز نوشته نشده‌اند:
- **«برای خروج دوباره بزن»**: دکمه‌ی برگشتِ گوشی حالا قدم‌به‌قدم در خودِ وب عقب می‌رود (`src/nav/Navigator.tsx`) و
از خانه یک‌راست بیرون می‌رود. اگر تأییدِ خروج خواستید، در `handleOnBackPressed` وقتی `!webView.canGoBack()` یک
Toast بدهید و فقط برگشتِ دوم در دو ثانیه `finish()` کند. در وب شدنی نیست (کروم ورودیِ history بی‌لمس را رد می‌کند).
- `versionCode`/`versionName` را برای هر نسخه بالا ببرید؛ هنوز ۱ و 1.0.0 است.
قانونِ بازار: داخلِ اپِ بازار حالا پرداخت با درگاه هم پیشنهاد می‌شود (خواستِ مالک). بازار پرداختِ محتوای دیجیتال بیرون از
پرداختِ درون‌برنامه‌ای را محدود می‌کند؛ پیش از انتشار در بازار این را با بازار یا مالک روشن کنید.
ساخت روی مکِ مالک: SDK در `~/Library/Android/sdk`، JDK 17 (`/opt/homebrew/opt/openjdk@17`)، و چون Google Maven از
ایران بی‌VPN ۴۰۴ می‌دهد، `~/.gradle/init.d/google-mirror.gradle` آینه‌ی Aliyun را اضافه می‌کند؛ ساختِ اول ~۹ دقیقه.
## پیش از build — سه چیز از پیشخانِ بازار (سنیور / حسابِ شرکت)
| چه | کجا گذاشته می‌شود | وضعیت |
|---|---|---|
| اسمِ پکیج | `applicationId` در `app/build.gradle.kts` | `com.tadrisino.app` حدس است؛ تأیید نشده |
| اسمِ پکیج | `applicationId` در `app/build.gradle.kts` | `com.tadrisino.math.app` (APKِ ساخته‌شده)؛ ثبتش در پیشخان تأیید نشده |
| کلیدِ RSAِ عمومیِ اپ | `BAZAAR_RSA_KEY` در `app/build.gradle.kts` | ندارد؛ بدونِ آن خرید شروع نمی‌شود |
| SKUِ هر بسته (محصولِ **مصرف‌شدنی**) | پنلِ ادمینِ بک‌اند: `/admin/subscription/plan/` ← «Bazaar sku» | هیچ‌کدام تعریف نشده |