[{"data":1,"prerenderedAt":2309},["ShallowReactive",2],{"page-\u002Fwebchat\u002Fandroid":3},{"id":4,"title":5,"body":6,"description":2301,"endpoint":2302,"extension":2303,"icon":2302,"meta":2304,"method":2302,"nav":2302,"navigation":337,"path":2305,"seo":2306,"stem":2307,"__hash__":2308},"docs\u002Fwebchat\u002Fandroid.md","Integrasi Android",{"type":7,"value":8,"toc":2287},"minimark",[9,18,23,42,64,160,180,183,357,368,372,383,668,672,679,1088,1179,1210,1214,1224,1295,1308,1312,1321,1581,1657,1665,1669,1679,1699,1702,1709,1713,1720,1965,1981,1985,1988,2026,2033,2037,2040,2107,2114,2118,2125,2139,2143,2198,2202,2283],[10,11,12,13,17],"p",{},"Webchat bisa dibuka layar penuh di dalam aplikasi Android lewat ",[14,15,16],"code",{},"WebView",". Aplikasi mengirim nama dan nomor HP user yang login, sehingga form pra-chat dilewati. Contoh di halaman ini memakai Kotlin.",[19,20,22],"h2",{"id":21},"url-chat","URL chat",[10,24,25,26,30,31,34,35,38,39,41],{},"Ambil ID channel di ",[27,28,29],"strong",{},"Integrasi"," → ",[27,32,33],{},"Webchat"," → ikon edit → bagian ",[27,36,37],{},"Pasang",". Buka URL berikut di ",[14,40,16],{},":",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-bash shiki shiki-themes github-light github-dark","https:\u002F\u002Fapp.csku.ai\u002Fwebchat\u002F\u003CID_CHANNEL>?embed=app\n","bash","",[14,50,51],{"__ignoreMap":48},[52,53,56,60],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sScJk","https:\u002F\u002Fapp.csku.ai\u002Fwebchat\u002F",[52,61,63],{"class":62},"sVt8B","\u003CID_CHANNEL>?embed=app\n",[65,66,67,83],"table",{},[68,69,70],"thead",{},[71,72,73,77,80],"tr",{},[74,75,76],"th",{},"Parameter",[74,78,79],{},"Wajib",[74,81,82],{},"Keterangan",[84,85,86,100,113,144],"tbody",{},[71,87,88,94,97],{},[89,90,91],"td",{},[14,92,93],{},"embed=app",[89,95,96],{},"Ya",[89,98,99],{},"Mode aplikasi: layar penuh, langsung terbuka, menerima pesan dari aplikasi.",[71,101,102,107,110],{},[89,103,104],{},[14,105,106],{},"header=0",[89,108,109],{},"Tidak",[89,111,112],{},"Menyembunyikan header chat (nama, logo, tombol riwayat, tombol tutup). Pakai jika aplikasi punya toolbar sendiri.",[71,114,115,127,129],{},[89,116,117,120,121,120,124],{},[14,118,119],{},"name",", ",[14,122,123],{},"phone",[14,125,126],{},"email",[89,128,109],{},[89,130,131,132,137,138,140,141,143],{},"Data user yang login, aturannya sama dengan ",[133,134,136],"a",{"href":135},"#data-user-identify","identify",". Jika ",[14,139,119],{}," dan ",[14,142,123],{}," valid, form pra-chat dilewati. Data tidak valid diabaikan.",[71,145,146,151,153],{},[89,147,148],{},[14,149,150],{},"autostart=1",[89,152,109],{},[89,154,155,156,159],{},"Sesi chat langsung dibuat saat halaman dibuka, tidak menunggu pesan pertama. Event ",[14,157,158],{},"session"," langsung terkirim.",[10,161,162,163,120,166,120,168,120,170,172,173,176,177,179],{},"Parameter ",[14,164,165],{},"header",[14,167,119],{},[14,169,123],{},[14,171,126],{},", dan ",[14,174,175],{},"autostart"," hanya berlaku bersama ",[14,178,93],{},", dan nilainya harus persis seperti di tabel.",[10,181,182],{},"Cara tercepat: buka URL dengan data user, tanpa kode tambahan.",[43,184,188],{"className":185,"code":186,"language":187,"meta":48,"style":48},"language-kotlin shiki shiki-themes github-light github-dark","val url = Uri.parse(\"https:\u002F\u002Fapp.csku.ai\u002Fwebchat\u002F$CHANNEL_KEY\").buildUpon()\n    .appendQueryParameter(\"embed\", \"app\")\n    .appendQueryParameter(\"autostart\", \"1\")\n    .appendQueryParameter(\"name\", user.name)\n    .appendQueryParameter(\"phone\", user.phone)\n    .appendQueryParameter(\"email\", user.email ?: \"\")\n    .build()\n\nwebView.loadUrl(url.toString())\n","kotlin",[14,189,190,231,253,272,287,302,322,332,339],{"__ignoreMap":48},[52,191,192,196,199,202,205,208,211,215,219,222,225,228],{"class":54,"line":55},[52,193,195],{"class":194},"szBVR","val",[52,197,198],{"class":62}," url ",[52,200,201],{"class":194},"=",[52,203,204],{"class":62}," Uri.",[52,206,207],{"class":58},"parse",[52,209,210],{"class":62},"(",[52,212,214],{"class":213},"sZZnC","\"https:\u002F\u002Fapp.csku.ai\u002Fwebchat\u002F",[52,216,218],{"class":217},"sj4cs","$CHANNEL_KEY",[52,220,221],{"class":213},"\"",[52,223,224],{"class":62},").",[52,226,227],{"class":58},"buildUpon",[52,229,230],{"class":62},"()\n",[52,232,234,237,240,242,245,247,250],{"class":54,"line":233},2,[52,235,236],{"class":62},"    .",[52,238,239],{"class":58},"appendQueryParameter",[52,241,210],{"class":62},[52,243,244],{"class":213},"\"embed\"",[52,246,120],{"class":62},[52,248,249],{"class":213},"\"app\"",[52,251,252],{"class":62},")\n",[52,254,256,258,260,262,265,267,270],{"class":54,"line":255},3,[52,257,236],{"class":62},[52,259,239],{"class":58},[52,261,210],{"class":62},[52,263,264],{"class":213},"\"autostart\"",[52,266,120],{"class":62},[52,268,269],{"class":213},"\"1\"",[52,271,252],{"class":62},[52,273,275,277,279,281,284],{"class":54,"line":274},4,[52,276,236],{"class":62},[52,278,239],{"class":58},[52,280,210],{"class":62},[52,282,283],{"class":213},"\"name\"",[52,285,286],{"class":62},", user.name)\n",[52,288,290,292,294,296,299],{"class":54,"line":289},5,[52,291,236],{"class":62},[52,293,239],{"class":58},[52,295,210],{"class":62},[52,297,298],{"class":213},"\"phone\"",[52,300,301],{"class":62},", user.phone)\n",[52,303,305,307,309,311,314,317,320],{"class":54,"line":304},6,[52,306,236],{"class":62},[52,308,239],{"class":58},[52,310,210],{"class":62},[52,312,313],{"class":213},"\"email\"",[52,315,316],{"class":62},", user.email ?: ",[52,318,319],{"class":213},"\"\"",[52,321,252],{"class":62},[52,323,325,327,330],{"class":54,"line":324},7,[52,326,236],{"class":62},[52,328,329],{"class":58},"build",[52,331,230],{"class":62},[52,333,335],{"class":54,"line":334},8,[52,336,338],{"emptyLinePlaceholder":337},true,"\n",[52,340,342,345,348,351,354],{"class":54,"line":341},9,[52,343,344],{"class":62},"webView.",[52,346,347],{"class":58},"loadUrl",[52,349,350],{"class":62},"(url.",[52,352,353],{"class":58},"toString",[52,355,356],{"class":62},"())\n",[358,359,362],"callout",{"title":360,"type":361},"Data di URL tercatat","info",[10,363,364,365,367],{},"Parameter URL tersimpan di riwayat dan log server seperti URL lainnya. Token chat tidak bisa dikirim lewat URL; kirim lewat ",[14,366,136],{},".",[19,369,371],{"id":370},"setup-webview","Setup WebView",[10,373,374,375,378,379,382],{},"Aktifkan JavaScript dan DOM storage (sesi chat disimpan di ",[14,376,377],{},"localStorage","), daftarkan bridge bernama ",[14,380,381],{},"CskuWebchatBridge",", lalu muat URL chat.",[43,384,386],{"className":185,"code":385,"language":187,"meta":48,"style":48},"class SupportChatActivity : AppCompatActivity() {\n\n    private lateinit var webView: WebView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        webView = WebView(this)\n        setContentView(webView)\n\n        webView.settings.apply {\n            javaScriptEnabled = true\n            domStorageEnabled = true\n        }\n\n        webView.addJavascriptInterface(ChatBridge(), \"CskuWebchatBridge\")\n        webView.webViewClient = ChatWebViewClient()\n        webView.webChromeClient = ChatChromeClient(this)\n\n        webView.loadUrl(\"https:\u002F\u002Fapp.csku.ai\u002Fwebchat\u002F$CHANNEL_KEY?embed=app\")\n    }\n\n    \u002F\u002F Tombol back menutup chat, bukan halaman sebelumnya di WebView\n    @Deprecated(\"Deprecated in Java\")\n    override fun onBackPressed() = finish()\n}\n",[14,387,388,405,409,426,430,450,463,480,488,492,504,515,525,531,536,558,571,588,593,611,617,622,629,642,662],{"__ignoreMap":48},[52,389,390,393,396,399,402],{"class":54,"line":55},[52,391,392],{"class":194},"class",[52,394,395],{"class":58}," SupportChatActivity",[52,397,398],{"class":62}," : ",[52,400,401],{"class":58},"AppCompatActivity",[52,403,404],{"class":62},"() {\n",[52,406,407],{"class":54,"line":233},[52,408,338],{"emptyLinePlaceholder":337},[52,410,411,414,417,420,423],{"class":54,"line":255},[52,412,413],{"class":194},"    private",[52,415,416],{"class":194}," lateinit",[52,418,419],{"class":194}," var",[52,421,422],{"class":62}," webView: ",[52,424,425],{"class":58},"WebView\n",[52,427,428],{"class":54,"line":274},[52,429,338],{"emptyLinePlaceholder":337},[52,431,432,435,438,441,444,447],{"class":54,"line":289},[52,433,434],{"class":194},"    override",[52,436,437],{"class":194}," fun",[52,439,440],{"class":58}," onCreate",[52,442,443],{"class":62},"(savedInstanceState: ",[52,445,446],{"class":58},"Bundle",[52,448,449],{"class":62},"?) {\n",[52,451,452,455,457,460],{"class":54,"line":304},[52,453,454],{"class":217},"        super",[52,456,367],{"class":62},[52,458,459],{"class":58},"onCreate",[52,461,462],{"class":62},"(savedInstanceState)\n",[52,464,465,468,470,473,475,478],{"class":54,"line":324},[52,466,467],{"class":62},"        webView ",[52,469,201],{"class":194},[52,471,472],{"class":58}," WebView",[52,474,210],{"class":62},[52,476,477],{"class":217},"this",[52,479,252],{"class":62},[52,481,482,485],{"class":54,"line":334},[52,483,484],{"class":58},"        setContentView",[52,486,487],{"class":62},"(webView)\n",[52,489,490],{"class":54,"line":341},[52,491,338],{"emptyLinePlaceholder":337},[52,493,495,498,501],{"class":54,"line":494},10,[52,496,497],{"class":62},"        webView.settings.",[52,499,500],{"class":58},"apply",[52,502,503],{"class":62}," {\n",[52,505,507,510,512],{"class":54,"line":506},11,[52,508,509],{"class":62},"            javaScriptEnabled ",[52,511,201],{"class":194},[52,513,514],{"class":217}," true\n",[52,516,518,521,523],{"class":54,"line":517},12,[52,519,520],{"class":62},"            domStorageEnabled ",[52,522,201],{"class":194},[52,524,514],{"class":217},[52,526,528],{"class":54,"line":527},13,[52,529,530],{"class":62},"        }\n",[52,532,534],{"class":54,"line":533},14,[52,535,338],{"emptyLinePlaceholder":337},[52,537,539,542,545,547,550,553,556],{"class":54,"line":538},15,[52,540,541],{"class":62},"        webView.",[52,543,544],{"class":58},"addJavascriptInterface",[52,546,210],{"class":62},[52,548,549],{"class":58},"ChatBridge",[52,551,552],{"class":62},"(), ",[52,554,555],{"class":213},"\"CskuWebchatBridge\"",[52,557,252],{"class":62},[52,559,561,564,566,569],{"class":54,"line":560},16,[52,562,563],{"class":62},"        webView.webViewClient ",[52,565,201],{"class":194},[52,567,568],{"class":58}," ChatWebViewClient",[52,570,230],{"class":62},[52,572,574,577,579,582,584,586],{"class":54,"line":573},17,[52,575,576],{"class":62},"        webView.webChromeClient ",[52,578,201],{"class":194},[52,580,581],{"class":58}," ChatChromeClient",[52,583,210],{"class":62},[52,585,477],{"class":217},[52,587,252],{"class":62},[52,589,591],{"class":54,"line":590},18,[52,592,338],{"emptyLinePlaceholder":337},[52,594,596,598,600,602,604,606,609],{"class":54,"line":595},19,[52,597,541],{"class":62},[52,599,347],{"class":58},[52,601,210],{"class":62},[52,603,214],{"class":213},[52,605,218],{"class":217},[52,607,608],{"class":213},"?embed=app\"",[52,610,252],{"class":62},[52,612,614],{"class":54,"line":613},20,[52,615,616],{"class":62},"    }\n",[52,618,620],{"class":54,"line":619},21,[52,621,338],{"emptyLinePlaceholder":337},[52,623,625],{"class":54,"line":624},22,[52,626,628],{"class":627},"sJ8bj","    \u002F\u002F Tombol back menutup chat, bukan halaman sebelumnya di WebView\n",[52,630,632,635,637,640],{"class":54,"line":631},23,[52,633,634],{"class":58},"    @Deprecated",[52,636,210],{"class":62},[52,638,639],{"class":213},"\"Deprecated in Java\"",[52,641,252],{"class":62},[52,643,645,647,649,652,655,657,660],{"class":54,"line":644},24,[52,646,434],{"class":194},[52,648,437],{"class":194},[52,650,651],{"class":58}," onBackPressed",[52,653,654],{"class":62},"() ",[52,656,201],{"class":194},[52,658,659],{"class":58}," finish",[52,661,230],{"class":62},[52,663,665],{"class":54,"line":664},25,[52,666,667],{"class":62},"}\n",[19,669,671],{"id":670},"data-user-identify","Data user (identify)",[10,673,674,675,678],{},"Kirim data user setelah ",[14,676,677],{},"onPageFinished",". Jika data tiba sebelum chat selesai dimuat, datanya tetap dipakai.",[43,680,682],{"className":185,"code":681,"language":187,"meta":48,"style":48},"private inner class ChatWebViewClient : WebViewClient() {\n\n    override fun onPageFinished(view: WebView, url: String) {\n        val user = Session.currentUser ?: return\n\n        val payload = JSONObject()\n            .put(\"name\", user.name)\n            .put(\"phone\", user.phone)\n            .put(\"email\", user.email ?: \"\")\n        \u002F\u002F Token chat dari server Anda (event session); lewati jika belum ada\n        user.chatToken?.let { payload.put(\"token\", it) }\n\n        postToChat(view, \"identify\", payload)\n    }\n\n    \u002F\u002F Link di dalam pesan dibuka di browser, bukan di WebView chat\n    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {\n        val url = request.url\n        if (url.host == \"app.csku.ai\") return false\n        startActivity(Intent(Intent.ACTION_VIEW, url))\n        return true\n    }\n}\n\nfun postToChat(view: WebView, type: String, payload: JSONObject? = null) {\n    val msg = JSONObject().put(\"source\", \"csku-webchat\").put(\"type\", type)\n    if (payload != null) msg.put(\"payload\", payload)\n    view.evaluateJavascript(\"window.postMessage($msg, '*')\", null)\n}\n",[14,683,684,704,708,731,747,751,765,779,791,807,812,833,837,851,855,859,864,891,902,925,938,945,949,953,957,990,1030,1056,1083],{"__ignoreMap":48},[52,685,686,689,692,695,697,699,702],{"class":54,"line":55},[52,687,688],{"class":194},"private",[52,690,691],{"class":194}," inner",[52,693,694],{"class":194}," class",[52,696,568],{"class":58},[52,698,398],{"class":62},[52,700,701],{"class":58},"WebViewClient",[52,703,404],{"class":62},[52,705,706],{"class":54,"line":233},[52,707,338],{"emptyLinePlaceholder":337},[52,709,710,712,714,717,720,722,725,728],{"class":54,"line":255},[52,711,434],{"class":194},[52,713,437],{"class":194},[52,715,716],{"class":58}," onPageFinished",[52,718,719],{"class":62},"(view: ",[52,721,16],{"class":58},[52,723,724],{"class":62},", url: ",[52,726,727],{"class":58},"String",[52,729,730],{"class":62},") {\n",[52,732,733,736,739,741,744],{"class":54,"line":274},[52,734,735],{"class":194},"        val",[52,737,738],{"class":62}," user ",[52,740,201],{"class":194},[52,742,743],{"class":62}," Session.currentUser ?: ",[52,745,746],{"class":194},"return\n",[52,748,749],{"class":54,"line":289},[52,750,338],{"emptyLinePlaceholder":337},[52,752,753,755,758,760,763],{"class":54,"line":304},[52,754,735],{"class":194},[52,756,757],{"class":62}," payload ",[52,759,201],{"class":194},[52,761,762],{"class":58}," JSONObject",[52,764,230],{"class":62},[52,766,767,770,773,775,777],{"class":54,"line":324},[52,768,769],{"class":62},"            .",[52,771,772],{"class":58},"put",[52,774,210],{"class":62},[52,776,283],{"class":213},[52,778,286],{"class":62},[52,780,781,783,785,787,789],{"class":54,"line":334},[52,782,769],{"class":62},[52,784,772],{"class":58},[52,786,210],{"class":62},[52,788,298],{"class":213},[52,790,301],{"class":62},[52,792,793,795,797,799,801,803,805],{"class":54,"line":341},[52,794,769],{"class":62},[52,796,772],{"class":58},[52,798,210],{"class":62},[52,800,313],{"class":213},[52,802,316],{"class":62},[52,804,319],{"class":213},[52,806,252],{"class":62},[52,808,809],{"class":54,"line":494},[52,810,811],{"class":627},"        \u002F\u002F Token chat dari server Anda (event session); lewati jika belum ada\n",[52,813,814,817,820,823,825,827,830],{"class":54,"line":506},[52,815,816],{"class":62},"        user.chatToken?.",[52,818,819],{"class":58},"let",[52,821,822],{"class":62}," { payload.",[52,824,772],{"class":58},[52,826,210],{"class":62},[52,828,829],{"class":213},"\"token\"",[52,831,832],{"class":62},", it) }\n",[52,834,835],{"class":54,"line":517},[52,836,338],{"emptyLinePlaceholder":337},[52,838,839,842,845,848],{"class":54,"line":527},[52,840,841],{"class":58},"        postToChat",[52,843,844],{"class":62},"(view, ",[52,846,847],{"class":213},"\"identify\"",[52,849,850],{"class":62},", payload)\n",[52,852,853],{"class":54,"line":533},[52,854,616],{"class":62},[52,856,857],{"class":54,"line":538},[52,858,338],{"emptyLinePlaceholder":337},[52,860,861],{"class":54,"line":560},[52,862,863],{"class":627},"    \u002F\u002F Link di dalam pesan dibuka di browser, bukan di WebView chat\n",[52,865,866,868,870,873,875,877,880,883,886,889],{"class":54,"line":573},[52,867,434],{"class":194},[52,869,437],{"class":194},[52,871,872],{"class":58}," shouldOverrideUrlLoading",[52,874,719],{"class":62},[52,876,16],{"class":58},[52,878,879],{"class":62},", request: ",[52,881,882],{"class":58},"WebResourceRequest",[52,884,885],{"class":62},"): ",[52,887,888],{"class":58},"Boolean",[52,890,503],{"class":62},[52,892,893,895,897,899],{"class":54,"line":590},[52,894,735],{"class":194},[52,896,198],{"class":62},[52,898,201],{"class":194},[52,900,901],{"class":62}," request.url\n",[52,903,904,907,910,913,916,919,922],{"class":54,"line":595},[52,905,906],{"class":194},"        if",[52,908,909],{"class":62}," (url.host ",[52,911,912],{"class":194},"==",[52,914,915],{"class":213}," \"app.csku.ai\"",[52,917,918],{"class":62},") ",[52,920,921],{"class":194},"return",[52,923,924],{"class":217}," false\n",[52,926,927,930,932,935],{"class":54,"line":613},[52,928,929],{"class":58},"        startActivity",[52,931,210],{"class":62},[52,933,934],{"class":58},"Intent",[52,936,937],{"class":62},"(Intent.ACTION_VIEW, url))\n",[52,939,940,943],{"class":54,"line":619},[52,941,942],{"class":194},"        return",[52,944,514],{"class":217},[52,946,947],{"class":54,"line":624},[52,948,616],{"class":62},[52,950,951],{"class":54,"line":631},[52,952,667],{"class":62},[52,954,955],{"class":54,"line":644},[52,956,338],{"emptyLinePlaceholder":337},[52,958,959,962,965,967,969,972,974,977,980,983,985,988],{"class":54,"line":664},[52,960,961],{"class":194},"fun",[52,963,964],{"class":58}," postToChat",[52,966,719],{"class":62},[52,968,16],{"class":58},[52,970,971],{"class":62},", type: ",[52,973,727],{"class":58},[52,975,976],{"class":62},", payload: ",[52,978,979],{"class":58},"JSONObject",[52,981,982],{"class":62},"? ",[52,984,201],{"class":194},[52,986,987],{"class":217}," null",[52,989,730],{"class":62},[52,991,993,996,999,1001,1003,1006,1008,1010,1013,1015,1018,1020,1022,1024,1027],{"class":54,"line":992},26,[52,994,995],{"class":194},"    val",[52,997,998],{"class":62}," msg ",[52,1000,201],{"class":194},[52,1002,762],{"class":58},[52,1004,1005],{"class":62},"().",[52,1007,772],{"class":58},[52,1009,210],{"class":62},[52,1011,1012],{"class":213},"\"source\"",[52,1014,120],{"class":62},[52,1016,1017],{"class":213},"\"csku-webchat\"",[52,1019,224],{"class":62},[52,1021,772],{"class":58},[52,1023,210],{"class":62},[52,1025,1026],{"class":213},"\"type\"",[52,1028,1029],{"class":62},", type)\n",[52,1031,1033,1036,1039,1042,1044,1047,1049,1051,1054],{"class":54,"line":1032},27,[52,1034,1035],{"class":194},"    if",[52,1037,1038],{"class":62}," (payload ",[52,1040,1041],{"class":194},"!=",[52,1043,987],{"class":217},[52,1045,1046],{"class":62},") msg.",[52,1048,772],{"class":58},[52,1050,210],{"class":62},[52,1052,1053],{"class":213},"\"payload\"",[52,1055,850],{"class":62},[52,1057,1059,1062,1065,1067,1070,1073,1076,1078,1081],{"class":54,"line":1058},28,[52,1060,1061],{"class":62},"    view.",[52,1063,1064],{"class":58},"evaluateJavascript",[52,1066,210],{"class":62},[52,1068,1069],{"class":213},"\"window.postMessage(",[52,1071,1072],{"class":217},"$msg",[52,1074,1075],{"class":213},", '*')\"",[52,1077,120],{"class":62},[52,1079,1080],{"class":217},"null",[52,1082,252],{"class":62},[52,1084,1086],{"class":54,"line":1085},29,[52,1087,667],{"class":62},[65,1089,1090,1102],{},[68,1091,1092],{},[71,1093,1094,1097,1099],{},[74,1095,1096],{},"Field",[74,1098,79],{},[74,1100,1101],{},"Aturan",[84,1103,1104,1115,1147,1158],{},[71,1105,1106,1110,1112],{},[89,1107,1108],{},[14,1109,119],{},[89,1111,96],{},[89,1113,1114],{},"2–60 karakter.",[71,1116,1117,1121,1123],{},[89,1118,1119],{},[14,1120,123],{},[89,1122,96],{},[89,1124,1125,1126,1129,1130,120,1133,120,1135,172,1138,1140,1141,120,1144,367],{},"8–15 digit, boleh diawali ",[14,1127,1128],{},"+",". Spasi, ",[14,1131,1132],{},"-",[14,1134,210],{},[14,1136,1137],{},")",[14,1139,367],{}," dibuang dulu. Contoh: ",[14,1142,1143],{},"081234567890",[14,1145,1146],{},"+6281234567890",[71,1148,1149,1153,1155],{},[89,1150,1151],{},[14,1152,126],{},[89,1154,109],{},[89,1156,1157],{},"Format email valid, maksimal 120 karakter.",[71,1159,1160,1165,1167],{},[89,1161,1162],{},[14,1163,1164],{},"token",[89,1166,109],{},[89,1168,1169,1170,1172,1173,120,1176,1178],{},"Token chat dari event ",[14,1171,158],{},". 16–128 karakter: huruf, angka, ",[14,1174,1175],{},"_",[14,1177,1132],{},". Token salah format diabaikan.",[1180,1181,1182,1189,1192,1198,1204],"ul",{},[1183,1184,1185,1186,367],"li",{},"Data valid: form pra-chat dilewati, dan tim CS melihat nama serta nomor ini di menu ",[27,1187,1188],{},"Chat",[1183,1190,1191],{},"Data tidak valid: diabaikan, user melihat form pra-chat seperti biasa.",[1183,1193,1194,1195,1197],{},"Hanya ",[14,1196,136],{}," valid pertama di setiap pemuatan halaman yang dipakai.",[1183,1199,1200,1201,1203],{},"Tanpa ",[14,1202,1164],{},": jika perangkat ini sudah pernah chat, profil yang tersimpan tidak ditimpa.",[1183,1205,1206,1207,1209],{},"Dengan ",[14,1208,1164],{},": chat di perangkat ini diganti dengan chat milik token tersebut, termasuk riwayatnya.",[19,1211,1213],{"id":1212},"pesan-dari-aplikasi-ke-chat","Pesan dari aplikasi ke chat",[10,1215,1216,1217,1220,1221,367],{},"Semua dikirim lewat ",[14,1218,1219],{},"postToChat(webView, type)"," dengan format ",[14,1222,1223],{},"{\"source\":\"csku-webchat\",\"type\":\"...\",\"payload\":{...}}",[65,1225,1226,1241],{},[68,1227,1228],{},[71,1229,1230,1235,1238],{},[74,1231,1232],{},[14,1233,1234],{},"type",[74,1236,1237],{},"Payload",[74,1239,1240],{},"Fungsi",[84,1242,1243,1257,1269,1281],{},[71,1244,1245,1249,1254],{},[89,1246,1247],{},[14,1248,136],{},[89,1250,1251],{},[14,1252,1253],{},"{ name, phone, email, token }",[89,1255,1256],{},"Mengisi data user.",[71,1258,1259,1264,1266],{},[89,1260,1261],{},[14,1262,1263],{},"open",[89,1265,1132],{},[89,1267,1268],{},"Menandai chat sedang dilihat. Jumlah belum dibaca direset ke 0.",[71,1270,1271,1276,1278],{},[89,1272,1273],{},[14,1274,1275],{},"close",[89,1277,1132],{},[89,1279,1280],{},"Menandai chat tidak sedang dilihat. Pesan baru dihitung belum dibaca.",[71,1282,1283,1288,1290],{},[89,1284,1285],{},[14,1286,1287],{},"history",[89,1289,1132],{},[89,1291,1292,1293,367],{},"Membuka daftar riwayat percakapan. Hanya berlaku jika user punya lebih dari satu percakapan. Pakai dari toolbar aplikasi saat ",[14,1294,106],{},[358,1296,1299],{"title":1297,"type":1298},"WebView di background","tip",[10,1300,1301,1302,1304,1305,1307],{},"Jika WebView chat disimpan di background (misalnya di bottom sheet), kirim ",[14,1303,1275],{}," saat disembunyikan dan ",[14,1306,1263],{}," saat ditampilkan lagi, supaya badge belum dibaca akurat.",[19,1309,1311],{"id":1310},"event-dari-chat-ke-aplikasi","Event dari chat ke aplikasi",[10,1313,1314,1315,1318,1319,367],{},"Chat memanggil ",[14,1316,1317],{},"CskuWebchatBridge.postMessage(json)"," dengan string JSON ",[14,1320,1223],{},[43,1322,1324],{"className":185,"code":1323,"language":187,"meta":48,"style":48},"private inner class ChatBridge {\n    @JavascriptInterface\n    fun postMessage(json: String) {\n        val msg = runCatching { JSONObject(json) }.getOrNull() ?: return\n        if (msg.optString(\"source\") != \"csku-webchat\") return\n\n        runOnUiThread {\n            when (msg.optString(\"type\")) {\n                \"ready\" -> { \u002F* halaman chat siap *\u002F }\n                \"unread\" -> updateBadge(msg.optJSONObject(\"payload\")?.optInt(\"count\") ?: 0)\n                \"close\" -> finish() \u002F\u002F user menekan tombol tutup di header chat\n                \"session\" -> msg.optJSONObject(\"payload\")?.optString(\"token\")\n                    ?.takeIf { it.isNotEmpty() }\n                    ?.let { saveChatTokenToServer(it) }\n            }\n        }\n    }\n}\n",[14,1325,1326,1339,1344,1359,1386,1411,1415,1422,1438,1454,1493,1507,1533,1550,1564,1569,1573,1577],{"__ignoreMap":48},[52,1327,1328,1330,1332,1334,1337],{"class":54,"line":55},[52,1329,688],{"class":194},[52,1331,691],{"class":194},[52,1333,694],{"class":194},[52,1335,1336],{"class":58}," ChatBridge",[52,1338,503],{"class":62},[52,1340,1341],{"class":54,"line":233},[52,1342,1343],{"class":58},"    @JavascriptInterface\n",[52,1345,1346,1349,1352,1355,1357],{"class":54,"line":255},[52,1347,1348],{"class":194},"    fun",[52,1350,1351],{"class":58}," postMessage",[52,1353,1354],{"class":62},"(json: ",[52,1356,727],{"class":58},[52,1358,730],{"class":62},[52,1360,1361,1363,1365,1367,1370,1373,1375,1378,1381,1384],{"class":54,"line":274},[52,1362,735],{"class":194},[52,1364,998],{"class":62},[52,1366,201],{"class":194},[52,1368,1369],{"class":58}," runCatching",[52,1371,1372],{"class":62}," { ",[52,1374,979],{"class":58},[52,1376,1377],{"class":62},"(json) }.",[52,1379,1380],{"class":58},"getOrNull",[52,1382,1383],{"class":62},"() ?: ",[52,1385,746],{"class":194},[52,1387,1388,1390,1393,1396,1398,1400,1402,1404,1407,1409],{"class":54,"line":289},[52,1389,906],{"class":194},[52,1391,1392],{"class":62}," (msg.",[52,1394,1395],{"class":58},"optString",[52,1397,210],{"class":62},[52,1399,1012],{"class":213},[52,1401,918],{"class":62},[52,1403,1041],{"class":194},[52,1405,1406],{"class":213}," \"csku-webchat\"",[52,1408,918],{"class":62},[52,1410,746],{"class":194},[52,1412,1413],{"class":54,"line":304},[52,1414,338],{"emptyLinePlaceholder":337},[52,1416,1417,1420],{"class":54,"line":324},[52,1418,1419],{"class":58},"        runOnUiThread",[52,1421,503],{"class":62},[52,1423,1424,1427,1429,1431,1433,1435],{"class":54,"line":334},[52,1425,1426],{"class":194},"            when",[52,1428,1392],{"class":62},[52,1430,1395],{"class":58},[52,1432,210],{"class":62},[52,1434,1026],{"class":213},[52,1436,1437],{"class":62},")) {\n",[52,1439,1440,1443,1446,1448,1451],{"class":54,"line":341},[52,1441,1442],{"class":213},"                \"ready\"",[52,1444,1445],{"class":194}," ->",[52,1447,1372],{"class":62},[52,1449,1450],{"class":627},"\u002F* halaman chat siap *\u002F",[52,1452,1453],{"class":62}," }\n",[52,1455,1456,1459,1461,1464,1467,1470,1472,1474,1477,1480,1482,1485,1488,1491],{"class":54,"line":494},[52,1457,1458],{"class":213},"                \"unread\"",[52,1460,1445],{"class":194},[52,1462,1463],{"class":58}," updateBadge",[52,1465,1466],{"class":62},"(msg.",[52,1468,1469],{"class":58},"optJSONObject",[52,1471,210],{"class":62},[52,1473,1053],{"class":213},[52,1475,1476],{"class":62},")?.",[52,1478,1479],{"class":58},"optInt",[52,1481,210],{"class":62},[52,1483,1484],{"class":213},"\"count\"",[52,1486,1487],{"class":62},") ?: ",[52,1489,1490],{"class":217},"0",[52,1492,252],{"class":62},[52,1494,1495,1498,1500,1502,1504],{"class":54,"line":506},[52,1496,1497],{"class":213},"                \"close\"",[52,1499,1445],{"class":194},[52,1501,659],{"class":58},[52,1503,654],{"class":62},[52,1505,1506],{"class":627},"\u002F\u002F user menekan tombol tutup di header chat\n",[52,1508,1509,1512,1514,1517,1519,1521,1523,1525,1527,1529,1531],{"class":54,"line":517},[52,1510,1511],{"class":213},"                \"session\"",[52,1513,1445],{"class":194},[52,1515,1516],{"class":62}," msg.",[52,1518,1469],{"class":58},[52,1520,210],{"class":62},[52,1522,1053],{"class":213},[52,1524,1476],{"class":62},[52,1526,1395],{"class":58},[52,1528,210],{"class":62},[52,1530,829],{"class":213},[52,1532,252],{"class":62},[52,1534,1535,1538,1541,1544,1547],{"class":54,"line":527},[52,1536,1537],{"class":62},"                    ?.",[52,1539,1540],{"class":58},"takeIf",[52,1542,1543],{"class":62}," { it.",[52,1545,1546],{"class":58},"isNotEmpty",[52,1548,1549],{"class":62},"() }\n",[52,1551,1552,1554,1556,1558,1561],{"class":54,"line":533},[52,1553,1537],{"class":62},[52,1555,819],{"class":58},[52,1557,1372],{"class":62},[52,1559,1560],{"class":58},"saveChatTokenToServer",[52,1562,1563],{"class":62},"(it) }\n",[52,1565,1566],{"class":54,"line":538},[52,1567,1568],{"class":62},"            }\n",[52,1570,1571],{"class":54,"line":560},[52,1572,530],{"class":62},[52,1574,1575],{"class":54,"line":573},[52,1576,616],{"class":62},[52,1578,1579],{"class":54,"line":590},[52,1580,667],{"class":62},[65,1582,1583,1596],{},[68,1584,1585],{},[71,1586,1587,1591,1593],{},[74,1588,1589],{},[14,1590,1234],{},[74,1592,1237],{},[74,1594,1595],{},"Kapan dikirim",[84,1597,1598,1610,1628,1643],{},[71,1599,1600,1605,1607],{},[89,1601,1602],{},[14,1603,1604],{},"ready",[89,1606,1132],{},[89,1608,1609],{},"Halaman chat sudah dimuat.",[71,1611,1612,1617,1623],{},[89,1613,1614],{},[14,1615,1616],{},"unread",[89,1618,1619,1622],{},[14,1620,1621],{},"{ count }"," (0–99)",[89,1624,1625,1626,367],{},"Jumlah belum dibaca berubah. Bertambah hanya saat chat berstatus ",[14,1627,1275],{},[71,1629,1630,1634,1636],{},[89,1631,1632],{},[14,1633,1275],{},[89,1635,1132],{},[89,1637,1638,1639,1642],{},"User menekan tombol tutup di header, atau ",[14,1640,1641],{},"Escape"," di keyboard fisik. Aplikasi yang memutuskan apa yang ditutup.",[71,1644,1645,1649,1654],{},[89,1646,1647],{},[14,1648,158],{},[89,1650,1651],{},[14,1652,1653],{},"{ token }",[89,1655,1656],{},"Setiap kali sesi chat dibuka atau dibuat. Hanya dikirim di mode aplikasi.",[10,1658,1659,1660,1662,1663,367],{},"Selain ",[14,1661,158],{},", event tidak pernah membawa data user atau isi pesan. Tanpa bridge, chat tetap berjalan, tetapi tombol tutup di header tidak berfungsi. Daftarkan bridge atau pakai ",[14,1664,106],{},[19,1666,1668],{"id":1667},"token-sesi","Token sesi",[10,1670,1671,1672,1674,1675,1678],{},"Token dari event ",[14,1673,158],{}," mengikat percakapan ke user. Simpan di server Anda untuk user yang login, lalu kirim lagi lewat ",[14,1676,1677],{},"identify.token",". Dengan begitu riwayat chat user tetap muncul setelah instal ulang atau di HP lain.",[1680,1681,1682,1688,1691],"ol",{},[1183,1683,1684,1685,1687],{},"Terima event ",[14,1686,158],{},", kirim token ke server Anda bersama ID user yang login.",[1183,1689,1690],{},"Saat user membuka chat, ambil token user dari server Anda.",[1183,1692,1693,1694,1696,1697,367],{},"Kirim token di field ",[14,1695,1164],{}," pada ",[14,1698,136],{},[10,1700,1701],{},"Tanpa token, user yang sama di HP lain atau setelah instal ulang tercatat sebagai pengunjung baru.",[358,1703,1706],{"title":1704,"type":1705},"Perlakukan token seperti password","danger",[10,1707,1708],{},"Siapa pun yang memegang token bisa membaca dan mengirim pesan di percakapan user tersebut. Simpan hanya di server Anda, berikan hanya ke user yang login sebagai pemiliknya, dan jangan pernah menulisnya ke log.",[19,1710,1712],{"id":1711},"kirim-gambar-dan-pdf","Kirim gambar dan PDF",[10,1714,1715,1716,1719],{},"User bisa mengirim JPG, PNG, WEBP, GIF, dan PDF hingga 5 MB. WebView butuh ",[14,1717,1718],{},"WebChromeClient"," yang membuka pemilih file:",[43,1721,1723],{"className":185,"code":1722,"language":187,"meta":48,"style":48},"class ChatChromeClient(private val activity: ComponentActivity) : WebChromeClient() {\n\n    private var callback: ValueCallback\u003CArray\u003CUri>>? = null\n\n    private val picker = activity.registerForActivityResult(\n        ActivityResultContracts.StartActivityForResult()\n    ) { result ->\n        callback?.onReceiveValue(FileChooserParams.parseResult(result.resultCode, result.data))\n        callback = null\n    }\n\n    override fun onShowFileChooser(\n        view: WebView, filePathCallback: ValueCallback\u003CArray\u003CUri>>, params: FileChooserParams\n    ): Boolean {\n        callback?.onReceiveValue(null)\n        callback = filePathCallback\n        picker.launch(params.createIntent())\n        return true\n    }\n}\n",[14,1724,1725,1751,1755,1786,1790,1810,1820,1828,1851,1860,1864,1868,1879,1905,1914,1926,1935,1951,1957,1961],{"__ignoreMap":48},[52,1726,1727,1729,1731,1733,1735,1738,1741,1744,1747,1749],{"class":54,"line":55},[52,1728,392],{"class":194},[52,1730,581],{"class":58},[52,1732,210],{"class":62},[52,1734,688],{"class":194},[52,1736,1737],{"class":194}," val",[52,1739,1740],{"class":62}," activity: ",[52,1742,1743],{"class":58},"ComponentActivity",[52,1745,1746],{"class":62},") : ",[52,1748,1718],{"class":58},[52,1750,404],{"class":62},[52,1752,1753],{"class":54,"line":233},[52,1754,338],{"emptyLinePlaceholder":337},[52,1756,1757,1759,1761,1764,1767,1770,1773,1775,1778,1781,1783],{"class":54,"line":255},[52,1758,413],{"class":194},[52,1760,419],{"class":194},[52,1762,1763],{"class":62}," callback: ",[52,1765,1766],{"class":58},"ValueCallback",[52,1768,1769],{"class":62},"\u003C",[52,1771,1772],{"class":58},"Array",[52,1774,1769],{"class":62},[52,1776,1777],{"class":58},"Uri",[52,1779,1780],{"class":62},">>? ",[52,1782,201],{"class":194},[52,1784,1785],{"class":217}," null\n",[52,1787,1788],{"class":54,"line":274},[52,1789,338],{"emptyLinePlaceholder":337},[52,1791,1792,1794,1796,1799,1801,1804,1807],{"class":54,"line":289},[52,1793,413],{"class":194},[52,1795,1737],{"class":194},[52,1797,1798],{"class":62}," picker ",[52,1800,201],{"class":194},[52,1802,1803],{"class":62}," activity.",[52,1805,1806],{"class":58},"registerForActivityResult",[52,1808,1809],{"class":62},"(\n",[52,1811,1812,1815,1818],{"class":54,"line":304},[52,1813,1814],{"class":62},"        ActivityResultContracts.",[52,1816,1817],{"class":58},"StartActivityForResult",[52,1819,230],{"class":62},[52,1821,1822,1825],{"class":54,"line":324},[52,1823,1824],{"class":62},"    ) { result ",[52,1826,1827],{"class":194},"->\n",[52,1829,1830,1833,1836,1839,1842,1845,1848],{"class":54,"line":334},[52,1831,1832],{"class":62},"        callback?.",[52,1834,1835],{"class":58},"onReceiveValue",[52,1837,1838],{"class":62},"(FileChooserParams.",[52,1840,1841],{"class":58},"parseResult",[52,1843,1844],{"class":62},"(result.resultCode, result.",[52,1846,1847],{"class":194},"data",[52,1849,1850],{"class":62},"))\n",[52,1852,1853,1856,1858],{"class":54,"line":341},[52,1854,1855],{"class":62},"        callback ",[52,1857,201],{"class":194},[52,1859,1785],{"class":217},[52,1861,1862],{"class":54,"line":494},[52,1863,616],{"class":62},[52,1865,1866],{"class":54,"line":506},[52,1867,338],{"emptyLinePlaceholder":337},[52,1869,1870,1872,1874,1877],{"class":54,"line":517},[52,1871,434],{"class":194},[52,1873,437],{"class":194},[52,1875,1876],{"class":58}," onShowFileChooser",[52,1878,1809],{"class":62},[52,1880,1881,1884,1886,1889,1891,1893,1895,1897,1899,1902],{"class":54,"line":527},[52,1882,1883],{"class":62},"        view: ",[52,1885,16],{"class":58},[52,1887,1888],{"class":62},", filePathCallback: ",[52,1890,1766],{"class":58},[52,1892,1769],{"class":62},[52,1894,1772],{"class":58},[52,1896,1769],{"class":62},[52,1898,1777],{"class":58},[52,1900,1901],{"class":62},">>, params: ",[52,1903,1904],{"class":58},"FileChooserParams\n",[52,1906,1907,1910,1912],{"class":54,"line":533},[52,1908,1909],{"class":62},"    ): ",[52,1911,888],{"class":58},[52,1913,503],{"class":62},[52,1915,1916,1918,1920,1922,1924],{"class":54,"line":538},[52,1917,1832],{"class":62},[52,1919,1835],{"class":58},[52,1921,210],{"class":62},[52,1923,1080],{"class":217},[52,1925,252],{"class":62},[52,1927,1928,1930,1932],{"class":54,"line":560},[52,1929,1855],{"class":62},[52,1931,201],{"class":194},[52,1933,1934],{"class":62}," filePathCallback\n",[52,1936,1937,1940,1943,1946,1949],{"class":54,"line":573},[52,1938,1939],{"class":62},"        picker.",[52,1941,1942],{"class":58},"launch",[52,1944,1945],{"class":62},"(params.",[52,1947,1948],{"class":58},"createIntent",[52,1950,356],{"class":62},[52,1952,1953,1955],{"class":54,"line":590},[52,1954,942],{"class":194},[52,1956,514],{"class":217},[52,1958,1959],{"class":54,"line":595},[52,1960,616],{"class":62},[52,1962,1963],{"class":54,"line":613},[52,1964,667],{"class":62},[10,1966,1967,1968,1971,1972,1974,1975,1978,1979,367],{},"Buat ",[14,1969,1970],{},"ChatChromeClient"," di ",[14,1973,459],{},", sebelum Activity ",[14,1976,1977],{},"STARTED",", karena memakai ",[14,1980,1806],{},[19,1982,1984],{"id":1983},"logout-dan-ganti-akun","Logout dan ganti akun",[10,1986,1987],{},"Sesi chat disimpan di penyimpanan WebView dan berlaku untuk seluruh aplikasi. Jika user A logout lalu user B login di HP yang sama tanpa membersihkan penyimpanan, B melihat percakapan A. Saat logout, panggil:",[43,1989,1991],{"className":185,"code":1990,"language":187,"meta":48,"style":48},"WebStorage.getInstance().deleteAllData()\nCookieManager.getInstance().removeAllCookies(null)\n",[14,1992,1993,2008],{"__ignoreMap":48},[52,1994,1995,1998,2001,2003,2006],{"class":54,"line":55},[52,1996,1997],{"class":62},"WebStorage.",[52,1999,2000],{"class":58},"getInstance",[52,2002,1005],{"class":62},[52,2004,2005],{"class":58},"deleteAllData",[52,2007,230],{"class":62},[52,2009,2010,2013,2015,2017,2020,2022,2024],{"class":54,"line":233},[52,2011,2012],{"class":62},"CookieManager.",[52,2014,2000],{"class":58},[52,2016,1005],{"class":62},[52,2018,2019],{"class":58},"removeAllCookies",[52,2021,210],{"class":62},[52,2023,1080],{"class":217},[52,2025,252],{"class":62},[10,2027,2028,2029,2032],{},"Jika WebView juga dipakai untuk halaman lain yang datanya tidak boleh ikut terhapus, jalankan chat di proses terpisah dengan ",[14,2030,2031],{},"WebView.setDataDirectorySuffix(\"csku-chat\")"," (Android 9+), lalu hapus direktori data itu saat logout.",[19,2034,2036],{"id":2035},"layar-penuh-edge-to-edge","Layar penuh (edge-to-edge)",[10,2038,2039],{},"Halaman chat otomatis memberi jarak untuk status bar, navigation bar, dan notch. Beberapa versi WebView lama tidak meneruskan jarak ini. Jika header tertutup status bar atau kotak ketik tertutup navigation bar (Android 15 \u002F targetSdk 35 memaksa edge-to-edge), beri padding di native:",[43,2041,2043],{"className":185,"code":2042,"language":187,"meta":48,"style":48},"ViewCompat.setOnApplyWindowInsetsListener(webView) { v, insets ->\n    val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime())\n    v.setPadding(bars.left, bars.top, bars.right, bars.bottom)\n    WindowInsetsCompat.CONSUMED\n}\n",[14,2044,2045,2058,2087,2098,2103],{"__ignoreMap":48},[52,2046,2047,2050,2053,2056],{"class":54,"line":55},[52,2048,2049],{"class":62},"ViewCompat.",[52,2051,2052],{"class":58},"setOnApplyWindowInsetsListener",[52,2054,2055],{"class":62},"(webView) { v, insets ",[52,2057,1827],{"class":194},[52,2059,2060,2062,2065,2067,2070,2073,2076,2079,2082,2085],{"class":54,"line":233},[52,2061,995],{"class":194},[52,2063,2064],{"class":62}," bars ",[52,2066,201],{"class":194},[52,2068,2069],{"class":62}," insets.",[52,2071,2072],{"class":58},"getInsets",[52,2074,2075],{"class":62},"(WindowInsetsCompat.Type.",[52,2077,2078],{"class":58},"systemBars",[52,2080,2081],{"class":62},"() or WindowInsetsCompat.Type.",[52,2083,2084],{"class":58},"ime",[52,2086,356],{"class":62},[52,2088,2089,2092,2095],{"class":54,"line":255},[52,2090,2091],{"class":62},"    v.",[52,2093,2094],{"class":58},"setPadding",[52,2096,2097],{"class":62},"(bars.left, bars.top, bars.right, bars.bottom)\n",[52,2099,2100],{"class":54,"line":274},[52,2101,2102],{"class":62},"    WindowInsetsCompat.CONSUMED\n",[52,2104,2105],{"class":54,"line":289},[52,2106,667],{"class":62},[10,2108,2109,2110,2113],{},"Padding ini tidak membuat jarak dobel. Pakai ",[14,2111,2112],{},"android:windowSoftInputMode=\"adjustResize\""," pada Activity supaya kotak ketik tetap terlihat saat keyboard muncul.",[19,2115,2117],{"id":2116},"keamanan-dan-batasan","Keamanan dan batasan",[358,2119,2122],{"title":2120,"type":2121},"Identitas tidak diverifikasi","warning",[10,2123,2124],{},"Nama dan nomor dari aplikasi tidak diverifikasi oleh CSKU. Siapa pun yang membuka URL chat bisa mengirim nomor lain. Gunakan sebagai info bantu untuk tim CS, bukan bukti identitas. Jangan membuka data sensitif (saldo, pesanan, data akun) hanya berdasarkan nomor yang tampil di chat.",[1180,2126,2127,2133,2136],{},[1183,2128,2129,2130,367],{},"Pengunjung baru melewati pemeriksaan anti-spam otomatis saat memulai chat. WebView harus bisa memuat ",[14,2131,2132],{},"challenges.cloudflare.com",[1183,2134,2135],{},"Satu pesan maksimal 2000 karakter.",[1183,2137,2138],{},"Tampilan chat berbahasa Indonesia dan bertema terang.",[19,2140,2142],{"id":2141},"checklist-uji","Checklist uji",[1680,2144,2145,2151,2158,2161,2174,2180,2183,2186,2189,2195],{},[1183,2146,2147,2148,2150],{},"Login, buka chat: form pra-chat tidak muncul. Kirim pesan, cek nama dan nomor di menu ",[27,2149,1188],{}," dashboard.",[1183,2152,2153,2154,2157],{},"Nomor salah format (misalnya ",[14,2155,2156],{},"12345","): form pra-chat muncul.",[1183,2159,2160],{},"Tutup chat lalu buka lagi: riwayat pesan masih ada.",[1183,2162,2163,2164,2166,2167,2169,2170,2173],{},"Kirim ",[14,2165,1275],{},", lalu balas dari dashboard: event ",[14,2168,1616],{}," masuk dengan ",[14,2171,2172],{},"count"," bertambah.",[1183,2175,2176,2177,2179],{},"Tombol tutup di header menutup Activity, atau ",[14,2178,106],{}," dan toolbar aplikasi tampil.",[1183,2181,2182],{},"Kirim gambar dan PDF.",[1183,2184,2185],{},"Ketuk link di pesan: terbuka di browser.",[1183,2187,2188],{},"Logout lalu login akun lain: chat mulai kosong.",[1183,2190,2191,2192,2194],{},"Event ",[14,2193,158],{}," masuk dan token tersimpan di server. Login akun yang sama di HP lain: riwayat chat muncul.",[1183,2196,2197],{},"HP dengan gesture navigation dan notch: header dan kotak ketik tidak tertutup.",[19,2199,2201],{"id":2200},"troubleshooting","Troubleshooting",[65,2203,2204,2214],{},[68,2205,2206],{},[71,2207,2208,2211],{},[74,2209,2210],{},"Gejala",[74,2212,2213],{},"Solusi",[84,2215,2216,2232,2240,2253,2264,2275],{},[71,2217,2218,2221],{},[89,2219,2220],{},"Form pra-chat tetap muncul",[89,2222,2223,2224,2227,2228,1971,2230,367],{},"Pastikan URL memakai ",[14,2225,2226],{},"?embed=app",". Cek nama minimal 2 karakter dan nomor 8–15 digit. Kirim ",[14,2229,136],{},[14,2231,677],{},[71,2233,2234,2237],{},[89,2235,2236],{},"Nama lama tampil setelah ganti akun",[89,2238,2239],{},"Hapus penyimpanan WebView saat logout.",[71,2241,2242,2245],{},[89,2243,2244],{},"Tombol tutup tidak berfungsi",[89,2246,2247,2248,2250,2251,367],{},"Daftarkan ",[14,2249,381],{}," atau pakai ",[14,2252,106],{},[71,2254,2255,2258],{},[89,2256,2257],{},"Tombol lampiran tidak membuka galeri",[89,2259,2260,2261,367],{},"Implementasikan ",[14,2262,2263],{},"onShowFileChooser",[71,2265,2266,2269],{},[89,2267,2268],{},"Muncul \"Verifikasi keamanan gagal\"",[89,2270,2271,2272,2274],{},"Izinkan ",[14,2273,2132],{}," di jaringan atau network security config.",[71,2276,2277,2280],{},[89,2278,2279],{},"Halaman kosong",[89,2281,2282],{},"Aktifkan JavaScript dan DOM storage. Cek ID channel di dashboard.",[2284,2285,2286],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":48,"searchDepth":255,"depth":255,"links":2288},[2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300],{"id":21,"depth":233,"text":22},{"id":370,"depth":233,"text":371},{"id":670,"depth":233,"text":671},{"id":1212,"depth":233,"text":1213},{"id":1310,"depth":233,"text":1311},{"id":1667,"depth":233,"text":1668},{"id":1711,"depth":233,"text":1712},{"id":1983,"depth":233,"text":1984},{"id":2035,"depth":233,"text":2036},{"id":2116,"depth":233,"text":2117},{"id":2141,"depth":233,"text":2142},{"id":2200,"depth":233,"text":2201},"Tampilkan Webchat di aplikasi Android lewat WebView, dengan data user yang login langsung terisi dan riwayat chat yang ikut pindah perangkat.",null,"md",{},"\u002Fwebchat\u002Fandroid",{"title":5,"description":2301},"webchat\u002Fandroid","qZ45gnr3m17u6c39RgYOlMeG9XFLbVTluTjM4lGANoY",1791957694418]