diff --git a/lib/constants/app_strings.dart b/lib/constants/app_strings.dart index d3df823..466cbf2 100644 --- a/lib/constants/app_strings.dart +++ b/lib/constants/app_strings.dart @@ -13,6 +13,7 @@ class AppStrings { static const String listViewExample = "ListView Example"; static const String taboolaWebIntegration = "Taboola Web Integration"; static const String taboolaInAppWebViewIntegration = "Taboola InAppWebView Integration"; + static const String taboolaTwoWebUnitsIntegration = "Taboola Two Web Units Integration"; // Menu items static const String menuItemSliverListWidgetFeed = 'SliverList Widget + Feed'; @@ -20,6 +21,7 @@ class AppStrings { static const String menuItemListViewWidget = 'ListView Widget'; static const String menuItemWebIntegration = 'Web Integration Flutter weview'; static const String menuItemWebIntegrationInappWebview = 'Web Integration InappWebview'; + static const String menuItemWebIntegrationTwoWebUnits = 'Web Integration Two Web Units'; // Widget labels static const String feedContainer = "Feed Container"; diff --git a/lib/constants/colors.dart b/lib/constants/colors.dart index eb0e5ea..f70ea66 100644 --- a/lib/constants/colors.dart +++ b/lib/constants/colors.dart @@ -7,6 +7,7 @@ class AppColors { static const Color lightGreen = Color.fromARGB(255, 67, 240, 177); static const Color orange = Color.fromARGB(255, 240, 147, 67); static const Color pink = Color.fromARGB(255, 240, 67, 149); + static const Color purple = Color.fromARGB(255, 155, 67, 240); static const Color darkGreen = Color(0xFF158443); static const Color blue = Color(0xFF61B3C3); static const Color indigo = Color(0xFF7C6DAF); diff --git a/lib/constants/routes.dart b/lib/constants/routes.dart index d975237..b09bd03 100644 --- a/lib/constants/routes.dart +++ b/lib/constants/routes.dart @@ -5,4 +5,5 @@ class Routes { static const String customListViewFeedAndWidget = '/customlistviewfeedAndWidget'; static const String webIntegrationFlutterWebview = '/webIntegrationFlutterWebview'; static const String webIntegrationInappWebview = '/webIntegrationInappWebview'; + static const String webIntegrationTwoWebUnits = '/webIntegrationTwoWebUnits'; } \ No newline at end of file diff --git a/lib/data/menu_items.dart b/lib/data/menu_items.dart index 0933e6c..39654fa 100644 --- a/lib/data/menu_items.dart +++ b/lib/data/menu_items.dart @@ -30,5 +30,10 @@ class MenuItemRepository { itemColor: AppColors.pink, routeName: Routes.webIntegrationInappWebview, ), + MenuItemModel( + title: AppStrings.menuItemWebIntegrationTwoWebUnits, + itemColor: AppColors.purple, + routeName: Routes.webIntegrationTwoWebUnits, + ), ]; } diff --git a/lib/main.dart b/lib/main.dart index 16a4865..4643f20 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,7 +8,8 @@ import 'package:taboola_flutter_example/pages/custom_scroll_view_page_widget.dar import 'package:taboola_flutter_example/pages/home_page.dart'; import 'package:taboola_flutter_example/pages/web_integration_inappwebview_page.dart'; import 'package:taboola_flutter_example/pages/web_integration_flutter_webview.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_flutter_example/pages/web_integration_two_web_units_screen.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -34,6 +35,7 @@ class TaboolaExampleApp extends StatelessWidget { Routes.customListViewFeedAndWidget: (context) => const CustomListViewPageFeedAndWidget(), Routes.webIntegrationFlutterWebview: (context) => const WebIntegrationFlutterWebview(), Routes.webIntegrationInappWebview: (context) => const WebIntegrationInappWebviewPage(), + Routes.webIntegrationTwoWebUnits: (context) => const WebIntegrationTwoWebUnitsScreen(), }, ); } diff --git a/lib/pages/custom_list_view_page_widget.dart b/lib/pages/custom_list_view_page_widget.dart index 6b01acc..bc60b42 100644 --- a/lib/pages/custom_list_view_page_widget.dart +++ b/lib/pages/custom_list_view_page_widget.dart @@ -3,10 +3,10 @@ import 'package:taboola_flutter_example/constants/publisher_params.dart'; import 'package:taboola_flutter_example/constants/ui_constants.dart'; import 'package:taboola_flutter_example/constants/app_strings.dart'; -import 'package:taboola_sdk/classic/tbl_classic_listener.dart'; -import 'package:taboola_sdk/classic/tbl_classic_page.dart'; -import 'package:taboola_sdk/classic/tbl_classic_unit.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_listener.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_page.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_unit.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; class CustomListViewPageFeedAndWidget extends StatefulWidget { const CustomListViewPageFeedAndWidget({Key? key}) : super(key: key); diff --git a/lib/pages/custom_scroll_view_page_feed_and_widget.dart b/lib/pages/custom_scroll_view_page_feed_and_widget.dart index bdb310f..1738bd5 100644 --- a/lib/pages/custom_scroll_view_page_feed_and_widget.dart +++ b/lib/pages/custom_scroll_view_page_feed_and_widget.dart @@ -4,10 +4,10 @@ import 'package:flutter/material.dart'; import 'package:taboola_flutter_example/constants/publisher_params.dart'; import 'package:taboola_flutter_example/constants/ui_constants.dart'; -import 'package:taboola_sdk/classic/tbl_classic_listener.dart'; -import 'package:taboola_sdk/classic/tbl_classic_page.dart'; -import 'package:taboola_sdk/classic/tbl_classic_unit.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_listener.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_page.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_unit.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; import 'package:taboola_flutter_example/constants/app_strings.dart'; class CustomScrollViewPageFeedAndWidget extends StatefulWidget { diff --git a/lib/pages/custom_scroll_view_page_widget.dart b/lib/pages/custom_scroll_view_page_widget.dart index db19000..231be0d 100644 --- a/lib/pages/custom_scroll_view_page_widget.dart +++ b/lib/pages/custom_scroll_view_page_widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:taboola_flutter_example/constants/publisher_params.dart'; import 'package:taboola_flutter_example/constants/ui_constants.dart'; -import 'package:taboola_sdk/classic/tbl_classic_listener.dart'; -import 'package:taboola_sdk/classic/tbl_classic_page.dart'; -import 'package:taboola_sdk/classic/tbl_classic_unit.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_listener.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_page.dart'; +import 'package:taboola_sdk_beta/classic/tbl_classic_unit.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; import 'package:taboola_flutter_example/constants/app_strings.dart'; class CustomScrollViewPageWidget extends StatefulWidget { diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 70d738a..3edfe3a 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -3,6 +3,7 @@ import 'package:taboola_flutter_example/constants/app_strings.dart'; import 'package:taboola_flutter_example/constants/ui_constants.dart'; import 'package:taboola_flutter_example/data/menu_items.dart'; import 'package:taboola_flutter_example/widgets/menu_item.dart'; +import 'package:taboola_flutter_example/pages/web_integration_two_web_units_screen.dart'; class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); diff --git a/lib/pages/web_integration_flutter_webview.dart b/lib/pages/web_integration_flutter_webview.dart index f9441e0..e2b4bdf 100644 --- a/lib/pages/web_integration_flutter_webview.dart +++ b/lib/pages/web_integration_flutter_webview.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:taboola_flutter_example/constants/ui_constants.dart'; +import 'package:taboola_flutter_example/utils/snack_bar_utils.dart'; import 'package:webview_flutter/webview_flutter.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; import 'package:taboola_flutter_example/constants/app_strings.dart'; import 'package:webview_flutter_android/webview_flutter_android.dart'; - const String kLocalExamplePage = ''' @@ -78,7 +78,8 @@ class WebIntegrationFlutterWebview extends StatefulWidget { State createState() => _WebIntegrationFlutterWebviewState(); } -class _WebIntegrationFlutterWebviewState extends State { +class _WebIntegrationFlutterWebviewState extends State + with SnackBarMixin { late final WebViewController _webViewController; late final TBLWebUnit _taboolaWebUnit; final ScrollController _scrollController = ScrollController(); @@ -97,19 +98,14 @@ class _WebIntegrationFlutterWebviewState extends State ScaffoldMessenger.of(context).hideCurrentSnackBar(), - ), - ), - ); + void tblOnUpdateContentCompleted() { + showSnackBar("Content update completed"); } -} \ No newline at end of file +} diff --git a/lib/pages/web_integration_inappwebview_page.dart b/lib/pages/web_integration_inappwebview_page.dart index 8a62c65..101cd1f 100644 --- a/lib/pages/web_integration_inappwebview_page.dart +++ b/lib/pages/web_integration_inappwebview_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -import 'package:taboola_sdk/taboola.dart'; +import 'package:taboola_flutter_example/utils/snack_bar_utils.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; import 'package:taboola_flutter_example/constants/app_strings.dart'; @@ -95,12 +96,11 @@ class WebIntegrationInappWebviewPage extends StatefulWidget { const WebIntegrationInappWebviewPage({Key? key}) : super(key: key); @override - _WebIntegrationInappWebviewPageState createState() => - _WebIntegrationInappWebviewPageState(); + _WebIntegrationInappWebviewPageState createState() => _WebIntegrationInappWebviewPageState(); } -class _WebIntegrationInappWebviewPageState - extends State { +class _WebIntegrationInappWebviewPageState extends State + with SnackBarMixin { final GlobalKey webViewKey = GlobalKey(); InAppWebViewController? webViewController; late TBLWebUnit tblWebUnit; @@ -135,12 +135,8 @@ class _WebIntegrationInappWebviewPageState InAppWebView( key: webViewKey, onWebViewCreated: (inappwebviewController) async { - TBLWebListener tblWebListener = TBLWebListener( - _tblDidResize, - _tblDidShow, - _tblDidFailToLoad, - _tblDidClickOnItem, - ); + TBLWebListener tblWebListener = TBLWebListener(tblDidResize, tblDidShow, + tblDidFailToLoad, tblDidClickOnItem, tblOnUpdateContentCompleted); TBLWebPage webPage = Taboola.getWebPage(); tblWebUnit = webPage.buildWebUnit( webViewKey, @@ -157,46 +153,31 @@ class _WebIntegrationInappWebviewPageState ]))); } - void _tblDidShow(String placement) { - print("tblDidShow for placement: $placement"); - _showSnackBar("${AppStrings.adShownMessage}$placement"); + void tblDidShow(String placement) { + showSnackBar("${AppStrings.adShownMessage}$placement"); } - void _tblDidResize(String placement, double height) { - print("Ad resized for placement $placement to height $height"); - _showSnackBar( + void tblDidResize(String placement, double height) { + showSnackBar( "${AppStrings.adResizedMessage}$placement${AppStrings.adResizedHeightMessage}$height"); } - void _tblDidFailToLoad(String placement, String error) { - print("Ad failed to load for placement: $placement with error: $error"); - _showSnackBar( - "${AppStrings.adFailedMessage}$placement${AppStrings.adFailedErrorMessage}$error"); + void tblDidFailToLoad(String placement, String error) { + showSnackBar("${AppStrings.adFailedMessage}$placement${AppStrings.adFailedErrorMessage}$error"); } - bool _tblDidClickOnItem( - String placement, String itemId, String clickUrl, bool organic) { + bool tblDidClickOnItem(String placement, String itemId, String clickUrl, bool organic) { print( "Publisher did click on item: $itemId with clickUrl: $clickUrl in placement: $placement of organic: $organic"); if (organic) { - _showSnackBar(AppStrings.organicClickMessage); - print("organic"); + showSnackBar(AppStrings.organicClickMessage); } else { - _showSnackBar(AppStrings.sponsoredClickMessage); - print("SC"); + showSnackBar(AppStrings.sponsoredClickMessage); } return false; } - void _showSnackBar(String message) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(message), - action: SnackBarAction( - label: AppStrings.okButton, - onPressed: () => ScaffoldMessenger.of(context).hideCurrentSnackBar(), - ), - ), - ); + void tblOnUpdateContentCompleted() { + showSnackBar("Content update completed"); } } diff --git a/lib/pages/web_integration_two_web_units_screen.dart b/lib/pages/web_integration_two_web_units_screen.dart new file mode 100644 index 0000000..d498e79 --- /dev/null +++ b/lib/pages/web_integration_two_web_units_screen.dart @@ -0,0 +1,262 @@ +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:taboola_sdk_beta/taboola.dart'; + +import 'package:taboola_flutter_example/utils/snack_bar_utils.dart'; +import 'package:taboola_flutter_example/utils/webview_utils.dart'; + +const String kLocalExamplePage = ''' + + + + + + + + +
+
+ + + + + + + +'''; + +class WebIntegrationTwoWebUnitsScreen extends StatefulWidget { + const WebIntegrationTwoWebUnitsScreen({Key? key}) : super(key: key); + + @override + State createState() => _WebIntegrationTwoWebUnitsScreenState(); +} + +class _WebIntegrationTwoWebUnitsScreenState extends State + with SnackBarMixin { + late final WebViewController _topWebViewController; + late final WebViewController _bottomWebViewController; + late final TBLWebUnit _topTaboolaWebUnit; + late final TBLWebUnit _bottomTaboolaWebUnit; + late final TBLWebPage _tblWebPage; + final int LIST_LENGTH = 10; + final ScrollController _scrollController = ScrollController(); + + // Keys for each WebView container + final GlobalKey _topWebViewKey = GlobalKey(); + final GlobalKey _bottomWebViewKey = GlobalKey(); + + // Style + final double CONTAINER_HEIGHT = 600; + final double LIST_ITEM_PADDING = 20.0; + + @override + void initState() { + super.initState(); + _topWebViewController = WebViewUtils.createWebViewController(); + _bottomWebViewController = WebViewUtils.createWebViewController(); + + // Initialize TBLWebPage + _tblWebPage = Taboola.getWebPage(); + + // Create listeners for both units + TBLWebListener topListener = TBLWebListener( + tblDidResize, tblDidShow, tblDidFailToLoad, tblDidClickOnItem, _onUpdateContentCompleted); + + TBLWebListener bottomListener = TBLWebListener( + tblDidResize, tblDidShow, tblDidFailToLoad, tblDidClickOnItem, _onUpdateContentCompleted); + + // Initialize both web units + _topTaboolaWebUnit = _tblWebPage.buildWebUnit( + _topWebViewKey, _topWebViewController, topListener, + scrollController: _scrollController); + + _bottomTaboolaWebUnit = _tblWebPage.buildWebUnit( + _bottomWebViewKey, _bottomWebViewController, bottomListener, + scrollController: _scrollController); + + // // Log view IDs + print("Top WebUnit ViewID: ${_topTaboolaWebUnit.viewId}"); + print("Bottom WebUnit ViewID: ${_bottomTaboolaWebUnit.viewId}"); + + _topWebViewController + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..loadHtmlString(kLocalExamplePage); + + _bottomWebViewController + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..loadHtmlString(kLocalExamplePage); + } + + @override + void dispose() { + // Clear all widgets and dispose of web units + _tblWebPage.clearAllWidgets(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Dual Taboola WebUnits'), + actions: [ + IconButton( + icon: Icon(Icons.refresh), + onPressed: () { + // Test refreshPage function + _tblWebPage.refreshPage(); + showSnackBar("Refreshed all Taboola units"); + }, + ), + ], + ), + body: CustomScrollView( + controller: _scrollController, + slivers: [ + SliverList( + delegate: SliverChildListDelegate(_buildList(LIST_LENGTH, "Top")), + ), + // Top Taboola WebUnit + SliverToBoxAdapter( + child: Column( + children: [ + Text("Top Taboola Unit", style: TextStyle(fontWeight: FontWeight.bold)), + ElevatedButton( + onPressed: () { + _topTaboolaWebUnit.refresh(); + showSnackBar("Refreshed top Taboola unit"); + }, + child: Text('Refresh Top Unit')), + Container( + key: _topWebViewKey, + height: CONTAINER_HEIGHT, + child: WebViewWidget( + controller: _topWebViewController, + ), + ), + ], + ), + ), + SliverList( + delegate: SliverChildListDelegate(_buildList(LIST_LENGTH, "Middle")), + ), + // Bottom Taboola WebUnit + SliverToBoxAdapter( + child: Column( + children: [ + Text("Bottom Taboola Unit", style: TextStyle(fontWeight: FontWeight.bold)), + ElevatedButton( + onPressed: () { + _bottomTaboolaWebUnit.refresh(); + showSnackBar("Refreshed bottom Taboola unit"); + }, + child: Text('Refresh Bottom Unit')), + Container( + key: _bottomWebViewKey, + height: CONTAINER_HEIGHT, + child: WebViewWidget( + controller: _bottomWebViewController, + ), + ), + ], + ), + ), + SliverList( + delegate: SliverChildListDelegate(_buildList(LIST_LENGTH, "Bottom")), + ), + ], + ), + ); + } + + List _buildList(int count, String section) { + List listItems = []; + for (int i = 0; i < count; i++) { + listItems.add( + Padding( + padding: EdgeInsets.all(LIST_ITEM_PADDING), + child: Text( + '$section Item $i', + style: const TextStyle(fontSize: 20.0), + ), + ), + ); + } + return listItems; + } + + // Callback when the ad is shown. + void tblDidShow(String placement) { + showSnackBar("Ad shown for placement: $placement"); + } + + // Callback when the ad is resized. + void tblDidResize(String placement, double height) { + showSnackBar("Ad resized for placement: $placement to height: $height"); + } + + // Callback when the ad fails to load. + void tblDidFailToLoad(String placement, String error) { + showSnackBar("Ad load failed for placement: $placement\nError: $error"); + } + + // Callback when an item is clicked. + bool tblDidClickOnItem(String placement, String itemId, String clickUrl, bool organic) { + print( + "Publisher did click on item: $itemId with clickUrl: $clickUrl in placement: $placement; organic: $organic"); + if (organic) { + showSnackBar("Clicked on organic item in placement: $placement"); + } else { + showSnackBar("Clicked on sponsored item in placement: $placement"); + } + return false; + } + + void _onUpdateContentCompleted() { + showSnackBar("Content update completed"); + } +} diff --git a/lib/utils/snack_bar_utils.dart b/lib/utils/snack_bar_utils.dart new file mode 100644 index 0000000..5200550 --- /dev/null +++ b/lib/utils/snack_bar_utils.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +/// A mixin that provides snack bar functionality to any widget state class +mixin SnackBarMixin on State { + static String OK = 'OK'; + + /// Shows a snack bar message using a SnackBar + void showSnackBar(String message) { + // Only proceed if the widget is still mounted + if (!mounted) return; + + final scaffoldMessenger = ScaffoldMessenger.of(context); + + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text(message), + action: SnackBarAction( + label: OK, + onPressed: () { + scaffoldMessenger.hideCurrentSnackBar(); + }, + ), + ), + ); + } +} diff --git a/lib/utils/webview_utils.dart b/lib/utils/webview_utils.dart new file mode 100644 index 0000000..0c1b0c4 --- /dev/null +++ b/lib/utils/webview_utils.dart @@ -0,0 +1,19 @@ +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; + +/// Utility class for WebView related functionality +class WebViewUtils { + /// Creates a WebViewController with platform-specific parameters + static WebViewController createWebViewController() { + late final PlatformWebViewControllerCreationParams params; + if (WebViewPlatform.instance is WebKitWebViewPlatform) { + params = WebKitWebViewControllerCreationParams( + allowsInlineMediaPlayback: true, + mediaTypesRequiringUserAction: const {}, + ); + } else { + params = const PlatformWebViewControllerCreationParams(); + } + return WebViewController.fromPlatformCreationParams(params); + } +} \ No newline at end of file