From cd51913f604c4a5fdf21b9d0406d3d897b83898b Mon Sep 17 00:00:00 2001 From: Diyan Date: Tue, 14 Nov 2023 23:02:15 +0200 Subject: [PATCH] m_patches importer --- lib/UI/pages/mighty_patches_importer.dart | 232 ++++++++++++++++++ .../presets/preset_list/presetList.dart | 12 +- pubspec.yaml | 3 + 3 files changed, 243 insertions(+), 4 deletions(-) create mode 100644 lib/UI/pages/mighty_patches_importer.dart diff --git a/lib/UI/pages/mighty_patches_importer.dart b/lib/UI/pages/mighty_patches_importer.dart new file mode 100644 index 0000000..0b1d711 --- /dev/null +++ b/lib/UI/pages/mighty_patches_importer.dart @@ -0,0 +1,232 @@ +// import the necessary packages +/* +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:mighty_plug_manager/UI/popups/savePreset.dart'; +import 'package:mighty_plug_manager/UI/widgets/common/nestedWillPopScope.dart'; +import 'package:mighty_plug_manager/bluetooth/NuxDeviceControl.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:http/http.dart' as http; +import 'package:qr_utils/qr_utils.dart'; + +// create a stateful widget for the page +class MightyPatchesPage extends StatefulWidget { + const MightyPatchesPage({super.key}); + + @override + _MightyPatchesPageState createState() => _MightyPatchesPageState(); +} + +// create the state class for the widget +class _MightyPatchesPageState extends State { +// create a web view controller + late WebViewController _controller; + bool _fromAppBar = false; + + @override + void initState() { + super.initState(); + + _fromAppBar = false; + + _controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..enableZoom(false) + ..setNavigationDelegate(NavigationDelegate( + onPageFinished: (url) { + _registerDOMChanged(); + }, + onProgress: (progress) { + _addImportButtons(); + }, + )) + ..addJavaScriptChannel( + "flutter_inappwebview", + onMessageReceived: (message) { + // Handle the message received from JavaScript + String jsonMessage = message.message; + Map data = json.decode(jsonMessage); + // Extract title and URL from the JSON data + String title = data['title']; + String imageUrl = data['imageUrl']; + + // Call your Flutter method with the title and image URL + _importImage(imageUrl, title); + }, + ) + ..addJavaScriptChannel("flutter_domchange", onMessageReceived: (message) { + print("DOM Changed"); + _addImportButtons(); + }); + _home(); + } + + void _home() { + _controller.loadRequest(Uri.parse('https://www.mightypatches.com/')); + } + + void _registerDOMChanged() { + const String script = ''' + var observeDOM = (function(){ + var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; + + return function( obj, callback ) { + if( !obj || obj.nodeType !== 1 ) return; + + if( MutationObserver ){ + // define a new observer + var mutationObserver = new MutationObserver(callback) + + // have the observer observe for changes in children + mutationObserver.observe( obj, { childList:true, subtree:true }) + return mutationObserver + } + + // browser support fallback + else if( window.addEventListener ){ + obj.addEventListener('DOMNodeInserted', callback, false) + obj.addEventListener('DOMNodeRemoved', callback, false) + } + } + })() + + var observed = document.querySelector(".page-content, [data-elementor-type=single-post]"); + + observeDOM(observed, function(m){ + flutter_domchange.postMessage(""); + }); + '''; + + _controller.runJavaScript(script); + } + + void _addImportButtons() async { + // Evaluate JavaScript to find elements and add import buttons + const String script = ''' + + function getSmallestSizeImageUrl(srcset) { + // Split the srcset into individual URL-width pairs + const pairs = srcset.split(',').map(pair => pair.trim().split(' ')); + + // Find the pair with the smallest width + const smallestPair = pairs.reduce((smallest, current) => { + const currentWidth = parseInt(current[1], 10); + const smallestWidth = parseInt(smallest[1], 10); + return currentWidth < smallestWidth ? current : smallest; + }, pairs[0]); + + // Return the URL from the smallest pair + return smallestPair[0]; + } + + var elements = document.querySelectorAll(".page-content [data-elementor-type=jet-listing-items]:not(:has(.import-button)), [data-elementor-type=single-post]:not(:has(.import-button))"); + elements.forEach(function(element) { + var imageWidget = element.querySelector(".elementor-widget-image"); + var imgElement = imageWidget.querySelector("img"); + //var imageUrl = imgElement.src; + const srcset = imgElement.getAttribute('srcset'); + const imageUrl = getSmallestSizeImageUrl(srcset); + + var titleElement = element.querySelector(".elementor-page-title .elementor-heading-title,.page-content .elementor-heading-title"); + var title = titleElement.textContent; + + var importButton = document.createElement("a"); + importButton.href = "javascript:void(0);"; // Placeholder href, you can change this + importButton.className = "import-button"; + importButton.style.position = "absolute"; + importButton.style.bottom = "0"; + importButton.style.right = "0"; + importButton.style.width = "50%"; + importButton.style.height = "50px"; + importButton.style.backgroundColor = "blue"; + importButton.style.color = "white"; + importButton.style.display = "flex"; + importButton.style.alignItems = "center"; + importButton.style.justifyContent = "center"; + importButton.innerHTML = "Import"; + + importButton.onclick = function() { + // Send title and image URL to Flutter using the JavascriptChannel + var data = { + "title": title, + "imageUrl": imageUrl + }; + flutter_inappwebview.postMessage(JSON.stringify(data)); + }; + + imageWidget.appendChild(importButton); + }); + '''; + + _controller.runJavaScript(script); + } + +// create a method to handle the import button click + void _importImage(String imageUrl, String imageName) async { +// get the image data from the url using http stream + print("opening stream"); + http.StreamedResponse response = + await http.Client().send(http.Request('GET', Uri.parse(imageUrl))); + print("Reading stream"); +// get the byte data from the response stream + List byteData = await response.stream.toBytes(); + + print("decoding QR"); +// scan the image data using qr utils + String? qrData = await QrUtils.scanImageFromData(byteData); + + print("Showing data"); +// do something with the qr data, such as showing a dialog + + if (qrData != null) { + var device = NuxDeviceControl.instance().device; + + var preset = device.setupDetachedPresetFromQRData(qrData); + var saveDialog = SavePresetDialog( + customName: imageName, + customPreset: preset, + device: device, + confirmColor: Theme.of(context).hintColor); + showDialog( + context: context, + builder: (BuildContext context) => + saveDialog.buildDialog(device, context), + ); + } + } + + @override + Widget build(BuildContext context) { + return NestedWillPopScope( + onWillPop: () async { + if (_fromAppBar) return true; + if (await _controller.canGoBack()) { + _controller.goBack(); + return false; + } + return true; + }, + child: SafeArea( + child: Scaffold( + appBar: AppBar( + title: const Text('Mighty Patches'), + leading: IconButton( + icon: Icon(Icons.adaptive.arrow_back), + onPressed: () { + // Set the flag to true before popping the navigation + _fromAppBar = true; + + Navigator.of(context).pop(); + }, + ), + actions: [ + IconButton(onPressed: _home, icon: const Icon(Icons.home)) + ], + ), + body: WebViewWidget(controller: _controller)), + ), + ); + } +} +*/ \ No newline at end of file diff --git a/lib/UI/widgets/presets/preset_list/presetList.dart b/lib/UI/widgets/presets/preset_list/presetList.dart index 460cb3f..de23d6f 100644 --- a/lib/UI/widgets/presets/preset_list/presetList.dart +++ b/lib/UI/widgets/presets/preset_list/presetList.dart @@ -7,6 +7,7 @@ import 'package:mighty_plug_manager/UI/toneshare/toneshare_main.dart'; import 'package:mighty_plug_manager/UI/widgets/presets/preset_list/preset_widget.dart'; import 'package:mighty_plug_manager/platform/simpleSharedPrefs.dart'; import '../../../mainTabs.dart'; +import '../../../pages/mighty_patches_importer.dart'; import '/utilities/string_extensions.dart'; import '../../search_field.dart'; @@ -100,8 +101,11 @@ class _PresetListState extends State } void _openToneShare() { - Navigator.of(context) - .push(MaterialPageRoute(builder: (context) => const ToneShare())); + //Navigator.of(context) + // .push(MaterialPageRoute(builder: (context) => const ToneShare())); + + //Navigator.of(context) + // .push(MaterialPageRoute(builder: (context) => MightyPatchesPage())); } Widget _mainPopupMenu() { @@ -139,13 +143,13 @@ class _PresetListState extends State trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - if (kDebugMode) + /*if (kDebugMode) IconButton( onPressed: _openToneShare, icon: const Icon( Icons.cloud_download, size: 28, - )), + )),*/ IconButton( onPressed: () { _showSearch = true; diff --git a/pubspec.yaml b/pubspec.yaml index df5c27c..fae4225 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -81,6 +81,9 @@ dependencies: convert: ^3.0.1 pocketbase: ^0.16.0 + #webview_flutter: ^4.4.2 + #http: ^1.1.0 + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. # cupertino_icons: ^0.1.3