diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 62bdc4a..3c0f41e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + + \ No newline at end of file diff --git a/assets/html/findwords/findwords.html b/assets/html/findwords/findwords.html new file mode 100644 index 0000000..32a99b9 --- /dev/null +++ b/assets/html/findwords/findwords.html @@ -0,0 +1,180 @@ + + + + + + Game Nusantara + + + +
+

Game Nusantara

+
+ +

Kata yang harus ditemukan:

+
    +

    +
    + + + + \ No newline at end of file diff --git a/assets/html/findwords/hati.png b/assets/html/findwords/hati.png new file mode 100644 index 0000000..aea12cb Binary files /dev/null and b/assets/html/findwords/hati.png differ diff --git a/assets/html/findwords/latar.png b/assets/html/findwords/latar.png new file mode 100644 index 0000000..df426e4 Binary files /dev/null and b/assets/html/findwords/latar.png differ diff --git a/assets/html/findwords/parkir - Copy.png b/assets/html/findwords/parkir - Copy.png new file mode 100644 index 0000000..9e010eb Binary files /dev/null and b/assets/html/findwords/parkir - Copy.png differ diff --git a/assets/html/findwords/parkir.png b/assets/html/findwords/parkir.png new file mode 100644 index 0000000..5ab03e1 Binary files /dev/null and b/assets/html/findwords/parkir.png differ diff --git a/assets/html/findwords/sekolah.png b/assets/html/findwords/sekolah.png new file mode 100644 index 0000000..286d89d Binary files /dev/null and b/assets/html/findwords/sekolah.png differ diff --git a/assets/html/findwords/test.html b/assets/html/findwords/test.html new file mode 100644 index 0000000..b09d4a2 --- /dev/null +++ b/assets/html/findwords/test.html @@ -0,0 +1,16 @@ + + + + + Test + + + +

    Hello WebView

    + + diff --git a/assets/html/freekake.png b/assets/html/freekake.png new file mode 100644 index 0000000..1f7cd62 Binary files /dev/null and b/assets/html/freekake.png differ diff --git a/assets/html/memory/ayambetutu.png b/assets/html/memory/ayambetutu.png new file mode 100644 index 0000000..1dc20f5 Binary files /dev/null and b/assets/html/memory/ayambetutu.png differ diff --git a/assets/html/memory/ayamtaliwang.png b/assets/html/memory/ayamtaliwang.png new file mode 100644 index 0000000..e63326a Binary files /dev/null and b/assets/html/memory/ayamtaliwang.png differ diff --git a/assets/html/memory/bali.png b/assets/html/memory/bali.png new file mode 100644 index 0000000..622f40b Binary files /dev/null and b/assets/html/memory/bali.png differ diff --git a/assets/html/memory/bikaambon.png b/assets/html/memory/bikaambon.png new file mode 100644 index 0000000..f52079b Binary files /dev/null and b/assets/html/memory/bikaambon.png differ diff --git a/assets/html/memory/freekake.png b/assets/html/memory/freekake.png new file mode 100644 index 0000000..1f7cd62 Binary files /dev/null and b/assets/html/memory/freekake.png differ diff --git a/assets/html/memory/gudeg.png b/assets/html/memory/gudeg.png new file mode 100644 index 0000000..5966bc0 Binary files /dev/null and b/assets/html/memory/gudeg.png differ diff --git a/assets/html/memory/kalsel.png b/assets/html/memory/kalsel.png new file mode 100644 index 0000000..122059f Binary files /dev/null and b/assets/html/memory/kalsel.png differ diff --git a/assets/html/memory/memory.html b/assets/html/memory/memory.html new file mode 100644 index 0000000..6c12d93 --- /dev/null +++ b/assets/html/memory/memory.html @@ -0,0 +1,177 @@ + + + + + + Game Nusantara + + + + +
    +

    Game Nusantara

    +
    +
    + + + + diff --git a/assets/html/memory/ntb.png b/assets/html/memory/ntb.png new file mode 100644 index 0000000..e6d5283 Binary files /dev/null and b/assets/html/memory/ntb.png differ diff --git a/assets/html/memory/pempek.png b/assets/html/memory/pempek.png new file mode 100644 index 0000000..785a822 Binary files /dev/null and b/assets/html/memory/pempek.png differ diff --git a/assets/html/memory/rendang.png b/assets/html/memory/rendang.png new file mode 100644 index 0000000..9e9d27f Binary files /dev/null and b/assets/html/memory/rendang.png differ diff --git a/assets/html/memory/sopkonro.png b/assets/html/memory/sopkonro.png new file mode 100644 index 0000000..c1661c2 Binary files /dev/null and b/assets/html/memory/sopkonro.png differ diff --git a/assets/html/memory/sotobanjar.png b/assets/html/memory/sotobanjar.png new file mode 100644 index 0000000..579d488 Binary files /dev/null and b/assets/html/memory/sotobanjar.png differ diff --git a/assets/html/memory/sulsel.png b/assets/html/memory/sulsel.png new file mode 100644 index 0000000..6b1c0c1 Binary files /dev/null and b/assets/html/memory/sulsel.png differ diff --git a/assets/html/memory/sulut.png b/assets/html/memory/sulut.png new file mode 100644 index 0000000..abcf2be Binary files /dev/null and b/assets/html/memory/sulut.png differ diff --git a/assets/html/memory/sumbar.png b/assets/html/memory/sumbar.png new file mode 100644 index 0000000..a6a3dd9 Binary files /dev/null and b/assets/html/memory/sumbar.png differ diff --git a/assets/html/memory/sumsel.png b/assets/html/memory/sumsel.png new file mode 100644 index 0000000..e528cbe Binary files /dev/null and b/assets/html/memory/sumsel.png differ diff --git a/assets/html/memory/sumut.png b/assets/html/memory/sumut.png new file mode 100644 index 0000000..5ad7e00 Binary files /dev/null and b/assets/html/memory/sumut.png differ diff --git a/assets/html/memory/tinutuan.png b/assets/html/memory/tinutuan.png new file mode 100644 index 0000000..885152d Binary files /dev/null and b/assets/html/memory/tinutuan.png differ diff --git a/assets/html/memory/yogyakarta.png b/assets/html/memory/yogyakarta.png new file mode 100644 index 0000000..d5edf78 Binary files /dev/null and b/assets/html/memory/yogyakarta.png differ diff --git a/lib/screen/collection/collection_caracter_screen.dart b/lib/screen/collection/collection_caracter_screen.dart index 1386a8a..3d30105 100644 --- a/lib/screen/collection/collection_caracter_screen.dart +++ b/lib/screen/collection/collection_caracter_screen.dart @@ -55,7 +55,13 @@ class _CollectionCaraterScreenState extends State { charSex: "Laki-laki", charOrigin: "Jawa Barat", content: - """Cepot adalah sosok yang begitu menarik—aneh, ceria, dan penuh kejutan! Ia muncul seperti tokoh dari dongeng lama yang lupa pulang ke rumah, dengan wajah merah seperti apel matang, hidung besar yang tampak siap mencium rahasia, dan mata bulat yang selalu bersinar penuh rasa ingin tahu. Ia suka tertawa keras, suka bermain-main dengan kata-kata, dan sangat pandai membuat siapa pun merasa nyaman di dekatnya. \nMeski kadang terlihat konyol, Cepot sebenarnya sangat cerdik—ia tahu kapan harus berbicara, kapan harus diam, dan yang paling penting, ia tahu bagaimana menghibur orang-orang yang sedang sedih. \nAnak-anak menyukainya, orang tua menghormatinya, dan tak jarang hewan-hewan kecil pun tampak betah duduk di dekatnya saat ia bercerita. + """Cepot adalah sosok yang begitu menarik—aneh, ceria, dan penuh kejutan! + Ia muncul seperti tokoh dari dongeng lama yang lupa pulang ke rumah, dengan wajah merah seperti apel matang, + hidung besar yang tampak siap mencium rahasia, dan mata bulat yang selalu bersinar penuh rasa ingin tahu. Ia suka tertawa keras, + suka bermain-main dengan kata-kata, dan sangat pandai membuat siapa pun merasa nyaman di dekatnya. \nMeski kadang terlihat konyol, + Cepot sebenarnya sangat cerdik—ia tahu kapan harus berbicara, kapan harus diam, dan yang paling penting, ia tahu bagaimana menghibur + orang-orang yang sedang sedih. \nAnak-anak menyukainya, orang tua menghormatinya, dan tak jarang hewan-hewan kecil pun tampak betah + duduk di dekatnya saat ia bercerita. """, ), ), @@ -119,8 +125,20 @@ class _CollectionCaraterScreenState extends State { charName: "Cepot", charSex: "Laki-laki", charOrigin: "Jawa Barat", - content: - """Cepot adalah sosok yang begitu menarik—aneh, ceria, dan penuh kejutan! Ia muncul seperti tokoh dari dongeng lama yang lupa pulang ke rumah, dengan wajah merah seperti apel matang, hidung besar yang tampak siap mencium rahasia, dan mata bulat yang selalu bersinar penuh rasa ingin tahu. Ia suka tertawa keras, suka bermain-main dengan kata-kata, dan sangat pandai membuat siapa pun merasa nyaman di dekatnya. \nMeski kadang terlihat konyol, Cepot sebenarnya sangat cerdik—ia tahu kapan harus berbicara, kapan harus diam, dan yang paling penting, ia tahu bagaimana menghibur orang-orang yang sedang sedih. \nAnak-anak menyukainya, orang tua menghormatinya, dan tak jarang hewan-hewan kecil pun tampak betah duduk di dekatnya saat ia bercerita. + content: """ + Cepot adalah sosok yang begitu menarik—aneh, + ceria, dan penuh kejutan! Ia muncul seperti + tokoh dari dongeng lama yang lupa pulang ke rumah, + dengan wajah merah seperti apel matang, + hidung besar yang tampak siap + mencium rahasia, dan mata bulat + yang selalu bersinar penuh rasa ingin + tahu. Ia suka tertawa keras, suka bermain-main dengan kata-kata, dan sangat + pandai membuat siapa pun merasa nyaman di dekatnya. \nMeski kadang terlihat konyol, + Cepot sebenarnya sangat cerdik—ia tahu kapan harus berbicara, kapan harus diam, dan + yang paling penting, ia tahu bagaimana menghibur orang-orang yang sedang sedih. \nAnak-anak + menyukainya, orang tua menghormatinya, dan tak jarang hewan-hewan kecil pun tampak betah duduk + di dekatnya saat ia bercerita. """, ), ), diff --git a/lib/screen/pustaka/_list_detail_screen.dart b/lib/screen/pustaka/_list_detail_screen.dart new file mode 100644 index 0000000..798a8e9 --- /dev/null +++ b/lib/screen/pustaka/_list_detail_screen.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class _ListDetailScreen extends StatefulWidget { + final String title; + final String? filepath; + + const _ListDetailScreen({super.key, required this.title, this.filepath}); + + @override + State<_ListDetailScreen> createState() => _ListDetailScreenState(); +} + +class _ListDetailScreenState extends State<_ListDetailScreen> { + List checklist = []; + late WebViewController _controller; + late String? fPath = widget.filepath; + + @override + void initState() { + super.initState(); + _controller = + WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted); + checklist = List.generate(paragraphs.length, (index) => false); + if (fPath != null && fPath!.isNotEmpty) { + _loadContent(fPath!); // <- ini penting + } + } + + final List paragraphs = [ + "Paragraf pertama tentang ${"widget.title"}.", + "Paragraf kedua dengan informasi tambahan.", + "Paragraf ketiga yang menjelaskan detail lebih lanjut.", + "Paragraf keempat yang melengkapi pembahasan.", + ]; + + void _loadContent(String path) async { + try { + if (path.startsWith('http')) { + _controller.loadRequest(Uri.parse(path)); + } else { + String fileHtml = await rootBundle.loadString(path); + _controller.loadHtmlString(fileHtml); + } + } catch (e) { + debugPrint("Error loading HTML: $e"); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar(title: Text(widget.title)), + body: + (fPath != null && fPath!.isNotEmpty) + ? WebViewWidget(controller: _controller) + : Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/default.png', + width: 100, + height: 100, + fit: BoxFit.cover, + ), + const SizedBox(width: 16), + Expanded( + child: Text( + "Ini adalah detail dari ${widget.title}.", + style: const TextStyle(fontSize: 18), + ), + ), + ], + ), + const SizedBox(height: 20), + Expanded( + child: ListView.builder( + itemCount: paragraphs.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(paragraphs[index]), + trailing: Checkbox( + value: checklist[index], + onChanged: (bool? value) { + setState(() { + checklist[index] = value!; + }); + }, + ), + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screen/pustaka/list_detail_screen.dart b/lib/screen/pustaka/list_detail_screen.dart index 664f91e..7451f1e 100644 --- a/lib/screen/pustaka/list_detail_screen.dart +++ b/lib/screen/pustaka/list_detail_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:webview_flutter/webview_flutter.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'dart:convert'; class ListDetailScreen extends StatefulWidget { final String title; @@ -13,89 +14,118 @@ class ListDetailScreen extends StatefulWidget { } class _ListDetailScreenState extends State { - List checklist = []; - late WebViewController _controller; - late String? fPath = widget.filepath; - - @override - void initState() { - super.initState(); - checklist = List.generate(paragraphs.length, (index) => false); - } - - final List paragraphs = [ - "Paragraf pertama tentang ${"widget.title"}.", - "Paragraf kedua dengan informasi tambahan.", - "Paragraf ketiga yang menjelaskan detail lebih lanjut.", - "Paragraf keempat yang melengkapi pembahasan.", - ]; - - void _loadContent(String path) async { - if (path.startsWith('http')) { - // Load dari Internet - _controller.loadRequest(Uri.parse(path)); - } else { - // Load dari assets lokal - String fileHtml = await rootBundle.loadString(path); - _controller.loadHtmlString(fileHtml); - } - } + late InAppWebViewController _webViewController; @override Widget build(BuildContext context) { + String _getMimeType(String path) { + if (path.endsWith('.png')) return 'image/png'; + if (path.endsWith('.jpg') || path.endsWith('.jpeg')) return 'image/jpeg'; + if (path.endsWith('.svg')) return 'image/svg+xml'; + if (path.endsWith('.html')) return 'text/html'; + if (path.endsWith('.css')) return 'text/css'; + if (path.endsWith('.js')) return 'application/javascript'; + return 'application/octet-stream'; + } + return Scaffold( - backgroundColor: Colors.white, appBar: AppBar(title: Text(widget.title)), body: - (fPath != null && fPath!.isNotEmpty) - ? WebViewWidget(controller: _controller) - : Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - // Gambar di kiri atas dengan teks di kanan - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/default.png', // Ganti dengan gambar yang sesuai - width: 100, - height: 100, - fit: BoxFit.cover, - ), - const SizedBox(width: 16), - Expanded( - child: Text( - "Ini adalah detail dari ${widget.title}.", - style: const TextStyle(fontSize: 18), - ), - ), - ], - ), - const SizedBox(height: 20), - - // Paragraf dengan checklist - Expanded( - child: ListView.builder( - itemCount: paragraphs.length, - itemBuilder: (context, index) { - return ListTile( - title: Text(paragraphs[index]), - trailing: Checkbox( - value: checklist[index], - onChanged: (bool? value) { - setState(() { - checklist[index] = value!; - }); - }, - ), - ); - }, - ), - ), - ], + widget.filepath != null + ? InAppWebView( + initialUrlRequest: URLRequest(url: WebUri("about:blank")), + initialOptions: InAppWebViewGroupOptions( + crossPlatform: InAppWebViewOptions( + javaScriptEnabled: true, + allowFileAccessFromFileURLs: true, + allowUniversalAccessFromFileURLs: true, + ), ), - ), + onWebViewCreated: (controller) async { + _webViewController = controller; + + final html = await rootBundle.loadString(widget.filepath!); + final base = widget.filepath!.substring( + 0, + widget.filepath!.lastIndexOf('/') + 1, + ); + await controller.loadData( + data: html, + baseUrl: WebUri( + "http://localhost/$base", + ), // agar path relatif seperti img1/* jalan + mimeType: 'text/html', + encoding: 'utf-8', + ); + }, + onLoadStop: (controller, url) async { + debugPrint("🚀 onLoadStop called. URL: $url"); + + var result = await controller.evaluateJavascript( + source: """ + (() => { + const board = document.getElementById('game-board'); + const hasRender = typeof renderGrid === 'function'; + return { hasRender, boardExists: board !== null }; + })(); + """, + ); + + debugPrint("📊 Evaluated JS result: $result"); + + final jsCheck = await controller.evaluateJavascript( + source: """ + typeof renderGrid === 'function' && + document.querySelector('#game-board') !== null + """, + ); + + debugPrint( + "Apakah renderGrid tersedia dan board muncul? => $jsCheck", + ); + + final imageLoaded = await controller.evaluateJavascript( + source: """ + Array.from(document.images).every(img => img.complete) + """, + ); + + debugPrint("Semua gambar berhasil dimuat? => $imageLoaded"); + }, + + // (Opsional) tangkap log dari JS + onConsoleMessage: (controller, consoleMessage) { + debugPrint("📢 JS Console: ${consoleMessage.message}"); + }, + shouldInterceptRequest: (controller, request) async { + final url = request.url; + if (url == null || url.host != 'localhost') return null; + + try { + // Strip "http://localhost/" from the path + final path = url.path.replaceFirst('/', ''); + + final asset = await rootBundle.load(path); + final mimeType = _getMimeType(path); + + return WebResourceResponse( + contentType: mimeType, + data: asset.buffer.asUint8List(), + statusCode: 200, + reasonPhrase: 'OK', + ); + } catch (e) { + print("⚠️ Asset not found: ${url.path} -> $e"); + return WebResourceResponse( + contentType: 'text/plain', + data: Uint8List.fromList(utf8.encode('404 Not Found')), + statusCode: 404, + reasonPhrase: 'Not Found', + ); + } + }, + ) + : const Center(child: Text("Tidak ada file HTML")), ); } } diff --git a/lib/screen/pustaka/list_education.dart b/lib/screen/pustaka/list_education.dart index 641b89a..1e6e6bc 100644 --- a/lib/screen/pustaka/list_education.dart +++ b/lib/screen/pustaka/list_education.dart @@ -6,12 +6,14 @@ import 'package:flutter/services.dart'; import 'package:freekake/components/card_list.dart'; import 'package:freekake/components/collection_container%20copy.dart'; import 'package:freekake/helpers/color_helper.dart'; +import 'package:freekake/screen/pustaka/list_detail_screen.dart'; import 'package:list_detail_extension/list_detail_extension.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:flutter/foundation.dart' show kIsWeb; class ListEducation extends StatefulWidget { - const ListEducation({super.key}); + final String? selectedCategory; + const ListEducation({super.key, this.selectedCategory}); @override State createState() => _ListEducationState(); @@ -22,8 +24,7 @@ class _ListEducationState extends State { late final WebViewController _controller; late String urlOrAssetPath; bool _shouldShowWebView = false; - - // load extension + String? selectedCategory; final listDetailExtension = ListDetailExtension(); Future _initExtension() async { @@ -69,18 +70,55 @@ class _ListEducationState extends State { """, "file": "assets/html/index.html", }, + { + "title": "Memori Game", + "image": "assets/html/freekake.png", + "color": "#cef1da", + "category": "Gizi", + "type": "Materi", + "point": "100", + "coint": "20", + "body": + """Game untuk melatih daya ingat siswa, sehingga bisa diharapkan bisa + menemukan cara sendiri untuk mengingat sesuatu + """, + "file": "assets/html/memory/memory.html", + }, + { + "title": "Find Words", + "image": "assets/html/freekake.png", + "color": "#cef1da", + "category": "Kesehatan", + "type": "Materi", + "point": "100", + "coint": "20", + "body": """ + No Descripptions + """, + "file": "assets/html/findwords/findwords.html", + }, ]; List> filteredItems = []; @override void initState() { super.initState(); - filteredItems = List.from(_listContent); + + selectedCategory = widget.selectedCategory; + print(selectedCategory); + if (selectedCategory != null && selectedCategory!.isNotEmpty) { + filteredItems = + _listContent + .where((item) => item["category"] == selectedCategory) + .toList(); + } else { + filteredItems = List.from(_listContent); + } if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { _shouldShowWebView = true; _controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted); - urlOrAssetPath = "assets/makanan_bergizi/index.html"; + urlOrAssetPath = "assets/html/index.html"; _loadContent(urlOrAssetPath); _initExtension(); } @@ -92,18 +130,20 @@ class _ListEducationState extends State { // Load dari Internet _controller.loadRequest(Uri.parse(path)); } else { - // Load dari assets lokal - // String fileHtml = await rootBundle.loadString(path); - String fileHtml = await DefaultAssetBundle.of( - context, - ).loadString('assets/html/index.html'); - _controller.loadHtmlString(fileHtml); + try { + await rootBundle.load(path); + await _controller.loadFlutterAsset(path); + } catch (e) { + print("Gagal memuat file HTML: $path\nError: $e"); + } + _controller.loadFlutterAsset(path); } } } void filterSearch(String query) { setState(() { + selectedCategory = null; if (query.isEmpty) { filteredItems = List.from(_listContent); } else { @@ -117,6 +157,7 @@ class _ListEducationState extends State { void filterByCategory(String category) { setState(() { + selectedCategory = category; filteredItems = _listContent.where((item) { return item["category"].toLowerCase() == category.toLowerCase(); @@ -126,7 +167,6 @@ class _ListEducationState extends State { @override Widget build(BuildContext context) { - String searchQuery = ""; final List> collections = [ { "label": "Kesehatan", @@ -158,7 +198,8 @@ class _ListEducationState extends State { collections .where( (item) => item["label"].toLowerCase().contains( - searchQuery.toLowerCase(), + // searchQuery.toLowerCase(), + searchController.text.toLowerCase(), ), ) .toList(); @@ -176,7 +217,7 @@ class _ListEducationState extends State { body: Column( children: [ // Header Section - headerContainer(context, filteredCollections), + headerContainer(context, collections), // Collection Items dengan Filter SizedBox(height: 20), Expanded(child: contentContainer(context)), @@ -255,6 +296,7 @@ class _ListEducationState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: filteredCollections.map((item) { + final isSelected = selectedCategory == item["category"]; return CollectionContainer( label: item["label"]!, imageSvg: item["image"]!, @@ -262,9 +304,16 @@ class _ListEducationState extends State { iconh: 20, width: 70, height: 70, - textColor: Colors.black, + textColor: + isSelected + ? const Color.fromARGB(255, 230, 48, 160) + : Colors.black, lblSize: 10, - colorContiner: ColorHelper.hexToColor(item["color"]), + // colorContiner: ColorHelper.hexToColor(item["color"]), + colorContiner: + isSelected + ? const Color.fromARGB(255, 84, 3, 224) + : ColorHelper.hexToColor(item["color"]), onTapAc: () => { searchController.clear(), @@ -347,36 +396,41 @@ class _ListEducationState extends State { GridView _generateList() { return GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, // 2 Kolom + crossAxisCount: 1, crossAxisSpacing: 10, mainAxisSpacing: 10, childAspectRatio: 2.5, ), - itemCount: _listContent.length, + itemCount: filteredItems.length, itemBuilder: (context, index) { return GestureDetector( child: CardList( - title: _listContent[index]["title"] ?? "", - body: _listContent[index]["body"] ?? "", - gambar: _listContent[index]['image'], - point: _listContent[index]['coint'], - coint: _listContent[index]['point'], - tipe: _listContent[index]['tipe'], + title: filteredItems[index]["title"] ?? "", + body: filteredItems[index]["body"] ?? "", + gambar: filteredItems[index]['image'], + point: filteredItems[index]['point'], + coint: filteredItems[index]['coint'], + tipe: filteredItems[index]['type'], ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: - (context) => listDetailExtension.buildPage({ - 'title': filteredItems[index]['category'], - 'imagePath': filteredItems[index]['image'], - 'filepath': filteredItems[index]['file'], - 'paragraphs': - """ - """ - "

    ${_listContent[index]["title"]}

    ${_listContent[index]["body"]}", - }), + // (context) => listDetailExtension.buildPage({ + // 'title': filteredItems[index]['category'], + // 'imagePath': filteredItems[index]['image'], + // 'filepath': filteredItems[index]['file'], + // 'paragraphs': + // """ + // """ + // "

    ${filteredItems[index]["title"]}

    ${filteredItems[index]["body"]}", + // }), + (context) => ListDetailScreen( + title: filteredItems[index]['category'], + // 'imagePath': filteredItems[index]['image'], + filepath: filteredItems[index]['file'], + ), ), ); }, diff --git a/lib/screen/pustaka/pustaka_detail_screen.dart b/lib/screen/pustaka/pustaka_detail_screen.dart index 6229741..64d5509 100644 --- a/lib/screen/pustaka/pustaka_detail_screen.dart +++ b/lib/screen/pustaka/pustaka_detail_screen.dart @@ -74,106 +74,11 @@ class _ListDetailScreenState extends State { ), ), ), - - // Padding( - // padding: const EdgeInsets.all(20.0), - // child: Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Image.asset( - // widget.imagePath, - // width: 100, - // height: 100, - // fit: BoxFit.cover, - // ), - // const SizedBox(width: 16), - // Expanded( - // child: Center( - // child: Text( - // widget.title, - // style: const TextStyle( - // fontSize: 22, - // fontWeight: FontWeight.bold, - // color: Colors.black, - // ), - // ), - // ), - // ), - // ], - // ), - // ), const SizedBox(height: 0), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.only(left: 18.0, right: 18, bottom: 18), - child: - // ListView.builder( - // itemCount: widget.paragraphs.length, - // itemBuilder: (context, index) { - // return - // Padding( - // padding: const EdgeInsets.only(bottom: 16.0), - // child: Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Expanded( - // child: - // // Text( - // // widget.paragraphs[index] + - // // style: TextStyle(color: Colors.black), - // Html( - // // style: { - // // "body": Style( - // // color: const Color.fromRGBO(0, 0, 0, 1), - // // ), - // // }, - // data: - // widget.paragraphs + - // """ - // - // - // - // Enter a title, displayed at the top of the window. - // - // - // - //

    Enter the main heading, usually the same as the title.

    - //

    Be bold in stating your key points. Put them in a list:

    - //
      - //
    • The first item in your list
    • - //
    • The second item; italicize key words
    • - //
    - //

    Improve your image by including an image.

    - //

    A Great HTML Resource

    - //

    Add a link to your favorite Web site. - // Break up your page with a horizontal rule or two.

    - //
    - //

    Finally, link to another page in your own Web site.

    - // - //

    © Wiley Publishing, 2011

    - // - // - // """, - // ), - // ), - // // ), - // // Checkbox( - // // value: _readStatus[index], - // // onChanged: (bool? value) { - // // _toggleReadStatus(index); - // // }, - // // ), - // ], - // ), - // ); - // }, - // ), - htmlBody(), + child: htmlBody(), ), ), ], diff --git a/lib/screen/pustaka_screen.dart b/lib/screen/pustaka_screen.dart index b33d1b5..507f9be 100644 --- a/lib/screen/pustaka_screen.dart +++ b/lib/screen/pustaka_screen.dart @@ -44,6 +44,32 @@ class _PustakaScreenState extends State { }, ]; + final List> _genres = [ + { + "label": "Game", + "type": "game", + "image": "assets/icons/healthy.svg", + "color": "#cdd0ee", + }, + { + "label": "Novel", + "image": "assets/icons/Nutrition.svg", + "color": "#e8e29a", + }, + { + "label": "TTS", + "type": "puzzle", + "image": "assets/icons/Education.svg", + "color": "#efd8c6", + }, + { + "label": "Pazzle", + "type": "puzzle", + "image": "assets/icons/Safety.svg", + "color": "#cef1da", + }, + ]; + void _onMenuTapped(int index) { setState(() { _selectedIndex = index; @@ -60,14 +86,23 @@ class _PustakaScreenState extends State { final screenWidth = MediaQuery.of(context).size.width; final buttonScanSize = screenWidth * 0.20; final double bottomPadding = (9000 / screenWidth).clamp(0, 0.2); - List> filteredCollections = - _collections - .where( - (item) => item["label"]!.toLowerCase().contains( - _searchQuery.toLowerCase(), - ), - ) - .toList(); + + List> filterCollections( + List> collections, + String query, + ) { + return collections + .where( + (item) => + item["label"]!.toLowerCase().contains(query.toLowerCase()), + ) + .toList(); + } + + List> filteredCollections = filterCollections( + _collections, + _searchQuery, + ); return Scaffold( backgroundColor: const Color.fromARGB(255, 255, 255, 255), @@ -121,16 +156,6 @@ class _PustakaScreenState extends State { ], ), ), - - // // Date Display - // Padding( - // padding: const EdgeInsets.symmetric(vertical: 10), - // child: Text( - // DateTime.now().toString(), - // style: const TextStyle(color: Colors.white), - // ), - // ), - // Search Bar Padding( padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 10), @@ -198,7 +223,10 @@ class _PustakaScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => const ListEducation(), + builder: + (_) => ListEducation( + selectedCategory: item["label"], + ), ), ); }, @@ -231,61 +259,61 @@ class _PustakaScreenState extends State { child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( - children: List.generate( - 10, - (index) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - elevation: 5, - color: ColorHelper.hexToColor("#efd8c6"), - // color: const Color.fromARGB(140, 255, 255, 255), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(15), - // ), - child: GestureDetector( - onTap: - () => { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ListEducation(), - ), + children: + _genres.map((genre) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + elevation: 5, + color: ColorHelper.hexToColor("#efd8c6"), + // color: const Color.fromARGB(140, 255, 255, 255), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(15), + // ), + child: GestureDetector( + onTap: + () => { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ListEducation(), + ), + ), + }, + child: Container( + width: 80, + padding: const EdgeInsets.all(10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.book, + size: 50, + color: Colors.blueAccent, + ), + Text( + genre['label'], + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Color.fromARGB(255, 0, 0, 0), + ), + ), + ], ), - }, - child: Container( - width: 80, - padding: const EdgeInsets.all(10), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.book, - size: 50, - color: Colors.blueAccent, - ), - Text( - 'Topic ${index + 1}', - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Color.fromARGB(255, 0, 0, 0), - ), - ), - ], + ), ), ), - ), - ), - ), - ), + ); + }).toList(), ), ), ), ), - // Bottom Navigation - // MainMenu(), ], ), // BG MEnu diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index f681062..4ccd257 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,7 @@ import Foundation import desktop_webview_window import file_selector_macos +import flutter_inappwebview_macos import shared_preferences_foundation import url_launcher_macos import webview_flutter_wkwebview @@ -14,6 +15,7 @@ import webview_flutter_wkwebview func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 8b95e34..32499ef 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -206,6 +206,70 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0-beta.2" + flutter_inappwebview: + dependency: "direct main" + description: + name: flutter_inappwebview + sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + flutter_inappwebview_android: + dependency: transitive + description: + name: flutter_inappwebview_android + sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + flutter_inappwebview_internal_annotations: + dependency: transitive + description: + name: flutter_inappwebview_internal_annotations + sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + flutter_inappwebview_ios: + dependency: transitive + description: + name: flutter_inappwebview_ios + sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_macos: + dependency: transitive + description: + name: flutter_inappwebview_macos + sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_platform_interface: + dependency: transitive + description: + name: flutter_inappwebview_platform_interface + sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500 + url: "https://pub.dev" + source: hosted + version: "1.3.0+1" + flutter_inappwebview_web: + dependency: transitive + description: + name: flutter_inappwebview_web + sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_windows: + dependency: transitive + description: + name: flutter_inappwebview_windows + sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" + url: "https://pub.dev" + source: hosted + version: "0.6.0" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2fd55a3..615ac79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,6 +54,7 @@ dependencies: url: https://github.com/fhauze/list_detail_screen.git ref: main desktop_webview_window: ^0.2.3 + flutter_inappwebview: ^6.0.0 # arcore_flutter_plugin: ^0.2.0-alpha # flutter_unity_widget: ^2022.2.1 # arcore_flutter_plugin: @@ -124,6 +125,18 @@ flutter: - assets/html/seratair.png - assets/html/vitaminmineral.png + #drag and drop + - assets/html/findwords/ + - assets/html/findwords/test.html + - assets/html/findwords/findwords.html + - assets/html/freekake.png + - assets/html/memory/ + - assets/html/memory/memory.html + + #assets puzzle memory + - assets/html/memory/freekake.png + + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 5d07d38..6465cfb 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,6 +17,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 379ad60..bdc3b66 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window file_selector_windows + flutter_inappwebview_windows permission_handler_windows url_launcher_windows )