movable_ink_plugin 2.2.1 copy "movable_ink_plugin: ^2.2.1" to clipboard
movable_ink_plugin: ^2.2.1 copied to clipboard

MovableInk Plugin for Flutter

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:movable_ink_plugin/currency.dart';
import 'package:movable_ink_plugin/movable_ink_plugin.dart';
import 'package:push/push.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _resolvedURL = '';
  String _pushToken = '';
  static const String _pushTokenKey = 'push_token';
  final _movableInkPlugin = MovableInkPlugin();
  StreamSubscription<String>? streamSubscription;
  VoidCallback? unsubscribeOnNewToken;
  VoidCallback? unsubscribeOnNotificationTap;

  @override
  void initState() {
    super.initState();

    _loadStoredPushToken();
    initMovableInkListener();
    initPush();
  }

  Future<void> _loadStoredPushToken() async {
    final prefs = await SharedPreferences.getInstance();
    final storedToken = prefs.getString(_pushTokenKey);
    if (storedToken != null && storedToken.isNotEmpty) {
      setState(() {
        _pushToken = storedToken;
      });
    }
  }

  Future<void> _savePushToken(String token) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_pushTokenKey, token);
  }

  @override
  void dispose() {
    super.dispose();

    streamSubscription?.cancel();
    unsubscribeOnNewToken?.call();
    unsubscribeOnNotificationTap?.call();
  }

  void initMovableInkListener() async {
    streamSubscription = _movableInkPlugin.start().listen((String data) {
      debugPrint('Resolved Deeplink: $data');

      setState(() {
        _resolvedURL = data;
      });
    }, onError: (error) {
      debugPrint('start error: ${error.toString()}');
    });

    _movableInkPlugin.setMIU("00000000-0000-0000-0000-000000000000");
  }

  void initPush() async {
    await Push.instance.requestPermission();
    Push.instance.registerForRemoteNotifications();

    unsubscribeOnNewToken = Push.instance.addOnNewToken((token) {
      print("push token: $token");
      _savePushToken(token);
      setState(() {
        _pushToken = token;
      });
    });

    unsubscribeOnNotificationTap = Push.instance.addOnNotificationTap((data) {
      print('Notification was tapped:\n'
          'Data: $data \n');
      _movableInkPlugin.handlePushNotificationOpenedWithContent(data);
    });

    Push.instance.notificationTapWhichLaunchedAppFromTerminated.then((data) {
      if (data != null) {
        print(
            'Notification tap launched app from terminated state:\n RemoteMessage: $data \n');
        _movableInkPlugin.handlePushNotificationOpenedWithContent(data);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Movable SDK Test'),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  if (_pushToken.isNotEmpty) {
                    Clipboard.setData(ClipboardData(text: _pushToken));
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(
                          content: Text('Push token copied to clipboard!')),
                    );
                  }
                },
                child: Container(
                  width: double.infinity,
                  padding: const EdgeInsets.all(16),
                  margin: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Colors.grey[200],
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(color: Colors.grey[400]!),
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        children: [
                          const Icon(Icons.key, size: 16),
                          const SizedBox(width: 8),
                          const Text('Push Token (tap to copy)',
                              style: TextStyle(
                                  fontWeight: FontWeight.bold, fontSize: 14)),
                        ],
                      ),
                      const SizedBox(height: 8),
                      Text(
                        _pushToken.isEmpty
                            ? 'Waiting for token...'
                            : _pushToken,
                        style: TextStyle(
                          fontSize: 11,
                          fontFamily: 'monospace',
                          color:
                              _pushToken.isEmpty ? Colors.grey : Colors.black87,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                child: ElevatedButton(
                  style: ElevatedButton.styleFrom(
                      minimumSize: const Size.fromHeight(60)),
                  onPressed: () {
                    _resolveUrl();
                  },
                  child: const Text('Resolve Url'),
                ),
              ),
              Text('Resolved URL: $_resolvedURL',
                  style: const TextStyle(
                    fontSize: 12.0,
                    fontWeight: FontWeight.bold,
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _orderCompleted();
                    },
                    child: const Text('Order Completed'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _productViewed();
                    },
                    child: const Text('Product Viewed'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _categoryViewed();
                    },
                    child: const Text('Category Viewed'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _productSearched();
                    },
                    child: const Text('Product Searched'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _productAdded();
                    },
                    child: const Text('Product Added'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _productRemoved();
                    },
                    child: const Text('Product Removed'),
                  )),
              Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        minimumSize: const Size.fromHeight(60)),
                    onPressed: () {
                      _surfaceMessage();
                    },
                    child: const Text('Show In App Message'),
                  )),
            ],
          ),
        ),
      ),
    );
  }

  void _orderCompleted() {
    final Map<String, dynamic> properties = {
      "id": "123",
      "revenue": "300.00",
      "currency": Currency.USD.value,
      "products": [
        {
          "id": "111-6666",
          "price": "150.00",
          "quantity": 2,
          "meta": {"pages": 496}
        }
      ]
    };
    _movableInkPlugin.orderCompleted(properties);
  }

  void _productSearched() {
    final Map<String, dynamic> properties = {"query": "search_term"};
    _movableInkPlugin.productSearched(properties);
  }

  void _resolveUrl() {
    String urlString =
        "https://www.movable-ink-7158.com/p/cpm/f9e1dde60c339938/c?mi_u=999999&url=https%3A%2F%2Fwww.movable-ink-7158.com%2Fp%2Frpm%2F4ff5ef609123c272%2Furl&url_sig=U4ZfyQRrrBylUa";

    _movableInkPlugin.resolveUrl(urlString).then((value) {
      setState(() {
        _resolvedURL = value ?? '';
      });
    });
  }

  void _surfaceMessage() {
    _movableInkPlugin.showInAppMessage(
        "https://www.movable-ink-7158.com/p/rp/bc49c08945403625.html");
  }

  void _categoryViewed() {
    final Map<String, dynamic> properties = {
      "id": "sci-fi",
      "title": "Sci-Fi",
      "url": "https://inkrediblebooks.com/hyperion-dan-simmons",
      "meta": {"pages": 496}
    };
    _movableInkPlugin.categoryViewed(properties);
  }

  void _productAdded() {
    final Map<String, dynamic> properties = {
      "id": "1",
      "title": "Hyperion",
      "price": "15.99",
      "currency": Currency.USD.value,
      "url": "https://inkrediblebooks.com/hyperion-dan-simmons",
      "categories": [
        {"id": "Sci-Fi", "url": "https://inkrediblebooks.com/categories/scifi"},
        {
          "id": "Fiction",
          "url": "https://inkrediblebooks.com/categories/fiction"
        }
      ],
      "meta": {"pages": 496}
    };
    _movableInkPlugin.productAdded(properties);
  }

  void _productRemoved() {
    final Map<String, dynamic> properties = {
      "id": "1",
      "title": "Hyperion",
      "price": "15.99",
      "currency": "USD",
      "url": "https://inkrediblebooks.com/hyperion-dan-simmons",
      "categories": [
        {"id": "Sci-Fi", "url": "https://inkrediblebooks.com/categories/scifi"},
        {
          "id": "Fiction",
          "url": "https://inkrediblebooks.com/categories/fiction"
        }
      ],
      "meta": {"pages": 496}
    };
    _movableInkPlugin.productRemoved(properties);
  }

  void _productViewed() {
    final Map<String, dynamic> properties = {
      "id": "1",
      "title": "Hyperion",
      "price": "15.99",
      "currency": "USD",
      "url": "https://inkrediblebooks.com/hyperion-dan-simmons",
      "categories": [
        {"id": "Sci-Fi", "url": "https://inkrediblebooks.com/categories/scifi"},
        {
          "id": "Fiction",
          "url": "https://inkrediblebooks.com/categories/fiction"
        }
      ],
      "meta": {"pages": 496}
    };
    _movableInkPlugin.productViewed(properties);
  }

  void _logEvent() {
    final Map<String, dynamic> properties = {"id": "122", "segment": "launch"};
    _movableInkPlugin.logEvent("product_removed", properties);
  }
}