# Progressive Web App (PWA) Guide (ខ្មែរ) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/PWA_GUIDE.md) · 🇪🇹 [am](../../../am/docs/guides/PWA_GUIDE.md) · 🇸🇦 [ar](../../../ar/docs/guides/PWA_GUIDE.md) · 🇦🇿 [az](../../../az/docs/guides/PWA_GUIDE.md) · 🇧🇬 [bg](../../../bg/docs/guides/PWA_GUIDE.md) · 🇧🇩 [bn](../../../bn/docs/guides/PWA_GUIDE.md) · 🇧🇦 [bs](../../../bs/docs/guides/PWA_GUIDE.md) · 🇨🇿 [cs](../../../cs/docs/guides/PWA_GUIDE.md) · 🇩🇰 [da](../../../da/docs/guides/PWA_GUIDE.md) · 🇩🇪 [de](../../../de/docs/guides/PWA_GUIDE.md) · 🇬🇷 [el](../../../el/docs/guides/PWA_GUIDE.md) · 🇪🇸 [es](../../../es/docs/guides/PWA_GUIDE.md) · 🇪🇪 [et](../../../et/docs/guides/PWA_GUIDE.md) · 🇮🇷 [fa](../../../fa/docs/guides/PWA_GUIDE.md) · 🇫🇮 [fi](../../../fi/docs/guides/PWA_GUIDE.md) · 🇫🇷 [fr](../../../fr/docs/guides/PWA_GUIDE.md) · 🇮🇪 [ga](../../../ga/docs/guides/PWA_GUIDE.md) · 🇮🇳 [gu](../../../gu/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ha](../../../ha/docs/guides/PWA_GUIDE.md) · 🇮🇱 [he](../../../he/docs/guides/PWA_GUIDE.md) · 🇮🇳 [hi](../../../hi/docs/guides/PWA_GUIDE.md) · 🇭🇷 [hr](../../../hr/docs/guides/PWA_GUIDE.md) · 🇭🇺 [hu](../../../hu/docs/guides/PWA_GUIDE.md) · 🇦🇲 [hy](../../../hy/docs/guides/PWA_GUIDE.md) · 🇮🇩 [id](../../../id/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ig](../../../ig/docs/guides/PWA_GUIDE.md) · 🇮🇹 [it](../../../it/docs/guides/PWA_GUIDE.md) · 🇯🇵 [ja](../../../ja/docs/guides/PWA_GUIDE.md) · 🇬🇪 [ka](../../../ka/docs/guides/PWA_GUIDE.md) · 🇮🇳 [kn](../../../kn/docs/guides/PWA_GUIDE.md) · 🇰🇷 [ko](../../../ko/docs/guides/PWA_GUIDE.md) · 🇱🇹 [lt](../../../lt/docs/guides/PWA_GUIDE.md) · 🇱🇻 [lv](../../../lv/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ml](../../../ml/docs/guides/PWA_GUIDE.md) · 🇮🇳 [mr](../../../mr/docs/guides/PWA_GUIDE.md) · 🇲🇾 [ms](../../../ms/docs/guides/PWA_GUIDE.md) · 🇲🇹 [mt](../../../mt/docs/guides/PWA_GUIDE.md) · 🇲🇲 [my](../../../my/docs/guides/PWA_GUIDE.md) · 🇳🇵 [ne](../../../ne/docs/guides/PWA_GUIDE.md) · 🇳🇱 [nl](../../../nl/docs/guides/PWA_GUIDE.md) · 🇳🇴 [no](../../../no/docs/guides/PWA_GUIDE.md) · 🇮🇳 [or](../../../or/docs/guides/PWA_GUIDE.md) · 🇮🇳 [pa](../../../pa/docs/guides/PWA_GUIDE.md) · 🇵🇭 [phi](../../../phi/docs/guides/PWA_GUIDE.md) · 🇵🇱 [pl](../../../pl/docs/guides/PWA_GUIDE.md) · 🇵🇹 [pt](../../../pt/docs/guides/PWA_GUIDE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/PWA_GUIDE.md) · 🇷🇴 [ro](../../../ro/docs/guides/PWA_GUIDE.md) · 🇷🇺 [ru](../../../ru/docs/guides/PWA_GUIDE.md) · 🇱🇰 [si](../../../si/docs/guides/PWA_GUIDE.md) · 🇸🇰 [sk](../../../sk/docs/guides/PWA_GUIDE.md) · 🇸🇮 [sl](../../../sl/docs/guides/PWA_GUIDE.md) · 🇷🇸 [sr](../../../sr/docs/guides/PWA_GUIDE.md) · 🇸🇪 [sv](../../../sv/docs/guides/PWA_GUIDE.md) · 🇰🇪 [sw](../../../sw/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ta](../../../ta/docs/guides/PWA_GUIDE.md) · 🇮🇳 [te](../../../te/docs/guides/PWA_GUIDE.md) · 🇹🇭 [th](../../../th/docs/guides/PWA_GUIDE.md) · 🇹🇷 [tr](../../../tr/docs/guides/PWA_GUIDE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/PWA_GUIDE.md) · 🇵🇰 [ur](../../../ur/docs/guides/PWA_GUIDE.md) · 🇺🇿 [uz](../../../uz/docs/guides/PWA_GUIDE.md) · 🇻🇳 [vi](../../../vi/docs/guides/PWA_GUIDE.md) · 🇳🇬 [yo](../../../yo/docs/guides/PWA_GUIDE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/PWA_GUIDE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/PWA_GUIDE.md) --- OmniRoute ត្រូវបានផ្តល់ជូនជា Progressive Web App ដែលអាចដំឡើងបានពេញលេញ។ នៅពេលអ្នកចូលប្រើផ្ទាំងគ្រប់គ្រងពីកម្មវិធីរុករកលើទូរសព្ទណាមួយ — Android (Chrome) ឬ iOS (Safari) — អ្នកអាច «បន្ថែមទៅអេក្រង់ដើម» និងទទួលបានបទពិសោធន៍ដូចកម្មវិធីដើម ដោយមិនចាំបាច់ប្រើហាងកម្មវិធីឡើយ។ ## PWA ជាអ្វី? Progressive Web App បំប្លែងផ្ទាំងគ្រប់គ្រងលើបណ្ដាញរបស់ OmniRoute ឱ្យមើលទៅ និងមានអារម្មណ៍ដូចជាកម្មវិធីទូរសព្ទដើម។ នៅពេលបានដំឡើង វានឹង៖ - ដំណើរការពីអេក្រង់ដើមរបស់អ្នក ដោយមានរូបតំណាងផ្ទាល់ខ្លួន - បើកពេញអេក្រង់ — គ្មានរបារអាសយដ្ឋានកម្មវិធីរុករក ឬផ្ទាំងចំណុចប្រទាក់ទេ - ដំណើរការក្រៅបណ្ដាញជាមួយទំព័រតភ្ជាប់ពិសេស - រក្សាទុកធនធានថេរក្នុងឃ្លាំងសម្ងាត់ ដើម្បីឱ្យផ្ទុកបានលឿនជាងមុន - គាំទ្រទាំងទិសបញ្ឈរ និងទិសផ្ដេក ## ការដំឡើង ### Android (Chrome) 1. បើកផ្ទាំងគ្រប់គ្រង OmniRoute ក្នុង Chrome៖ `http://YOUR_IP:20128` 2. Chrome នឹងបង្ហាញបដា **«បន្ថែម OmniRoute ទៅអេក្រង់ដើម»** ដោយស្វ័យប្រវត្តិ ឬ៖ - ចុចម៉ឺនុយ **⋮** (ចំណុចបី) → **«បន្ថែមទៅអេក្រង់ដើម»** ឬ **«ដំឡើងកម្មវិធី»** 3. បញ្ជាក់តាមសារណែនាំ 4. OmniRoute នឹងបង្ហាញនៅលើអេក្រង់ដើមរបស់អ្នកជាកម្មវិធីឯករាជ្យ ### iOS (Safari) 1. បើកផ្ទាំងគ្រប់គ្រង OmniRoute ក្នុង Safari៖ `http://YOUR_IP:20128` 2. ចុចប៊ូតុង **ចែករំលែក** (ប្រអប់ដែលមានព្រួញ) 3. អូសចុះក្រោម ហើយចុច **«បន្ថែមទៅអេក្រង់ដើម»** 4. ដាក់ឈ្មោះវា (លំនាំដើមគឺ "OmniRoute") ហើយចុច **បន្ថែម** 5. OmniRoute នឹងបង្ហាញនៅលើអេក្រង់ដើមរបស់អ្នកជាមួយរូបតំណាងកម្មវិធី ### កុំព្យូទ័រ (Chrome / Edge) 1. បើកផ្ទាំងគ្រប់គ្រង OmniRoute 2. ចុច **រូបតំណាងដំឡើង** នៅក្នុងរបារអាសយដ្ឋាន (ឬ ⋮ → «ដំឡើង OmniRoute...») 3. បញ្ជាក់តាមសារណែនាំ 4. OmniRoute នឹងបើកជាបង្អួចឯករាជ្យ — គ្មានផ្ទាំង និងគ្មានរបារអាសយដ្ឋាន ## មុខងារ ### បទពិសោធន៍ពេញអេក្រង់ Manifest ត្រូវបានកំណត់រចនាសម្ព័ន្ធជាមួយ `display: "fullscreen"` ដែលមានន័យថា កម្មវិធីដែលបានដំឡើងនឹងប្រើអេក្រង់ទាំងមូល — គ្មានចំណុចប្រទាក់កម្មវិធីរុករក និងគ្មានការជាន់លើរបារស្ថានភាព។ វាធ្វើឱ្យផ្ទាំងគ្រប់គ្រងមានអារម្មណ៍ដូចជាកម្មវិធីដើមពិតប្រាកដ។ ### ការគាំទ្រក្រៅបណ្ដាញ OmniRoute រួមបញ្ចូល service worker (`sw.js`) ដែលផ្តល់ការរក្សាទុកក្នុងឃ្លាំងសម្ងាត់ប្រកបដោយភាពឆ្លាតវៃ៖ | ប្រភេទធនធាន | យុទ្ធសាស្ត្រ | ឥរិយាបថ | | -------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | **ស្នូលកម្មវិធី** | ប្រើឃ្លាំងសម្ងាត់ជាមុន | `/`, `/offline`, manifest និងរូបតំណាង ត្រូវបានរក្សាទុកក្នុងឃ្លាំងសម្ងាត់ជាមុនពេលដំឡើង | | **ធនធានថេរ** (CSS, JS, រូបភាព, ពុម្ពអក្សរ) | ប្រើបណ្ដាញជាមុន និងប្រើឃ្លាំងសម្ងាត់ជាជម្រើសបម្រុង | ទាញយកទិន្នន័យថ្មីពីបណ្ដាញ ហើយប្រើឃ្លាំងសម្ងាត់ជំនួស ប្រសិនបើនៅក្រៅបណ្ដាញ | | **Next.js bundles** (`/_next/`) | ប្រើបណ្ដាញជាមុន និងធ្វើបច្ចុប្បន្នភាពឃ្លាំងសម្ងាត់ | ទាញយកពីបណ្ដាញ និងធ្វើបច្ចុប្បន្នភាពឃ្លាំងសម្ងាត់ ហើយផ្តល់កំណែដែលបានរក្សាទុក ប្រសិនបើនៅក្រៅបណ្ដាញ | | **សំណើរុករក** | រំលង (មិនដែលត្រូវបានស្ទាក់ចាប់) | កម្មវិធីរុករកគ្រប់គ្រងការប្តូរពី HTTP/3→HTTP/2 ដោយខ្លួនឯង ហើយរន្ធ QUIC ដែលលែងដំណើរការមិនត្រូវក្លាយជា `Response.error()` ទេ | | **API / ផ្លូវផ្ទាំងគ្រប់គ្រង** (`/api/`, `/a2a`, `/dashboard`) | រំលង (មិនដែលរក្សាទុកក្នុងឃ្លាំងសម្ងាត់) | តែងតែទៅកាន់ម៉ាស៊ីនមេដោយផ្ទាល់ — មិនត្រូវបាន service worker ស្ទាក់ចាប់ឡើយ | ### ទំព័រក្រៅបណ្ដាញ នៅពេលបណ្ដាញមិនអាចប្រើបាន ហើយអ្នកប្រើរុករកទៅកាន់ទំព័រថ្មី service worker នឹងផ្តល់ទំព័រ `/offline` ពិសេស ដែល៖ - បង្ហាញសារ **«បញ្ហាការតភ្ជាប់»** យ៉ាងច្បាស់ - បង្ហាញ **សូចនាករស្ថានភាពលើបណ្ដាញ/ក្រៅបណ្ដាញ** ផ្ទាល់ ដែលធ្វើបច្ចុប្បន្នភាពភ្លាមៗ - ផ្តល់ប៊ូតុង **«ព្យាយាមតភ្ជាប់ឡើងវិញ»** ដើម្បីផ្ទុកឡើងវិញ នៅពេលការតភ្ជាប់ត្រឡប់មកវិញ - ភ្ជាប់ទៅកាន់ **ទំព័រស្ថានភាព** សម្រាប់ការវិនិច្ឆ័យបញ្ហា ### រូបតំណាងកម្មវិធី OmniRoute ផ្តល់រូបតំណាងដែលបានបង្កើនប្រសិទ្ធភាពសម្រាប់វេទិកានីមួយៗ៖ | ឯកសារ | ទំហំ | ប្រើដោយ | | ---------------------- | ----------------- | ------------------------------------ | | `icon-512.png` | 512×512 | សារដំឡើង Android និងអេក្រង់ចាប់ផ្ដើម | | `apple-touch-icon.png` | 180×180 | រូបតំណាងអេក្រង់ដើម iOS | | `icon-192.svg` | 192×192 (វ៉ិចទ័រ) | រូបតំណាងសម្របខ្លួន Android | | `apple-touch-icon.svg` | 180×180 (វ៉ិចទ័រ) | ជម្រើសបម្រុងសម្រាប់ Apple | | `favicon.svg` | វ៉ិចទ័រ | ផ្ទាំងកម្មវិធីរុករក | | `favicon.ico` | ច្រើនទំហំ | កម្មវិធីរុករកចាស់ៗ | ### ការចុះឈ្មោះដោយស្វ័យប្រវត្តិ Service worker ត្រូវបានចុះឈ្មោះដោយស្វ័យប្រវត្តិតាមរយៈ component `` នៅក្នុង root layout។ អ្នកប្រើមិនចាំបាច់ធ្វើអ្វីទេ — កម្មវិធីអាចដំឡើងបានភ្លាមៗ នៅពេលកម្មវិធីរុករករកឃើញ manifest និង service worker ដែលមានសុពលភាព។ ## ស្ថាបត្យកម្មបច្ចេកទេស ### Web App Manifest (`manifest.webmanifest`) បង្កើតដោយ Next.js តាមរយៈ `src/app/manifest.ts`៖ ```json { "name": "OmniRoute", "short_name": "OmniRoute", "description": "OmniRoute គឺជា AI gateway សម្រាប់ LLMs ពីអ្នកផ្តល់សេវាច្រើន។ endpoint តែមួយសម្រាប់អ្នកផ្តល់សេវា AI របស់អ្នកទាំងអស់។", "start_url": "/", "scope": "/", "display": "fullscreen", "orientation": "any", "background_color": "#0b0f1a", "theme_color": "#0b0f1a", "icons": [ { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }, { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" } ] } ``` ### Service Worker (`public/sw.js`) service worker សុទ្ធ (គ្មានភាពអាស្រ័យលើ framework) ដែលមាន៖ - **ដំណាក់កាលដំឡើង**៖ រក្សាទុក app shell ជាមុនក្នុង cache (ទំព័រដើម ទំព័រ offline manifest និងរូបតំណាង) - **ដំណាក់កាលដំណើរការ**៖ សម្អាតកំណែ cache ចាស់ៗ និងគ្រប់គ្រង client ទាំងអស់ - **ដំណាក់កាល Fetch**៖ កំណត់ផ្លូវយ៉ាងឆ្លាតវៃដោយផ្អែកលើប្រភេទ request (navigation, static asset, API) - **ការកំណត់កំណែ Cache**៖ `omniroute-pwa-v3` — បង្កើនតម្លៃនេះដើម្បីបង្ខំឱ្យប្រើ cache ថ្មីនៅពេលធ្វើបច្ចុប្បន្នភាព ### Layout Metadata (`src/app/layout.tsx`) root layout ផ្តល់ meta tag ទាំងអស់ដែលត្រូវការសម្រាប់ការអនុលោមតាម PWA៖ - តំណ `manifest` ទៅកាន់ `/manifest.webmanifest` - `apple-web-app-capable: true` សម្រាប់របៀប standalone របស់ iOS - `apple-web-app-status-bar-style: black-translucent` - `mobile-web-app-capable: yes` សម្រាប់ Android Chrome - `theme-color: #0b0f1a` - `viewport-fit: cover` សម្រាប់ការបង្ហាញពីគែមទៅគែម ### Component៖ `PwaRegister` មានទីតាំងនៅ `src/shared/components/PwaRegister.tsx` ហើយ client component នេះ៖ 1. ដំណើរការនៅពេល mount (តែផ្នែក client ប៉ុណ្ណោះ) 2. ពិនិត្យមើលការគាំទ្រ `serviceWorker` នៅក្នុង browser 3. ចុះឈ្មោះ `/sw.js` ដោយស្ងាត់ស្ងៀម (error ត្រូវបានមិនអើពើ ដើម្បីជៀសវាងការរាំងខ្ទប់ app) 4. មិនបង្ហាញអ្វីឡើយ (`return null`) — វាជា component សម្រាប់តែ side effect ប៉ុណ្ណោះ ## ប្រើជាមួយ Termux (Android) នៅពេលដំណើរការ OmniRoute លើ Android តាមរយៈ Termux នោះ PWA ដំណើរការយ៉ាងរលូន៖ 1. ចាប់ផ្តើម OmniRoute នៅក្នុង Termux៖ `npx omniroute` 2. បើក Chrome នៅលើទូរសព្ទដដែល៖ `http://localhost:20128` 3. ដំឡើង PWA តាមរយៈ "បន្ថែមទៅអេក្រង់ដើម" 4. PWA ភ្ជាប់ទៅកាន់ server Termux ក្នុងមូលដ្ឋាន — អ្វីៗទាំងអស់ដំណើរការលើឧបករណ៍ផ្ទាល់ ការរួមបញ្ចូលគ្នានេះមានន័យថា ទូរសព្ទ Android របស់អ្នកគឺជា **server** (Termux) ផង និងជា **client** (PWA) ផង — ជា AI gateway ដែលដំណើរការដោយឯករាជ្យ និងពេញលេញ។ ## ប្រើពីឧបករណ៍ផ្សេងទៀត ដំឡើង PWA នៅលើឧបករណ៍ណាមួយដែលអាចចូលប្រើ OmniRoute server របស់អ្នកតាម browser បាន៖ - **ទូរសព្ទ/ថេប្លេតមួយផ្សេងទៀត**៖ ចូលទៅកាន់ `http://PHONE_IP:20128` ហើយដំឡើង PWA - **Laptop**៖ បើក Chrome/Edge ហើយដំឡើងវាជា desktop PWA - **Smart TV ដែលមាន browser**៖ ចូលប្រើ dashboard ជាទម្រង់ពេញអេក្រង់ ## ការកំណត់តាមបំណង ### ឈ្មោះ Instance ចំណងជើង PWA អនុវត្តតាមការកំណត់ **ឈ្មោះ Instance** ពី `Dashboard → Settings`។ ប្រសិនបើអ្នកប្តូរឈ្មោះ instance របស់អ្នកទៅជា "AI Gateway របស់ខ្ញុំ" នោះ PWA ដែលបានដំឡើងនឹងបង្ហាញឈ្មោះនោះ។ ### Favicon ផ្ទាល់ខ្លួន ប្រសិនបើអ្នក upload favicon ផ្ទាល់ខ្លួនតាមរយៈ `Dashboard → Settings` រូបតំណាង PWA នៅលើ desktop នឹងប្រើរូបតំណាងផ្ទាល់ខ្លួននោះ។ រូបតំណាងលើអេក្រង់ដើមរបស់ឧបករណ៍ចល័តប្រើឯកសារ `icon-512.png` និង `apple-touch-icon.png` ដែលបានបង្កើតជាមុន។ ## ដែនកំណត់ - **មិនមានការជូនដំណឹង Push** — Service worker មិនអនុវត្ត Push API ទេ។ ផ្ទុយទៅវិញ ការជូនដំណឹងត្រូវបានគ្រប់គ្រងដោយកម្មវិធី Electron។ - **មិនមានការធ្វើសមកាលកម្មនៅផ្ទៃខាងក្រោយ** — សកម្មភាពពេលគ្មានអ៊ីនធឺណិតមិនត្រូវបានដាក់ជាជួរសម្រាប់ដំណើរការឡើងវិញទេ។ PWA នេះត្រូវបានប្រើជាចម្បងសម្រាប់មើលផ្ទាំងគ្រប់គ្រង។ - **ការរឹតបន្តឹងរបស់ iOS** — Safari នៅលើ iOS មិនគាំទ្រមុខងារ PWA ទាំងអស់ទេ (ឧ. ការបង្ហាញសារណែនាំឱ្យដំឡើងត្រូវធ្វើដោយដៃ ហើយ Service worker នៅផ្ទៃខាងក្រោយមានដែនកំណត់)។ - **ទំហំឃ្លាំងសម្ងាត់** — Service worker រក្សាទុកតែធនធានឋិតិវន្តក្នុងឃ្លាំងសម្ងាត់ប៉ុណ្ណោះ។ ទិន្នន័យឆ្លើយតបដែលមានទំហំធំពី route `/api/` មិនត្រូវបានរក្សាទុកក្នុងឃ្លាំងសម្ងាត់ឡើយ។ - **រូបតំណាងផ្ទាល់ខ្លួននៅលើឧបករណ៍ចល័ត** — ការផ្លាស់ប្តូរ favicon នៅក្នុងការកំណត់ មិនធ្វើបច្ចុប្បន្នភាពរូបតំណាងនៅលើអេក្រង់ដើមរបស់ឧបករណ៍ចល័តទេ (វាទាមទារឱ្យបង្កើតរូបតំណាង PWA ឡើងវិញ)។ ## ឯកសារយោង | ឯកសារ | គោលបំណង | | --------------------------------------- | -------------------------------------------------------------------- | | `src/app/manifest.ts` | Route manifest របស់ Next.js (បង្កើត `manifest.webmanifest`) | | `public/sw.js` | Service worker ដែលមានតក្កវិជ្ជារក្សាទុកក្នុងឃ្លាំងសម្ងាត់ | | `src/shared/components/PwaRegister.tsx` | Component ខាង client ដែលចុះឈ្មោះ Service worker | | `src/app/offline/page.tsx` | ទំព័រជំនួសពេលគ្មានអ៊ីនធឺណិត ដែលមានសូចនាករស្ថានភាពផ្ទាល់ | | `src/app/layout.tsx` | Layout ឫសដែលមាន metadata របស់ PWA (apple-web-app, theme-color ជាដើម) | | `public/icon-512.png` | រូបតំណាង PNG ទំហំ 512×512 (Android, អេក្រង់ចាប់ផ្តើម) | | `public/apple-touch-icon.png` | រូបតំណាង PNG ទំហំ 180×180 (អេក្រង់ដើមរបស់ iOS) | | `public/icon-192.svg` | រូបតំណាង SVG ទំហំ 192×192 (រូបតំណាងសម្របខ្លួនរបស់ Android) | | `public/apple-touch-icon.svg` | រូបតំណាង SVG ទំហំ 180×180 (ជម្រើសជំនួសសម្រាប់ Apple) |