Skip to main content

linkbud_flutter 0.4.0 copy "linkbud_flutter: ^0.4.0" to clipboard
linkbud_flutter: ^0.4.0 copied to clipboard

Flutter plugin for LinkBud app-link resolution and explicit recovery on Android and iOS.

example/lib/main.dart

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:linkbud_flutter/linkbud_flutter.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xff166534)),
      ),
      home: const LinkBudExample(),
    ),
  );
}

class LinkBudExample extends StatefulWidget {
  const LinkBudExample({super.key});
  @override
  State<LinkBudExample> createState() => _LinkBudExampleState();
}

class _LinkBudExampleState extends State<LinkBudExample> {
  final sdk = LinkBud.instance;
  final code = TextEditingController();
  StreamSubscription<LinkBudResult>? subscription;
  String status = 'Initializing public environment configuration…';
  bool signedIn = false;
  bool busy = true;
  bool routing = false;
  String? routedId;

  @override
  void initState() {
    super.initState();
    subscription = sdk.incoming.listen(
      (result) => unawaited(show(result)),
      onError: (_) {
        if (mounted)
          setState(
            () => status = 'Incoming link failed. Reopen the original link.',
          );
      },
    );
    unawaited(
      run(
        () => sdk.initialize(
          const LinkBudConfiguration(
            origin: String.fromEnvironment(
              'LINKBUD_ORIGIN',
              defaultValue: 'https://links.example.com',
            ),
            applicationId: String.fromEnvironment(
              'LINKBUD_APPLICATION',
              defaultValue: 'aaaaaaaaaaaaaaaaaaaaaaaaaa',
            ),
            environment: String.fromEnvironment(
              'LINKBUD_ENVIRONMENT',
              defaultValue: 'development',
            ),
            sdkId: String.fromEnvironment(
              'LINKBUD_SDK_ID',
              defaultValue: 'bbbbbbbbbbbbbbbbbbbbbbbbbb',
            ),
            appleAppId: String.fromEnvironment(
              'LINKBUD_APPLE_APP_ID',
              defaultValue: 'A1B2C3D4E5.dev.linkbud.sample',
            ),
          ),
        ),
      ),
    );
  }

  Future<void> run(Future<LinkBudResult> Function() operation) async {
    setState(() => busy = true);
    try {
      await show(await operation());
    } catch (_) {
      if (mounted)
        setState(
          () => status =
              'Operation failed. Check setup or retry after the current operation.',
        );
    } finally {
      if (mounted) setState(() => busy = false);
    }
  }

  Future<void> show(LinkBudResult result) async {
    if (!mounted) return;
    switch (result) {
      case PendingDestination():
        if (!signedIn) {
          setState(() => status = 'Destination waiting for simulated login.');
          return;
        }
        if (result.expiresAt.isBefore(DateTime.now().toUtc()) ||
            Uri.parse(result.destination).path != '/welcome') {
          setState(
            () => status =
                'Expired or unsupported route. Only /welcome is allowed in this sample.',
          );
          return;
        }
        if (routing) return;
        routing = true;
        try {
          // Demo only. A real host must authenticate, revalidate and authorize its own routes.
          if (routedId != result.id) {
            routedId = result.id;
            setState(
              () => status = 'Welcome! Simulated authorized navigation.',
            );
          }
          if (!await sdk.acknowledge(result.id) && mounted) {
            setState(
              () => status =
                  'Welcome shown; acknowledgment failed. Retry without navigating twice.',
            );
          }
        } finally {
          routing = false;
        }
      case LinkBudRetryable():
        setState(
          () => status = 'Retry at or after ${result.retryAt.toLocal()}.',
        );
      case LinkBudRejected():
        setState(
          () => status =
              'Cannot continue (${result.reason}). Reopen the link or request a fresh code.',
        );
      case LinkBudAlreadyAcknowledged():
        setState(() => status = 'Journey already handled.');
      case LinkBudEmpty():
        setState(
          () => status = 'No pending destination. Open a configured link.',
        );
    }
  }

  @override
  void dispose() {
    unawaited(subscription?.cancel());
    code.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('LinkBud Flutter preview')),
    body: ListView(
      padding: const EdgeInsets.all(24),
      children: [
        const Text(
          'Demo login only. Real authentication and route authorization belong to the host app.',
        ),
        const SizedBox(height: 24),
        Text(status, key: const Key('linkbud-status'), semanticsLabel: status),
        const SizedBox(height: 24),
        FilledButton(
          onPressed: busy
              ? null
              : () {
                  setState(() => signedIn = true);
                  unawaited(run(sdk.resume));
                },
          child: Text(
            signedIn
                ? 'Revalidate pending destination'
                : 'Simulate login and revalidate',
          ),
        ),
        TextButton(
          onPressed: busy ? null : () => unawaited(run(sdk.resume)),
          child: const Text('Retry'),
        ),
        if (Platform.isIOS) ...[
          const SizedBox(height: 24),
          TextField(
            controller: code,
            decoration: const InputDecoration(labelText: 'Recovery code'),
            autocorrect: false,
          ),
          FilledButton(
            onPressed: busy
                ? null
                : () {
                    final entered = code.text;
                    code.clear();
                    unawaited(run(() => sdk.recover(entered)));
                  },
            child: const Text('Use entered code'),
          ),
          const Text(
            'Explicit code entry only. No automatic recovery or clipboard reading.',
          ),
        ],
      ],
    ),
  );
}
0
likes
150
points
0
downloads

Documentation

API reference

Publisher

verified publishercodeloops.net

Weekly Downloads

Flutter plugin for LinkBud app-link resolution and explicit recovery on Android and iOS.

Repository (GitHub)

License

MIT (license)

Dependencies

flutter

More

Packages that depend on linkbud_flutter

Packages that implement linkbud_flutter