{
  "app": "KumaLive คุมะไลฟ์",
  "updated": "2026-10-14T13:25:46.074Z",
  "android": {
    "version": "0.26.0",
    "file": "KumaLive-0.26.0.apk",
    "size": 49782540,
    "date": "2026-10-14"
  },
  "ios": {
    "version": "0.26.0",
    "file": "KumaLive-0.26.0.ipa",
    "size": 38973758,
    "date": "2026-10-14"
  },
  "history": [
    {
      "version": "0.26.0",
      "date": "2026-10-14",
      "notes": [
        "KumaFX \"Momo-exact\" — ฟิลเตอร์ความงามเขียนใหม่ทั้งหมดให้ตรงไปป์ไลน์ Momo Live (ByteDance Effect SDK) ระดับพิกเซล ทั้ง Android (GLES3) และ iOS (Metal; โค้ดครบ ยังไม่ได้ xcodebuild เพราะไม่มี Mac): แกะ bundle/native ละเอียด (momo-apk/beauty_re/MOMO_FILTER_SPEC.md, REA+Ghidra) → เขียน shader/graph ใหม่ทุก pass (SmoothV10 12 pass, whiten_clear, sharpen, palette, filter, reshape mesh-warp, whiten_teeth, style_makeup baixi) เรียงตาม zorder จริง · จุดบนหน้า: MediaPipe 478 → ผัง tt_face 106+174 ด้วยตัวแปลงของเราเอง · asset ทุกชิ้นเป็นของเรา (LUT 33 ตัว fit ≤2/255, มาสก์ผิว/สีผิว/ฟัน fit จากค่าวัด, สนามปรับหน้า fit RMS ≤0.15% ของหน้า, ชุดแต่งหน้า baixi วาดด้วย GPT-6) — ไม่มีไฟล์ ByteDance ในแอป",
        "ผลวัดบน Redmi เทียบ shader ต้นฉบับ (เฉลี่ย /255): Reset 0.31, Default2 0.34, เนียน 0.07, ขาว+ใส 0.19, ฟิลเตอร์ 0.39, ฟันขาว 0.00, baixi D1 0.43, ปรับหน้า ≤1.0 — ทุกเคส ≤0.5 (เป้า ≤1.5) · 7.6 ms/เฟรม @720p",
        "แผง ✨ ครบตาม Momo: โหมดสวย / ปรับแต่งใบหน้า (หน้าตัด คาง จมูก หน้าเล็ก ปาก ฟันขาว ไรผม โหนกแก้ม) / สไตล์แต่งหน้า (baixi; สไตล์อื่นรอข้อมูล) / คุณภาพรูป (+hue) / ฟิลเตอร์ 10 แบบของ Momo · พรีเซ็ต รีเซ็ต/ค่าเริ่มต้น 1-2-3 = ตาราง Momo เป๊ะ · ค่าที่บันทึกไว้เดิม migrate อัตโนมัติ",
        "เครื่องมือ: harness อ้างอิงรัน shader ต้นฉบับบน PC (beauty_re/harness), validate.py device 9 เคส, ops/pack-fx-assets.py / ios/scripts/pack-fx-assets.sh"
      ]
    },
    {
      "version": "0.25.0",
      "date": "2026-09-13",
      "notes": [
        "ฟิลเตอร์ความงาม KumaFX บน iOS (ios/KumaLive/Fx/): พอร์ตจาก Android 1:1 เป็น Metal — มาสก์ผิวจาก face mesh + สีผิวปรับตามหน้า, bilateral + คืน texture, ขาว/ใส/โกลว์/ตาใส, ปรับหน้า mesh warp (เรียว/คาง/ตา/จมูก), คมชัด+คุณภาพรูป+LUT 7 แบบ, One-Euro + ROI tracking, ค่าเริ่มต้น/พรีเซ็ต Momo ชุดเดียวกัน · จุดตรวจจับหน้าใช้ MediaPipe Tasks Vision (478 จุด) โหลด xcframework ด้วย ios/scripts/fetch-deps.sh (ไม่ใช้ CocoaPods) · เกี่ยวเข้ากับกล้องผ่าน FxProcessor ระหว่าง capturer กับ WebRTC (ปิด = ส่งผ่านตรง, ล้มเกิน 20 ครั้งปิดตัวเอง) · แผง ✨ ใช้งานจริงแล้ว",
        "ทดสอบออฟไลน์บน simulator: ผลต่างจาก Android เฉลี่ย 0.9/255 (ภาพเดียวกัน), ฉากหลัง Δ≈0, mask ถึงไรผม ไม่มีกรอบ · ยังต้องวัดความเร็วบน iPhone จริง (เป้า ≤12 ms/เฟรม)",
        "iOS: แถบบนห้องไลฟ์ไม่ทับนาฬิกา/Dynamic Island, จำล็อกอินบน build ที่ไม่ได้เซ็น, สคริปต์ ios/scripts/build-ipa.sh สร้าง IPA สำหรับ sideload"
      ]
    },
    {
      "version": "0.24.0",
      "date": "2026-09-12",
      "notes": [
        "แอป iOS (native SwiftUI) รุ่นแรก ios/ — เขียนตามแอป Android 1:1: ล็อกอิน/สมัคร, ฟีดไลฟ์+ค้นหา, ห้องไลฟ์ (WebRTC ผ่าน mediasoup offer/answer เดิม, แบ่งจอแขก, แชต, ของขวัญแบบ Momo 2×4, คอมโบการ์ดตั๋ว+เลขวิ่ง, โบนัสแตก, แจ้งเตือนมุมขวาบน), ไลฟ์เอง (กล้องหน้า 720p, ภาพย่อ, แขก/VS, แผงความงามแบบ Momo — ฟิลเตอร์จริงบน iOS เป็นเฟสถัดไป), หน้า \"ฉัน\" ครบ (กระเป๋า/เติมเงิน/ถอน/คลัง/ร้าน/ภารกิจ/กิลด์/VIP/สถิติ/ตั้งค่า), อันดับ, ระดับ, โปรไฟล์ · โปรเจกต์สร้างด้วย XcodeGen (ios/project.yml), แพ็กเกจ WebRTC (stasel) + SDWebImage (WebP เคลื่อนไหว)",
        "บิ้ลด์ iOS จากเครื่องนี้ได้โดยไม่มี Mac ในมือ: ios/scripts/build-remote.sh ส่งโค้ดผ่าน VPS → Mac (MacinCloud ไม่ให้ SSH) ดึงไปบิ้ลด์ผ่าน \"สะพานคำสั่ง\" server/ops/macbridge/ (pm2 macbridge :3299, Mac วน ~/mb.sh) → ดึง log/ภาพหน้าจอ simulator กลับ · + GitHub Actions ios.yml สำรอง",
        "บิ้ลด์ผ่าน (Xcode 26.6, simulator iPhone 17) และรันถึงหน้าล็อกอินแล้ว — ยังไม่ได้ทดสอบล็อกอิน/ห้องไลฟ์บน iPhone จริง (ต้องใช้บัญชี Apple Developer สำหรับเครื่องจริง)"
      ]
    },
    {
      "version": "0.23.2",
      "date": "2026-09-12",
      "notes": [
        "ปรับคางไม่ดึงปากแล้ว — ยกเฉพาะช่วงใต้ริมฝีปากล่างถึงปลายคาง ริมฝีปากไม่ขยับ"
      ]
    },
    {
      "version": "0.23.1",
      "date": "2026-09-12",
      "notes": [
        "ค่าความงามเริ่มต้น/พรีเซ็ต 1-2-3 คัดลอกจาก Momo (บันทึกตารางแปลงที่ fx/MOMO_VALUES.md)"
      ]
    },
    {
      "version": "0.23.0",
      "date": "2026-09-12",
      "notes": [
        "เมนูปรับความงามแบบ Momo (แท็บ โหมดสวย/ปรับแต่งใบหน้า/คุณภาพรูป/ฟิลเตอร์ + สไลเดอร์ 0–100 + ค่าเริ่มต้น 1/2/3) + คุณภาพรูป (อุณหภูมิสี/อิ่มตัว/สว่าง/เปรียบต่าง) + แก้ปรับแรงแล้วหน้าลอย/เห็นกรอบ (ขอบหน้าไล่กว้าง ไม่มีขั้น, ขาวสูงสุด +10%, คืน texture ≥42%, mesh ไม่สร้างใหม่ถี่)"
      ]
    },
    {
      "version": "0.22.3",
      "date": "2026-09-12",
      "notes": [
        "KumaFX: mask ผิวแบบ Momo — น้ำหนักต่อจุดวาดผ่าน face mesh (ไล่นุ่มรอบคิ้ว/ตา/ปาก ไม่มีกรอบ) ตัดส่วนคอ/หน้าอก, คมชัดทั้งเฟรมเบาๆ"
      ]
    },
    {
      "version": "0.22.2",
      "date": "2026-09-12",
      "notes": [
        "KumaFX: ครอปหน้าให้ตัวตรวจจับ (ROI ความละเอียดสูง จุดนิ่งขึ้น), ต่อ mask หน้าผากถึงไรผม + ในวงหน้าไม่พึ่งสีผิว, One-Euro นิ่งตอนหยุด/ทำนายเฉพาะตอนขยับ"
      ]
    },
    {
      "version": "0.22.1",
      "date": "2026-09-11",
      "notes": [
        "KumaFX: แก้หน่วง/เงา/หลุดตรงหน้าผาก — ตรวจหน้าทุกเฟรม + ทำนายตำแหน่งชดเชย latency, One-Euro ไวขึ้น (2.4Hz), MediaPipe confidence ต่ำลง (หน้าใหญ่ชิดกล้องไม่หลุด), mask ตามเฟรมใหม่ 70%, สีผิว σ กว้างขึ้น + จุดหน้าผาก"
      ]
    },
    {
      "version": "0.22.0",
      "date": "2026-09-11",
      "notes": [
        "ฟิลเตอร์บิวตี้เขียนใหม่ทั้งหมด (Android fx/) หลังแกะไปป์ไลน์ ByteDance Effect ในแอป Momo เป็นแบบอ้างอิงพฤติกรรม (โค้ด/asset เป็นของเราเองล้วน ไม่คัดลอก): มาสก์ผิวจากรูปทรงหน้าจริง (mesh 478 จุด + คอ) × สีผิวที่วัดจากแก้ม/หน้าผากของคนนั้น ๆ × กันตา/คิ้ว/ปาก/รูจมูกเสมอ (ตาปิดก็กัน) + นิ่งตามเวลา · เนียนด้วย bilateral 2 ชั้น (รัศมีตามขนาดหน้า) + คืน texture 35–60% + ยกจุดด่าง + กันไรผม/หนวด · ขาว = ยกโทนกลางบนผิวเท่านั้น (ไม่รั่วออกนอกหน้า ไม่ยกเงา ไม่ย้อมสี) · สไลเดอร์ใหม่ \"ใส\" (S-curve) · คมชัดเฉพาะนอกผิว · ตาสว่างเฉพาะตอนลืมตา · One-Euro filter ลดสั่น/หน่วงของจุดหน้า",
        "ปรับรูปหน้าแบบ mesh warp (Delaunay 990 สามเหลี่ยม + วงนอกตรึง): หน้าเรียวเป็น V-line ทั้งแนวกราม, คาง, ตาโต (ไม่กินคิ้ว), จมูก — พื้นหลังนอกวงหน้าไม่บิดเลย (วัด Δ=0)",
        "ฟิลเตอร์สี LUT 7 แบบของเราเอง (ธรรมชาติ/ชมพูนุ่ม/ฟิล์มซีด/อุ่นทอง/เย็นฟ้า/สดใส/คลีน) shader highp · ค่าเริ่มต้น \"ธรรมชาติ\" เบาลง (เนียน .5 ขาว .22 ใส .2 คม .25 เรียว .18 ตา .12) พรีเซ็ต ธรรมชาติ/เนียนใส/ฟิลเตอร์จีน/สุด · ยังปิดเป็นค่าเริ่มต้น (เปิดที่ ✨)",
        "ผลวัดบนเฟรมจริง: ฉากหลัง Δ 0, ผิวคง texture 75–80%, สีผิว ΔH ≤0.3° ΔS ≤1.2%, ตา/ปาก Δ≈0 · CPU 10–12 ms/เฟรม @720p (Redmi 15C) · ประมวลผลกล้องหมุนบน GPU (ลด 14.8→0.2 ms)",
        "RE: momo-apk/beauty_re/ (ถอดรหัส bundle .enc ได้ 100%, รายงาน BUNDLE_RE/JAVA_RE, PUENFX_REVIEW)"
      ]
    },
    {
      "version": "0.21.1",
      "date": "2026-09-07",
      "notes": [
        "การ์ดคอมโบ: ลดช่องว่างระหว่างตัวสัตว์กับชื่อ (ช่อง 64→46dp / PWA ย้ายตัวสัตว์ไปซ้ายสุด) + พื้นตั๋วโปร่ง 80% เบลอหลัง"
      ]
    },
    {
      "version": "0.21.0",
      "date": "2026-09-08",
      "notes": [
        "การ์ดคอมโบดีไซน์ใหม่ \"ตั๋วลูกกวาด\" (เจ้าของเลือกแบบ B จาก 4 คอนเซปต์; Android + PWA): กรอบเดียวรวมทุกอย่าง — พื้นขาว-ชมพู ขอบเส้นประชมพูในกรอบทอง วงนอกน้ำเงินกรมท่า, แมวกวัก/สัตว์โผล่พ้นขอบซ้าย, ชื่อผู้ส่ง+ \"ส่ง … ×n\" สีเข้มอ่านชัด, ตัวนับทองใหญ่ขวา · โบนัสแตกเป็นตราเหรียญทองเอียง −6° ทับมุมขวาบนของตั๋ว (BONUS! x{mult} 🪙 +{coins}) เด้ง+แสงวิ่ง 3.5 วิ",
        "ตัวเลขคอมโบวิ่งแบบสล็อต/หวยออก: ทุกหลักหมุนขึ้นตามแนวตั้ง (หมุนเกิน 1 รอบ) แล้วหยุดที่เลขใหม่ ~0.38 วิ หลักที่ไม่เปลี่ยนไม่หมุน เลขที่งอกหลักใหม่ (999→1000) ค่อยๆ โผล่ · ใช้กับเหรียญโบนัส +xxxx ด้วย",
        "ตัวนับคอมโบ/เหรียญโบนัส ไม่มีลูกน้ำ (x1234)"
      ]
    },
    {
      "version": "0.20.2",
      "date": "2026-09-08",
      "notes": [
        "โบนัสแตกอยู่บนการ์ดคอมโบ (Android + PWA): ตัวคูณ BONUS! x20 + เหรียญ +380 เป็นบรรทัดเล็ก (16px ชมพู/สีรุ้ง ≥x100 + ทอง) วางเหนือตัวนับ x จำนวนของขวัญบนการ์ดเดิม เด้งเข้า+แสงทองวิ่ง หายใน 3.5 วิ (โบนัสใหม่รีเซ็ตเวลา) — ตัดป้าย BONUS แยกในกองแจ้งเตือนออก · ฝนเหรียญ/สั่นการ์ด/เสียง/แจ้งเจ้าของ คงเดิม · การ์ดกว้างไม่เกิน 80% ของจอ"
      ]
    },
    {
      "version": "0.20.1",
      "date": "2026-09-08",
      "notes": [
        "แจ้งเตือนในห้องรวมที่เดียว (Android + PWA): ป้ายของขวัญ, โบนัสแตกทุกห้อง, COMBO x10, BONUS! x2 +xxx ของห้องนี้ → เป็นป้ายเล็ก (30px) ซ้อนกันมุมขวาบนใต้ป้ายเหรียญ/อันดับ เลื่อนเข้าจากขวา หายเองใน 3.5 วิ (โชว์สูงสุด 3) — ไม่มีป้ายกลางจอใหญ่อีก · ฝนไอคอน/สั่นการ์ด/เสียง คงเดิม · โบนัสของห้องตัวเองไม่ขึ้นซ้ำเป็นป้ายทั่วห้อง"
      ]
    },
    {
      "version": "0.20.0",
      "date": "2026-09-08",
      "notes": [
        "แผ่นของขวัญตามฟีดแบ็กเครื่องจริง (Android + PWA): เลื่อนข้างเป็นหน้า (หน้าละ 2 แถว × 4 = 8 ชิ้นพอดี) + จุดบอกหน้า · แถว \"ส่งให้\" เล็กลง ป้ายโฮสต์/แขกทับบนรูปโปรไฟล์ · การ์ดคอมโบไม่เด้งขึ้นบนตอนเปิดแผ่น (อยู่ตำแหน่งเดิม)",
        "ป้าย COMBO x10 / BONUS! x2 +xxx ไม่บังจอ: ย่อ ≤60% ของจอ วางใต้แถบบน (~16%) มีพื้นหลังโปร่ง แฟลชทองเบาลง ฝนไอคอนเฉพาะครึ่งบน"
      ]
    },
    {
      "version": "0.19.2",
      "date": "2026-09-08",
      "notes": [
        "แคตตาล็อกของขวัญ: ปิดขายของขวัญที่ถูกถอดจากรุ่น (ลูกเจี๊ยบ/แกะ ยังโชว์ใน prod เพราะอยู่ในตาราง) + ซิงก์ลำดับตามรุ่นปัจจุบันตอนบูต"
      ]
    },
    {
      "version": "0.19.1",
      "date": "2026-09-08",
      "notes": [
        "ของขวัญคอมโบสัตว์ 20 ตัว ไม่ซ้ำกัน สไตล์เดียวกับแมวกวัก (เจ้าของ: ลายเส้น/ความเงาแบบแมวกวัก คนละสี คนละคาแรกเตอร์ + เสียงน่ารักเฉพาะตัว): เจนโดยส่งภาพแมวกวักเป็นตัวอ้างอิงสไตล์ (input_image) — หมาคอร์กี้ เป็ดกัปตัน หมูออมสิน กบเจ้าชาย นกฮูก เพนกวิน กระต่าย แพนด้า จิ้งจอก เสือน้อย สิงโตน้อย ช้างน้อย ลิง หมีน้ำผึ้ง โคอาล่า แฮมสเตอร์ โลมา นกแก้ว (พูด \"รักนะ\") สลอธ วัวน้อย ราคา 1–5 เหรียญ · แทนชุด 6 ตัวเดิม (ลูกเจี๊ยบซ้ำเป็ด/แกะ ตัดออก) · โบนัสแตกครอบคลุมทั้ง 21 ตัว",
        "หน้าอันดับ: ภาพโพเดียมครอปชิดล่างให้เห็นแท่น 1-2-3 (Android)"
      ]
    },
    {
      "version": "0.19.0",
      "date": "2026-09-07",
      "notes": [
        "ของขวัญคอมโบเพิ่ม 6 ตัว (สัตว์น่ารักมีคาแรกเตอร์ + เสียงร้องของสัตว์นั้นจริงๆ จาก gpt-6-astra/TTS): หมาน้อยคอร์กี้ 2, เป็ดน้อย 1, หมูออมสิน 3, กบเจ้าชาย 2, ลูกเจี๊ยบ 1, แกะปุกปุย 5 เหรียญ — แอนิเมชัน 3 ท่าวนซ้ำ + เสียง 3 ระดับ (ปกติ/ตื่นเต้น ≥10/ยาว ≥50) · โบนัสแตกครอบคลุมทุกตัว (ops/gen-combo-gifts.mjs, ops/build-combo-gifts.py)",
        "หน้าอันดับ VJ แบบ TikTok (Android + PWA): แตะป้ายอันดับในห้อง → รายวัน/รายสัปดาห์/รายเดือน 100 อันดับ โพเดียม 1-2-3 (ฉากโพเดียมทอง + มงกุฎ/เหรียญรางวัลเจนใหม่) + รายการ 4–100 + อันดับของคุณ · API GET /api/v1/rank/hosts?period=daily|weekly|monthly (domain/rank.ts board + ช่วงรายเดือนไทย)",
        "แผ่นของขวัญ: พื้นหลังโปร่งแสงเห็นวิดีโอ · ย่อทุกส่วนให้พอดีจอไม่ต้องเลื่อน (ผู้รับ/หมวด/การ์ด/แถบล่างเล็กลงตามลำดับ) · ปุ่มส่ง/หัวใจ/ของขวัญ/⋯ ขนาดเท่ากันและเรียงแนวเดียวกัน"
      ]
    },
    {
      "version": "0.18.1",
      "date": "2026-09-07",
      "notes": [
        "ทดสอบฝั่งคนดูบนเครื่องจริง (ห้องทดลอง testhost_bot) แล้วแก้: แผ่นของขวัญบน Android เปิดมาครึ่งจอ ปุ่ม \"ส่ง\" ถูกซ่อน (skipPartiallyExpanded + กริดสูงตามเนื้อหา) · การ์ดคอมโบ/ป้ายคอมโบ/โบนัสแตกถูกแผ่นของขวัญบังตอนกดส่งรัวจากแผ่น → ยกขึ้นบนจอเมื่อแผ่นเปิด (Android raised, PWA .sheet-open) · ops/test-room.ts ส่ง ping ทุก 20 วิ (เดิมห้องถูกตัดหลัง ~90 วิ เพราะ socket เงียบ)",
        "ยืนยันบนเครื่องจริง: ส่งรัว/คอมโบ x9,337 ตัวเลขภาพสายรุ้ง, โบนัสแตก x2 + ป้าย BONUS! + ป้ายเล็กทุกห้อง, เหรียญ/อันดับของโฮสต์อัปเดตสด, วงเลือกจำนวน, เมนู ⋯, โหมดพิมพ์"
      ]
    },
    {
      "version": "0.18.0",
      "date": "2026-09-07",
      "notes": [
        "ห้องไลฟ์ปรับใหญ่ตามเจ้าของ (Android + PWA): ไม่โชว์ของขวัญในแชต · เสียงออกลำโพง (เดิมออกหูฟังสนทนา) · แผ่นของขวัญพอดีจอไม่ต้องเลื่อน (รูปผู้รับเล็กลง กริดย่อ) · วงเลือกจำนวนรอบปุ่มคอมโบ: กดค้างวงแหวน 1 22 33 … 99 เด้งออกมา ลากไปที่เลข มีสายฟ้าเรืองแสงเชื่อม ปล่อย = เลือก (คอมโบไม่หลุด) · ID: xxxxxxx ใต้ชื่อในห้อง · มุมขวาบนรูปคนดูล่าสุด 3 คน + จำนวนคนดูแบบ TikTok · ใต้รูป VJ ป้ายเหรียญที่ได้ในไลฟ์นี้ + ป้ายอันดับ ชั่วโมง/วัน/สัปดาห์ (สลับทุก 4 วิ) · ป้ายเล็ก \"ใครโบนัสแตก\" โชว์ทุกห้อง · ปุ่มไอเท็ม/ขอร่วมไลฟ์/รายงาน ย้ายไปเมนู ⋯ ด้านล่าง · ช่องพิมพ์ \"พูดอะไรสักหน่อย…\" จัดกลางไม่ตกขอบ · แตะช่องพิมพ์แล้วขยายเต็มแถบ ซ่อนปุ่มหัวใจ/ของขวัญ/⋯",
        "เซิร์ฟเวอร์: GET /api/v1/rooms/:id/rank (อันดับโฮสต์จากเพชรที่ได้รับ รายชั่วโมง/วันไทย/สัปดาห์ไทย แคช 20 วิ, domain/rank.ts) · WS bonus.global ประกาศโบนัสแตกให้ทุกคนที่ออนไลน์ · เทสเพิ่ม"
      ]
    },
    {
      "version": "0.17.1",
      "date": "2026-09-07",
      "notes": [
        "เปลี่ยนชื่อแอปเป็น KumaLive (คุมะไลฟ์): ทุกข้อความที่ผู้ใช้เห็น (ชื่อแอป/ไอคอน launcher, หน้าล็อกอิน, หัวหน้าแรก, เกี่ยวกับแอป, ตัวอย่างข้อความ, แจ้งเตือนกำลังไลฟ์, PWA title/manifest, หน้าแอดมิน, User-Agent) — ชื่อแพ็กเกจ/โดเมน/โฟลเดอร์/ตัวแปรในโค้ดคงเดิม"
      ]
    },
    {
      "version": "0.17.0",
      "date": "2026-09-06",
      "notes": [
        "ตัวเลข/ป้ายคอมโบเป็นภาพ (เจ้าของ: สวยกว่า CSS): ชุดตัวอักษร jelly 3 สี (ทอง/ชมพู/สายรุ้ง: 0–9 x , + .) และป้าย COMBO / BONUS! เจนด้วย gpt-6-astra (ops/gen-digits.mjs) ตัดเป็นรายตัวด้วยการแยก \"เนื้อสี\" จากขอบ/เงาที่เชื่อมกัน (ops/slice-digits.py → dg_<set>_<name>.webp 96px + Android drawable + DigitIds.kt)",
        "ตัวนับบนการ์ด x{n} (ทอง <50 / ชมพู ≥50 / สายรุ้ง ≥100 ย่อขนาดเมื่อเลขยาว), ป้ายคอมโบ x10/x50/…, ป้ายโบนัสแตก x{เท่า} +{เหรียญ}, ตัวนับบนปุ่มคอมโบ — ทั้ง PWA (numImg) และ Android (DigitText)",
        "การ์ดคอมโบใบเดียว แย่งกันโชว์: ใครกดล่าสุดการ์ดเด้งเป็นคนนั้นทันที (เดิมซ้อน 2 ใบ) · คอมโบของแต่ละคนไม่หลุด (เซิร์ฟเวอร์นับแยกต่อคน + client จำค่าล่าสุดต่อคนไว้ตรวจป้าย 10/50/100 ไม่ซ้ำ) ทั้ง PWA/Android",
        "docs/ASSETS.md หมวด L"
      ]
    },
    {
      "version": "0.16.1",
      "date": "2026-09-06",
      "notes": [
        "กดรัวได้ไม่จำกัด: เจ้าของเจอ \"ส่งของขวัญถี่เกินไป\" ตอนกระหน่ำกด → client รวมการแตะที่ติดกันภายใน 120ms เป็นคำขอเดียว (quantity รวม) ทั้ง PWA/Android — จอตอบสนองทุกแตะทันที ตัวนับคอมโบบวกตามจำนวนรวม เซิร์ฟเวอร์ได้คำขอ ≤ ~8/วิ · ลิมิตเซิร์ฟเวอร์ 20/วิ (กันยิงตรง)",
        "เสียงเมี้ยวเบามาก (TTS ให้ระดับเสียงพูด) → normalize ด้วย ffmpeg loudnorm I=-9 LUFS + limiter (ดังขึ้น ~3–4 เท่า)"
      ]
    },
    {
      "version": "0.16.0",
      "date": "2026-09-06",
      "notes": [
        "คอมโบไม่จำกัดที่ 999: ตัวนับแสดงเลขใหญ่ได้ (x1,234 …) · ส่งได้สูงสุด 9,999 ชิ้นต่อครั้ง (เดิม 99) · จำกัดส่ง 10 ครั้ง/วิ (เดิม 5) รองรับแตะรัว",
        "เลือกจำนวนต่อครั้ง: กดค้างที่ของขวัญ → เลือก 1 22 33 44 55 66 77 88 99 หรือ \"กรอกเอง\" · ช่องกรอกจำนวนอยู่ข้างยอดเหรียญในแผ่นของขวัญ · ปุ่มคอมโบใช้จำนวนที่เลือก (ป้าย ×22/ครั้ง) ทั้ง PWA/Android",
        "โบนัสแตก (ของขวัญคอมโบ): ส่งแล้วมีโอกาสได้เหรียญคืนเป็นทวีคูณ (ค่าเริ่มต้น 1/12 ×2 · 1/60 ×5 · 1/600 ×20 · 1/6000 ×100 เพดาน 20,000 เหรียญ/ครั้ง) · ทุกคนในห้องเห็นเอฟเฟกต์ \"โบนัสแตก x20! +380 เหรียญ\" ฝนเหรียญ+แฟลชทอง · ผู้ส่งได้เหรียญเข้ากระเป๋าทันที (ledger COIN_BONUS อ้าง GiftEvent)",
        "ตั้งค่าได้จากหลังบ้าน (แท็บ \"โบนัสแตก\" ใน /admin): เปิด/ปิด, ของขวัญที่ร่วม, ระดับโอกาส/เท่า, เพดานต่อครั้ง · แสดงค่าคาดหวังสด · ระบบบังคับค่าคาดหวังรวม ≤ 35% ของเหรียญที่ส่ง (MAX_EXPECTED_RETURN) บันทึกเกินไม่ได้ → ไม่ขาดทุน · เก็บใน AppSetting (migration) + audit",
        "แก้อัตราถอนที่ทำให้ขาดทุน: WITHDRAW_RATE_SATANG 50 → 5 (1 เพชร = 0.05 บาท; เดิม 0.50 บาท = จ่าย VJ 5 เท่าของราคาเหรียญ 0.077–0.10 บาท) — กระทบเฉพาะคำขอถอนใหม่",
        "แผ่นของขวัญแบบ Momo (ทั้ง PWA/Android): แถว \"ส่งให้:\" รูปโฮสต์/แขก + \"ทั้งหมด\" · แตะของขวัญ = เลือก (ป้าย X{จำนวน}) · แถบล่าง เหรียญ/เพชร + ช่องจำนวน \"99 ›\" (1 22 33 … 99 หรือกรอกเอง) + ปุ่ม \"ส่ง\" ใหญ่ · กด \"ส่ง\" รัวๆ = คอมโบ แผ่นไม่ปิด ปรับจำนวนระหว่างคอมโบได้ คอมโบไม่หลุด (ปุ่มคอมโบลอยมีแถบเลือกจำนวนด้วย)",
        "EXP แบบ Momo: ของขวัญนำโชค/คอมโบ 1 Coin = 1 EXP · ของขวัญหรูหรา 1 Coin = 10 EXP (ผู้รับ 1 EXP/เหรียญเท่าเดิม) · เส้นโค้งเลเวลใหม่ 150·L²·(L−1) (Lv.2=600, Lv.5=15,000, Lv.10=135,000, Lv.12≈237,600, Lv.50≈18.4M) · หน้าใหม่ \"ระดับของฉัน\" (หัวชมพู รูป+ป้ายระดับ ค่าประสบการณ์ แถบ \"ห่างจากการอัปเลเวลอีก N\" สิทธิพิเศษ/วิธีเลื่อนระดับ) เข้าจากการ์ดระดับ · ProgressView.toNext",
        "ops/test-room.ts เปิดห้องไลฟ์ทดลอง (บัญชีบอท + offer ตัวอย่าง ไม่มีภาพ) ไว้ทดสอบส่งของขวัญบนเครื่องจริง",
        "เทส 91/91"
      ]
    },
    {
      "version": "0.15.0",
      "date": "2026-09-06",
      "notes": [
        "ของขวัญคอมโบ \"แมวกวัก\" (แบบกุหลาบ TikTok ส่งรัวๆ) ราคา 1 เหรียญ หมวด \"คอมโบ\" อยู่ช่องแรกของแผ่นของขวัญ",
        "ภาพ: แมวกวักทองกล้ามแขนโตข้างเดียว ปลอกคอแดง แว่นดำ (gpt-6-astra) — ไอคอนนิ่ง + แอนิเมชันกวัก 4 เฟรมวนซ้ำ (เฟรมต่อเนื่องด้วยการส่งภาพเดิมเข้าไปแก้) · เสียง \"เมี้ยว\" 3 ระดับจาก gpt-4o-mini-tts (ปกติ / ตื่นเต้น ≥10 / ยาวสุดมัน ≥50) ตัดเงียบ+AAC ด้วย ffmpeg",
        "เซิร์ฟเวอร์: effect.combo + comboSfx ต่อระดับ · gift.sent.event.combo นับต่อผู้ส่ง/ของขวัญ/ห้อง (ส่งซ้ำภายใน 5 วิ บวกต่อตาม quantity, retry ไม่นับ) · เทส 90/90",
        "ทุกคนในห้องเห็นการ์ดคอมโบซ้ายจอ (แมวกวักวนซ้ำ + รูป/ชื่อผู้ส่ง + ตัวเลข x1 x2 … x999 กระแทกทุกครั้งที่ส่ง บวกไปเรื่อยๆ ตามจำนวน) สีไต่ระดับ ขาว → ทอง ≥10 → ชมพูแดง ≥50 → สายรุ้ง ≥100 → เรืองไฟ ≥500 · แมวเล็กพุ่งออกจากการ์ดทุกครั้ง (มากขึ้นตามคอมโบ) · ป้าย \"คอมโบ x10!\" ที่ 10/50/100/500 และฝนแมว 30 ตัวที่ ≥50 · เสียงเมี้ยวทุกครั้ง pitch สูงขึ้นตามคอมโบ (Web Audio / SoundPool) · การ์ดหายเอง 3 วิหลังส่งครั้งสุดท้าย (สูงสุด 2 การ์ด)",
        "ผู้ส่ง: หลังส่งครั้งแรกมีปุ่มคอมโบลอยมุมขวาล่าง (แมว + x{n} + วงนับถอยหลัง 5 วิ) แตะรัวๆ ส่งทันทีไม่ต้องเปิดแผ่นใหม่ ครบเวลาหายเอง เหรียญไม่พอแจ้งเตือน · แผ่นของขวัญติดป้าย \"คอมโบ\"",
        "ไม่เข้าคิวเอฟเฟกต์เต็มจอ (SuperCar ยังทำงานเดิม) · PWA โหลดภาพ/เสียงล่วงหน้าตอนเข้าห้อง",
        "เครื่องมือ: ops/gen-maneki.mjs, ops/gen-maneki-frame.mjs, ops/build-maneki.py, ops/topup.sh (เติมเหรียญบัญชีทดสอบผ่าน SSH) · docs/ASSETS.md หมวด K"
      ]
    },
    {
      "version": "0.14.2",
      "date": "2026-09-06",
      "notes": [
        "PWA: รายการแนะนำของช่องค้นหาถูกแท็บ แนะนำ/ติดตาม และกริดทับ (กฎ .page.hub > * ตั้ง z-index:1 ทับค่าใหม่) → เพิ่ม specificity"
      ]
    },
    {
      "version": "0.14.1",
      "date": "2026-09-06",
      "notes": [
        "เมนูบาร์: แท็บที่ไม่ได้เลือกใช้ไอคอน jelly สี (ลดสี 65% + จาง) แทนไอคอนเส้นเทาที่มองไม่เห็น · PWA ป้ายชื่อแท็บที่เลือกอยู่แนวเดียวกับแท็บอื่น (ยกด้วย transform) · รายการแนะนำของช่องค้นหาลอยทับแท็บ/กริดถูกต้อง (z-index)"
      ]
    },
    {
      "version": "0.14.0",
      "date": "2026-09-06",
      "notes": [
        "เมนูบาร์ใหม่ (Android + PWA): ไอคอนแท็บปกติ 30px (เดิม 24 เล็กจนมองไม่เห็น) · แท็บที่เลือกเป็นวงไล่สี 56px ล้นขึ้นเหนือแถบ มีขอบขาว 3px + เงา เด้งเข้าแบบ spring และมีประกายวิ้ง 4 จุดวนรอบไอคอนตลอดเวลา",
        "ช่องค้นหาบนหน้าแรก แทนปุ่มค้นหา: พิมพ์ไอดีหรือชื่อ → แนะนำทันทีสูงสุด 10 คน (รูปโปรไฟล์+กรอบ · ชื่อ · เลเวล · ไอดี · @username) แบบ Google หน่วง 150ms · แตะ = โปรไฟล์ · Enter/ปุ่มค้นหา = หน้าค้นหาเต็ม (คน+ห้องสด) · เซิร์ฟเวอร์ค้นด้วยเลขไอดี (displayId ขึ้นต้นด้วย) เพิ่มจากชื่อ",
        "ปุ่มไลฟ์อนิเมชัน: วงแหวนพัลส์เรืองแสง + แสงวิ่งผ่านปุ่ม + ไอคอนกล้องเด้ง + จุด REC กะพริบ (Compose infinite transition / CSS keyframes)",
        "หมวดสินค้าใหม่ \"ป้ายเข้าห้อง\" (ENTRANCE) ขายได้จริงตามที่วางไว้: ป้ายดาวทอง 300 / ซากุระ 400 / นีออน 1,200 (Lv.3) / ราชวงศ์ 5,000 หรือ 2,000 เพชร (Lv.10) — สวมแล้วป้าย \"เข้ามาแล้ว\" เหนือแชตเปลี่ยนสี ไอคอน (ภาพ item_entrance_* gpt-6-astra) และข้อความเฉพาะป้าย (\"มาถึงแล้ว!\" ฯลฯ) ทั้ง PWA/Android · migration entrance_category (enum) · เทส 89/89",
        "sw.js cache v8"
      ]
    },
    {
      "version": "0.13.0",
      "date": "2026-09-06",
      "notes": [
        "ภาพแทนอีโมจิทั้งแอป (Android + PWA): ไอคอน jelly 72 ชิ้นเจนด้วย gpt-6-astra (ico_* 192px — ops/gen-assets.mjs --jobs=5 → ops/pack-icons.py) + สำเนาภาพเดิม 17 ชิ้น (เหรียญ/เพชร/มงกุฎ/ของขวัญ ฯลฯ) รวม 89 ไอคอน",
        "Android ฝังใน res/drawable-nodpi ใช้ Ico(\"name\") / IcoText / IcoStatRow / PriceText / RarityStars (ไม่โหลดเน็ต ไม่กะพริบ); ปุ่ม HubButton/GhostButton/Chip/MicFrameTag รับ icon",
        "PWA ใช้ ico('name') / giftIco(key); หัวใจลอย/ของขวัญเด้ง/เอฟเฟกต์ไอเท็ม/ป้ายเข้าห้อง/แถบ VS เป็นภาพทั้งหมด",
        "เซิร์ฟเวอร์: ภารกิจส่ง icon เป็นชื่อไอคอน (ไม่ใช่อีโมจิ) · เอฟเฟกต์ไอเท็มในห้องใช้ชื่อ effect",
        "ข้อความที่ใส่ภาพไม่ได้ (Toast/แชตระบบ/ตัวเลือก select/กล่องยืนยัน) ตัดอีโมจิออกเหลือคำล้วน · ชิป LUT ในแผงฟิลเตอร์เป็นแถบสีล้วน",
        "เมนูบาร์เพิ่มแท็บ \"ฟีด\" (ไทม์ไลน์) ลำดับ 2 ต่อจากหน้าแรก ทั้ง Android/PWA (ไอคอน tab_feed/tab_feed_on) — มีเมนูแล้ว หน้ายังเป็น \"เร็วๆ นี้\" ตามที่สั่ง",
        "docs/ASSETS.md หมวด I (ระบบไอคอน) · sw.js cache v7"
      ]
    },
    {
      "version": "0.12.3",
      "date": "2026-09-06",
      "notes": [
        "PuenFX ปิดเป็นค่าเริ่มต้น (opt-in ที่ปุ่ม ✨) — เจ้าของทดสอบกับหน้าจริงแล้วเห็นว่าต้นฉบับดูเป็นคนกว่า ผลลัพธ์ยัง \"เอเลี่ยน\" → พักการจูนฟิลเตอร์ไว้ก่อน"
      ]
    },
    {
      "version": "0.12.2",
      "date": "2026-09-06",
      "notes": [
        "PuenFX จูนกับเฟรมกล้องจริงของเจ้าของ (dump เฟรมดิบ+ผลลัพธ์จากแอปด้วย broadcast FX_DUMP ใน build debug):",
        "พบว่าห้องสีเบจ/ไม้ถูก mask \"สีผิว\" นับเป็นผิวทั้งภาพ → ทั้งจอโดนเนียน+ฟอกขาวจนเหลืองซีด (\"โป๊ะ\") → เอฟเฟกต์ทำเฉพาะโซนหน้า+คอจาก landmarks (วงรีหน้า 1.25×/1.3× เลื่อนลงคาง) นอกโซนไม่แต่ง; ไม่มีหน้าที่เชื่อถือได้ = เนียนตามสีผิวเบาๆ ไม่ฟอกขาว",
        "ตรวจความน่าเชื่อถือของ mesh: หน้าโดนขอบภาพ/สัดส่วนผิด → ไม่ใช้ (MediaPipe ให้จุดเพี้ยนเมื่อหน้าโดนตัด/ก้มหน้า → mask/warp ผิดที่) · ความมั่นใจต่อเนื่อง (ขึ้นเร็วลงช้า) กัน mask กะพริบ",
        "ภาพตรวจใบหน้า 320×180 → 360×640 (จุดแม่นขึ้นมาก) · วงหน้าสูงพอคลุมหน้าผากตอนก้มหน้า · \"ตาใส\" เฉพาะตอนลืมตา+เฉพาะส่วนสว่าง (เดิมเป็นปื้นบนเปลือกตาตอนหลับตา) · เว้นดวงตาน้อยลงตอนหลับตา (เดิมเป็นแถบ) · ขาวแบบยกเงา (gamma) แทนยกไฮไลต์ · ขาว/โกลว์ไม่ลามเสื้อ",
        "ยืนยันด้วยจุด landmarks ซ้อนภาพ: geometry ถูกต้องทุก rotation (0/90/270)",
        "debug: FX_DUMP, preset mask1|mask2|mask3 (วาด mask), จุด landmarks ซ้อนภาพ"
      ]
    },
    {
      "version": "0.12.1",
      "date": "2026-09-06",
      "notes": [
        "ความชัดสูงสุดที่กล้องทำได้: เลือก 1920×1080@30 อัตโนมัติถ้ากล้องรองรับ (Redmi 15C กล้องหน้ารองรับ) ไม่งั้น 720p · bitrate 4 Mbps ที่ 1080p / 2.5 Mbps ที่ 720p · log รายการ format ของกล้อง",
        "PuenFX แก้ \"ลอย/โป๊ะ\": ขาว/โกลว์ใช้ mask สีผิวล้วน (หน้า คอ หู ขาวเท่ากัน ไม่เป็นหน้ากากลอย), นอกวงหน้าเนียนเกือบเท่ากัน, ขอบวงหน้าฟุ้งกว้าง, ลดแป้ง/อมชมพู/โกลว์, EMA จุดหน้าหนักขึ้น + ปิดปรับรูปหน้าเมื่อหน้าเล็กกว่า 9% ของภาพ (ไกลกล้อง → จุดสั่น)",
        "ผิวเนียนแรงขึ้น: เกลี่ยสีผิว (chroma จากภาพเบลอ) ลบด่าง/แดง/noise สีของกล้องจริง, รัศมี guided ~40px, 60% ขึ้นไป = เนียนเต็ม, กันหนวด/ขนตา/ขนคิ้วไม่ถูกเกลี่ย",
        "ช่องทดสอบออฟไลน์รองรับ --ei rot 90|270 จำลองบัฟเฟอร์กล้องจริง — ยืนยัน mapping จุดหน้าถูกต้องทุกทิศ"
      ]
    },
    {
      "version": "0.12.0",
      "date": "2026-09-06",
      "notes": [
        "PuenFX v2 — ลุค \"ฟิลเตอร์จีน/Douyin\" (เจ้าของ: \"ยังไม่เนียน ต้องแบบ tiktok ฟิลเตอร์จีน\")",
        "ผิวเนียนด้วย guided filter รัศมีใหญ่ (ครึ่งความละเอียด 6 pass: Y/Y² → box blur → a,b → box blur) เนียนแบบพอร์ซเลนแต่ขอบตา/ปาก/ไรผมยังคม",
        "mask ผิวจากรูปหน้าจริง (วงรีหน้า/ตา/ปาก/คิ้วจาก landmarks หมุนตามแกนหน้า) ร่วมกับ mask สี — ไม่เนียนทับตา คิ้ว ปาก, นอกหน้าเนียนเบาๆ ตามสีผิว",
        "ขาวใสแบบ tone curve (ยกโทนกลาง-สว่างนุ่มๆ) + ลดความอิ่มของผิว + อมชมพู · ผิวโกลว์ (ยกส่วนสว่างจากภาพเบลอ) · ตาใส (ตาขาวสว่าง+contrast ในวงตา)",
        "สไลเดอร์ใหม่ \"ผิวโกลว์\" \"ตาใส\" + พรีเซ็ต ธรรมชาติ / เกาหลี / จีน / สุด ในแผง ✨ · ค่าเริ่มต้นแรงขึ้น (เนียน 70 ขาว 45 เรียว 35 ตา 30 โกลว์ 25 ตาใส 35) · หน้าเรียว/ตาโตแรงขึ้นที่ค่าเท่ากัน",
        "ทดสอบออฟไลน์กับนางแบบ/นายแบบสังเคราะห์ + รีวิว GPT-5.4 เทียบเป้าหมาย Douyin (ผล/ภาพใน .fxtest/out)"
      ]
    },
    {
      "version": "0.11.2",
      "date": "2026-09-06",
      "notes": [
        "PuenFX รอบรีวิว: ทดสอบกับ \"นางแบบสังเคราะห์\" (gpt-6-astra, ops/gen-test-faces.mjs) ผ่านช่องทดสอบออฟไลน์ใน build debug (FxTestReceiver — ป้อนภาพนิ่งแทนกล้อง บันทึก PNG) แล้วส่งภาพก่อน/หลังให้ GPT-5.4 รีวิว (ops/review-fx.mjs) ได้ 7/10 → ปรับตาม: ผิวเนียนแบบรู้ texture (ลบรอยเล็ก คงขอบตา/คิ้ว/ไรผม), ขาวเฉพาะความสว่างคง chroma + อุ่นผิวเล็กน้อย (ไม่ซีด), คมชัดเฉพาะขอบ (กัน halo), warp falloff quintic นุ่มขึ้น + รัศมีกว้าง/แรงลด, ค่าเริ่มต้นเบาลงตามรีวิว 2 รอบ \"สวยขึ้นแต่ยังเป็นเรา\" (เนียน 42 ขาว 16 คม 25 เรียว 14 คาง 8 ตา 10 จมูก 8) · รีวิวรอบ 2 ยัง 7/10 — จุดที่เหลือ: skin mask ละเอียดขึ้นแถวใต้ตา/ไรผม, ขาวแบบ tone curve, warp ที่ 100% ยังแรง (ไว้รอบถัดไป)",
        "ยืนยันทิศทางปรับรูปหน้าถูกต้องกับใบหน้าจริง: ตาโตขึ้น แก้มเข้า คางสั้นลง จมูกเล็กลง (ตรวจจับ 6 จุด warp)"
      ]
    },
    {
      "version": "0.11.1",
      "date": "2026-09-06",
      "notes": [
        "Android release (R8): กฎ proguard สำหรับ MediaPipe/Flogger/protobuf — ตัว release เดิม FaceLandmarker สร้างไม่ได้ (no caller found on the stack) ทำให้หน้าเรียว/ตาโตไม่ทำงาน; debug ไม่เจอเพราะไม่ minify"
      ]
    },
    {
      "version": "0.11.0",
      "date": "2026-09-06",
      "notes": [
        "PuenFX — ฟิลเตอร์ความงามแบบ TikTok (Android, เขียนใหม่ทั้งหมด ไม่ใช้โค้ดเก่า) android/.../fx/: OpenGL บนเธรดกล้องของ libwebrtc (VideoProcessor) ประมวลผลที่ 1280×720 เต็ม ก่อนเข้า preview/encoder (คนดูเห็นผลเหมือนโฮสต์)",
        "ความงาม 7 อย่าง: ผิวเนียน (แยกความถี่ รักษาขอบ/ผม), ผิวขาว, คมชัด, หน้าเรียว, คาง, ตาโต, จมูก — 4 อย่างหลังใช้จุดบนใบหน้า 478 จุดจาก MediaPipe Face Landmarker (ตรวจทุก 2 เฟรมที่ 320×180, EMA กันสั่น) + warp เฉพาะที่ 8 จุดในเชดเดอร์",
        "ฟิลเตอร์สี LUT 3D 13 โทน (ธรรมชาติ/พีช/ซากุระ/สว่างใส/อุ่น/เย็น/ฟิล์ม/วินเทจ/แคนดี้/ทีล-ส้ม/ป่า/ราตรี/ขาวดำ) สร้างจากสูตรในโค้ด เปลี่ยนได้ระหว่างไลฟ์ + ความเข้ม",
        "แผง ✨ ในหน้าไลฟ์ (ก่อนเริ่มและระหว่างไลฟ์) สไลเดอร์/ชิป จำค่าไว้ (FxPrefs), ปิด-เปิดได้, รีเซ็ต",
        "encoder: 2.2 Mbps 30fps MAINTAIN_RESOLUTION (ความชัดสูง ไม่ลดความละเอียดต่ำกว่า 720p)",
        "วัดจริง: กล้อง 30 fps, render 30 fps ไม่มีเฟรมตกขณะเปิดทุกเอฟเฟกต์ (Redmi 15C)",
        "⏳ PWA ยังไม่มีฟิลเตอร์ (รอบถัดไป) · สติกเกอร์ AR/ฉากหลัง ยังไม่ทำ"
      ]
    },
    {
      "version": "0.10.1",
      "date": "2026-09-06",
      "notes": [
        "ป้าย \"เข้ามาแล้ว\" ลอยเหนือแชต (PWA + Android): คนเข้าห้องเด้งเป็นป้ายไล่สีเลื่อนเข้าจากซ้ายแล้วจางหาย ~2.5 วิ ไม่ปนในแชตอีก (คนมีสัตว์ขี่ = ไอคอน+สีของสัตว์ขี่ และยังมีแอนิเมชันวิ่งเข้าห้องเดิม) · โครงรองรับ ป้ายเข้าห้องแบบซื้อได้ ในอนาคต: client อ่านรูปลักษณ์จาก cosmetics.ENTRANCE ก่อนถ้ามี (ยังไม่มีหมวดในร้าน)",
        "ภาพจาก gpt-6-astra: สินค้า 31 + ของขวัญ 7 + bg_profile_glow ครบ (เจนเสร็จรอบนี้)"
      ]
    },
    {
      "version": "0.10.0",
      "date": "2026-09-06",
      "notes": [
        "หน้าแรกจัดใหม่ (PWA + Android): ปุ่ม \"🎥 ไลฟ์\" ไล่สีแทนปุ่มรีเฟรช, ปุ่มค้นหาย้ายมาอยู่แถวแท็บ แนะนำ/ติดตาม, bottom nav เหลือ 3 แท็บ (หน้าแรก/แจ้งเตือน/ฉัน) และแท็บที่เลือกไม่ยกล้นแถบแล้ว (วงพาสเทลในแถบ)",
        "ฟีดรีเฟรชอัตโนมัติ: WS event ใหม่ feed.changed { roomId, status: LIVE|ENDED } ประกาศถึงทุกคนที่ออนไลน์เมื่อมีห้องเริ่ม/จบ (Presence.broadcast) → client โหลดกริดใหม่ (หน่วง 700ms) · เทส feed.changed ใน battle.test (89)",
        "ภาพสินค้า/ของขวัญ/พื้นหลังจาก gpt-6-astra (เครดิตเติมแล้ว) ทยอยเข้า public/app/assets/"
      ]
    },
    {
      "version": "0.9.1",
      "date": "2026-09-06",
      "notes": [
        "Android: ป้ายชื่อแท็บที่เลือกใน bottom nav แคปซูลถูกตัด (วงยก 56dp ล้นแถบ 64dp) → ลดเป็น 48dp/ยก 8dp",
        "หมายเหตุ deploy: เทสไม่นิ่งเมื่อรัน Gradle (WSL) พร้อมกัน — รัน deploy ตอนเครื่องว่าง"
      ]
    },
    {
      "version": "0.9.0",
      "date": "2026-09-06",
      "notes": [
        "ธีมพาสเทลแบบหน้า \"ของฉัน\" ทั้งแอป (PWA + Android): หน้าแรก/ฟีด (การ์ดขาว thumbnail 9:16 + ป้าย LIVE ชมพู), ค้นหา, แจ้งเตือน, ล็อกอิน/สมัคร, กระเป๋าเงิน + bottom nav แคปซูลลอยทุกหน้า · ห้องไลฟ์และหน้าเปิดไลฟ์คงโทนมืด (วิดีโอเต็มจอ) · PWA: ธีมเปิดทุก route ยกเว้น #/watch/, #/golive (LIVE_ROUTE), meta theme-color สลับตาม; ลบ ProfilePage เก่าที่ไม่ได้ใช้; sw cache v4"
      ]
    },
    {
      "version": "0.8.1",
      "date": "2026-09-06",
      "notes": [
        "Android: กล้องไลฟ์กระตุก/กะพริบ — จับภาพ 30 fps (เดิม 24 ทำให้ adapter ทิ้งเฟรมไม่สม่ำเสมอ และไม่เข้ากับไฟ 50Hz), encoder maxFramerate 30 / 1.5 Mbps; ตัวจับภาพตัวอย่างทุก 8 วิ ย่อบน GPU ก่อนอ่านกลับ (เดิมอ่าน 720p เต็มบนเธรดกล้อง → fps ตกเป็นจังหวะ)",
        "Android: ของขวัญที่มีเอฟเฟกต์เต็มจอไม่เล่นอีโมจิซ้อน"
      ]
    },
    {
      "version": "0.8.0",
      "date": "2026-09-06",
      "notes": [
        "ของขวัญหมวด \"SuperCar\" (supercar 5,000 🪙) — ของขวัญชิ้นแรกที่มีเอฟเฟกต์เต็มจอ: animated WebP 9:16 โปร่งใส 6 วิ (แปลงจากแพ็กของเจ้าของ 720×1280 → 540×960 q70 = 7.6MB) + เสียง m4a; GiftView เพิ่ม category และ effect: { anim, sfx, durationMs } | null (นิยามใน GIFT_META ของ wallet.ts); แคตตาล็อกเติมของ default ที่ยังไม่มีอัตโนมัติตอนบูต (skipDuplicates)",
        "แผ่นของขวัญมีแท็บหมวด (ทั่วไป / SuperCar) + ภาพ gift_<id>.webp + ป้าย \"เอฟเฟกต์\" ทั้ง PWA และ Android",
        "ตัวเล่นเอฟเฟกต์: PWA playGiftEffect() (คิวทีละชิ้น, blob แคช, <audio>), Android GiftEffectPlayer (Coil + coil-gif AnimatedImageDecoder เล่น 1 รอบ, MediaPlayer เสียง) ทั้งฝั่งผู้ชมและโฮสต์",
        "/app/assets/ เสิร์ฟ .m4a .mp4 .webm ได้ (allowlist)"
      ]
    },
    {
      "version": "0.7.0",
      "date": "2026-09-06",
      "notes": [
        "ตรวจทุกฟังก์ชันหน้าโปรไฟล์ (PWA + Android) แล้วปิดจุดที่ยังเป็นโครง (รายการเต็มใน docs/PROFILE_HUB.md หัวข้อ v0.7.0)",
        "เติมเหรียญ (ผู้ใช้ทั่วไป) แบบโอน+แนบสลิป: TopupRequest (migration topup), แพ็กเกจ 6 ระดับมีโบนัส, รหัสอ้างอิง 6 ตัว, บัญชีรับเงินจาก env TOPUP_BANK, แนบ/เปลี่ยนสลิป (≤3MB), ยกเลิกเอง; แอดมินแท็บ \"เติมเงิน\" ดูสลิป → \"ได้รับเงิน\" (เพิ่มเหรียญใน tx เดียว, ledger COIN_TOPUP) / ปฏิเสธ; หน้า #/topup (PWA) + TopupScreen (Android) เข้าถึงจากการ์ด Coin / Mcoin / VIP \"เติม Coin\" / กระเป๋าเงิน · เพชรเติมไม่ได้ (ได้จากของขวัญ)",
        "VIP มีสิทธิ์จริง: XP ×1.5 (ซ้อนบัตร ×2), ภารกิจ vip_daily 100 🪙/วัน เฉพาะ VIP (MissionView.vipOnly, progress.update.vip), ชื่อทองในแชต; หน้า VIP แสดงสิทธิ์จาก API",
        "ผู้ติดตาม/กำลังติดตาม → รายชื่อ (#/follows/…, FollowsScreen); ลบรูปโปรไฟล์; Android อัปโหลดรูปโปรไฟล์ (เลือกภาพ+ย่อ ≤2MB); ยกเลิกคำขอเข้ากิลด์ + ดูข้อมูลกิลด์ก่อนเข้า; ปุ่ม 🎒 ใช้ไอเท็มในห้องไลฟ์บน Android; กระเป๋าเงินธีม hub + ป้าย ledger ครบ 11 ชนิด; PWA แก้รหัสผ่านเรียก /auth/password (เดิม 404), ขนาดตัวอักษรมีผลจริง (zoom), i18n en เพิ่ม ~80 คีย์, feedback ส่งเวอร์ชันจริง",
        "คอสเมติกเห็นผลครบทุกหมวด: กรอบไมค์ / คลื่นเสียง / สกินหน้าแรก / สกินการ์ด (ใหม่) + กรอบรูป/สัตว์ขี่/ธีมห้อง/ฟองแชต ใช้ภาพ item_<id>.webp ก่อน fallback; Android หน้าโปรไฟล์คนอื่นเป็นธีม hub (กรอบ/Lv/ฉายา/VIP/กิลด์/เพศ/ไอดี)",
        "ops/gen-assets.mjs เพิ่ม prompt สินค้า 31 + ของขวัญ 7 + พื้นหลัง (ขนาดต่อชิ้น) — ⚠️ ยังไม่ได้เจน: เครดิต OpenAI หมด (insufficient_quota)",
        "เทส 88 (เพิ่มเติมเหรียญ + สิทธิ์ VIP)"
      ]
    },
    {
      "version": "0.6.1",
      "date": "2026-09-06",
      "notes": [
        "แก้หน้า \"ของฉัน\": การ์ด VIP ดำชนการ์ด Coin/ระดับ (ไม่มีช่องว่าง) → เว้น 12px (PWA .stat2); ภาพ \"VIP\" wordmark (ไฟล์ 1024² ตัวอักษรอยู่แถบกลาง) ล้นลงทับไอคอนสกินพิเศษ/เพิ่มเติม → ครอปเฉพาะแถบกลาง 120×44",
        "Android: การ์ด Coin/ระดับ สูงตามเนื้อหา (ขั้นต่ำ 118dp) สองใบเท่ากัน — ตัวอักษรใหญ่ไม่ตัดบรรทัด XP",
        "เอกสาร docs/ASSETS.md: สถานะการเจนภาพ (31 ไฟล์แล้ว / หมวด E ยังไม่เจน)"
      ]
    },
    {
      "version": "0.6.0",
      "date": "2026-09-06",
      "notes": [
        "ตามภาพอ้างอิงหน้า \"ของฉัน\": การ์ด VIP ดำ-ทอง (แท็บมงกุฎ, ปุ่มเปิดใช้งาน/สถานะ, ตัว VIP ทอง, เมนู 4 ช่องเส้นทอง), เมนูลัด \"Mcoin\", ป้ายเพศ, เมนู \"ข้อมูลการถอน\", ห้างมีริบบิ้นหมวด, bottom nav แคปซูลลอย (5 แท็บเดิม แท็บที่เลือกยกขึ้น)",
        "VIP (โครงรองรับ): User.vipUntil, GET /me/vip, POST /me/vip/activate (999 🪙 / 30 วัน ต่ออายุบวกต่อ), ป้าย VIP บนโปรไฟล์/แชต, หน้า #/vip — สิทธิ์พิเศษจะเติมภายหลัง",
        "ถอนรายได้ (VJ): WithdrawRequest — ยื่นถอนเพชร→บาท (อัตรา 0.50 บาท/เพชร ขั้นต่ำ 1,000) กันเพชรทันที, ยกเลิกได้ตอนรอตรวจ, แอดมินอนุมัติ→จ่ายแล้ว/ปฏิเสธ (คืนเพชร) ในแผง /admin/ แท็บ \"ถอนเงิน\", หน้า #/withdraw + ประวัติ; ledger DIAMOND_WITHDRAW/_REFUND, COIN_VIP",
        "เพศ: User.gender (PATCH /me), ป้าย ♂/♀/⚧ บนโปรไฟล์, เลือกในแก้โปรไฟล์",
        "ไอคอนจากไฟล์ภาพ: public/app/assets/ (เสิร์ฟ /app/assets/*), PWA โหลดภาพถ้ามีไม่มีใช้ SVG/อีโมจิ (aimg()); สคริปต์ ops/gen-assets.mjs เจนไอคอนสไตล์ jelly ด้วยโมเดล gpt-6-astra (Responses API + image_generation) ตาม docs/ASSETS.md",
        "Android (Compose) หน้า \"ของฉัน\" ใหม่ตามภาพอ้างอิง — ui/hub/* (HubTheme tokens + ProfileHeader/VipCard/StatCards/ShortcutGrid/ShopSection/MenuList/FloatingBottomNav), หน้าย่อยครบ: กระเป๋า/ร้านค้า/ภารกิจ/สถิติไลฟ์/ของขวัญ/VIP/ถอนรายได้/กิลด์/ตั้งค่า 12 รายการ (รวมสลับบัญชี, ลบบัญชี, ล้างแคช, PiP จริงด้วย enterPictureInPictureMode, ขนาดตัวอักษรผ่าน LocalDensity, ภาษา th/en) · ไอคอนโหลดจากเซิร์ฟเวอร์ (/app/assets/*.webp ผ่าน Coil, fallback JellyTile) · ในห้องไลฟ์: ฟองแชตสี + ป้าย VIP/Lv./กิลด์, เอฟเฟกต์ไอเท็ม (room.effect), toast เลเวลอัป/ภารกิจครบ",
        "migration vip_withdraw_gender · เทส 86"
      ]
    },
    {
      "version": "0.5.0",
      "date": "2026-09-06",
      "notes": [
        "Profile Hub (หลังบ้าน) — docs/PROFILE_HUB.md: ระดับ/XP + ยศ, ภารกิจ (รายวัน/สัปดาห์/ครั้งเดียว, claim รางวัล), ไอเท็ม 11 หมวด (ไอดีสวย/กรอบ/สัตว์ขี่/ฟองแชต/ธีมห้อง/กรอบไมค์/ไอเท็ม/คลื่นเสียง/สกินหน้าแรก/สกินการ์ด/ฉายา) + ร้านค้า + กระเป๋า/สวม/ใช้, กิลด์ (สร้าง/เข้า/ขอเข้า/อนุมัติ/แอดมิน/เตะ/โอน/ยุบ), ตั้งค่า (ภาษา/ตัวอักษร/PiP/แจ้งเตือน/ความเป็นส่วนตัว — บังคับใช้ฝั่งเซิร์ฟเวอร์), ข้อเสนอแนะ (+แท็บใน /admin/), ลบบัญชี, สถิติไลฟ์, ไอดีตัวเลข 7 หลัก",
        "PublicUser เพิ่ม displayId, level, xp, title, guild, cosmetics; WS event progress.update, mission.completed, room.effect; ledger kind COIN_SHOP/DIAMOND_SHOP/COIN_MISSION",
        "migration profile_hub (7 ตารางใหม่ + คอลัมน์ User) · เทส 85",
        "PWA หน้า \"ของฉัน\" ใหม่ (hub.js/hub.css): ธีมพาสเทลม่วงอ่อน-ขาว ตามสเปกออกแบบ (แสงชมพู-ม่วงบน, การ์ดขาวมุมมน, การ์ด Coin ส้ม-ทอง / ระดับ ม่วง, เมนูลัด 4 ช่องไอคอน jelly SVG, ห้าง 4 ชิ้น, เมนูแนวตั้ง) + หน้าย่อยครบ: กระเป๋า/ห้องแต่งตัว, ร้านค้า, ศูนย์ภารกิจ, ข้อมูลไลฟ์สด, จัดการกิลด์, ตั้งค่า 12 รายการ (บัญชี/PiP mini player/ขนาดตัวอักษร/ข้อเสนอแนะ/ภาษา th-en/แจ้งเตือน/ความเป็นส่วนตัว/ล้างแคช/เกี่ยวกับ/ลบบัญชี/สลับบัญชี/ออก)",
        "ในห้องไลฟ์: กรอบโปรไฟล์รอบรูป, ฟองแชตสี + ป้าย Lv./กิลด์, ธีมห้องของโฮสต์, สัตว์ขี่ตอนเข้าห้อง, ปุ่ม 🎒 ใช้ประทัด/สายรุ้ง, ป้ายเลเวลอัป",
        "⚠️ Android ยังเป็นหน้าโปรไฟล์เดิม — v0.7.0"
      ]
    },
    {
      "version": "0.4.1",
      "date": "2026-09-06",
      "notes": [
        "เอกสาร: DNS live.phuen.com + ผลทดสอบ prod ผ่านเน็ตจริง (APK release ↔ PWA prod)"
      ]
    },
    {
      "version": "0.4.0",
      "date": "2026-09-06",
      "notes": [
        "ประวัติศึก VS: ตาราง Battle (migration battles) บันทึกตอนศึกจบ (ไม่บล็อกการประกาศผล); REST GET /api/v1/rooms/:id/battles, GET /api/v1/users/:id/battles (มี outcome ในมุมผู้ใช้ + สรุป ชนะ/แพ้/เสมอ)",
        "หน้าโปรไฟล์ (PWA + Android) แสดง \"⚔️ ศึก VS\" ชนะ/แพ้/เสมอ + รายการล่าสุด",
        "PWA: เข้าห้อง/ต่อกลับกลางศึก → วาดแถบคะแนนจาก Room.battle ทันที (เดิมต้องรอ event ถัดไป)"
      ]
    },
    {
      "version": "0.3.0",
      "date": "2026-09-06",
      "notes": [
        "โหมด VS/PK (ศึกของขวัญ โฮสต์ vs แขก): WS battle.start (โฮสต์/แอดมิน, 5–600 วิ, default 180) / battle.stop, event battle.started / battle.score / battle.ended (result host|guest|draw, endReason timeout|stopped|guest_left|room_ended), Room.battle ให้คนเข้าทีหลังเห็นแถบคะแนนทันที",
        "gift.send รับ to: 'host'|'guest' — เพชรเข้ากระเป๋าผู้รับฝั่งนั้นจริง และเหรียญนับเป็นคะแนนฝั่งนั้นระหว่างศึก (GiftEvent.to/receiverId)",
        "Android + PWA: แถบคะแนนชมพู(โฮสต์)/ฟ้า(แขก) สัดส่วนตามคะแนน + นับถอยหลัง บนขอบล่างของแถบสองจอ, ป้ายผล 🏆, ปุ่ม ⚔️ เลือก 1/3/5 นาที และ ⏹ หยุด ของโฮสต์, แผ่นของขวัญเลือกฝั่งผู้รับเมื่อมีแขก",
        "เทส 78 (tests/battle.test.ts ใหม่ 3 ชุด) · ops/switch.sh --prune ไม่ล้มเมื่อมีรุ่นเดียว"
      ]
    },
    {
      "version": "0.2.0",
      "date": "2026-09-06",
      "notes": [
        "ไลฟ์ร่วม/VS: แบ่งจอ ซ้าย(โฮสต์)/ขวา(แขก) แบบ TikTok — แถบใต้แถบบน แต่ละครึ่ง 50% สัดส่วน 9:16 พอดีภาพกล้อง ไม่ครอป (Android + PWA)",
        "ระบบเวอร์ชัน/rollback: VERSION + CHANGELOG.md + ops/release.sh (bump+commit+tag), deploy เป็น release แยกโฟลเดอร์ + symlink current + ตรวจสุขภาพแล้วย้อนอัตโนมัติถ้าล้ม, ops/rollback.sh",
        "/health/live คืน version; แสดงเวอร์ชันในหน้าโปรไฟล์ (PWA/Android); Android versionName/versionCode อ่านจาก VERSION"
      ]
    },
    {
      "version": "0.1.0",
      "date": "2026-09-06",
      "notes": [
        "v1 ครบ Phase 0–9: บัญชี/โปรไฟล์/ติดตาม, ไลฟ์ mediasoup SFU + SDP bridge, แชต, เหรียญ/ของขวัญ/กระเป๋า, ค้นหา/แนะนำ/แจ้งเตือน, แอดมิน, Android (Kotlin/Compose/libwebrtc), PWA /app/, ไลฟ์ร่วม (แขก 1 คน)"
      ]
    }
  ]
}
