social_share_kit 0.2.0 copy "social_share_kit: ^0.2.0" to clipboard
social_share_kit: ^0.2.0 copied to clipboard

Share text, links and files directly to X, WhatsApp, Instagram, Threads, Telegram, LinkedIn, Messenger, TikTok, SMS and mail, or to the system share sheet. Reports per-target capabilities up front. Bu [...]

example/lib/main.dart

import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;

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

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'social_share_kit',
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        brightness: Brightness.dark,
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final TextEditingController _text = TextEditingController(
    text: 'Shipping social_share_kit today.',
  );
  final TextEditingController _url = TextEditingController(
    text: 'https://pub.flutter-io.cn/packages/social_share_kit',
  );

  Map<ShareTarget, bool> _installed = const <ShareTarget, bool>{};
  bool _attachImage = false;
  String? _imagePath;

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

  @override
  void dispose() {
    _text.dispose();
    _url.dispose();
    super.dispose();
  }

  Future<void> _refreshInstalled() async {
    final Map<ShareTarget, bool> installed =
        await SocialShareKit.installedTargets();
    if (mounted) setState(() => _installed = installed);
  }

  /// Draws a PNG to a temp file, so the example can demonstrate file sharing
  /// without pulling in an image picker.
  Future<String> _sampleImage() async {
    final String? existing = _imagePath;
    if (existing != null && File(existing).existsSync()) return existing;

    final ui.PictureRecorder recorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(recorder);
    const Size size = Size(600, 600);

    canvas.drawRect(
      Offset.zero & size,
      Paint()..color = const Color(0xFF3F51B5),
    );
    canvas.drawCircle(
      size.center(Offset.zero),
      180,
      Paint()..color = const Color(0xFFFFC107),
    );

    final ui.Image image = await recorder
        .endRecording()
        .toImage(size.width.toInt(), size.height.toInt());
    final ByteData? data =
        await image.toByteData(format: ui.ImageByteFormat.png);

    // systemTemp is the app's cache directory on both platforms, which is one
    // of the roots the plugin's FileProvider is allowed to hand out.
    final File file = File('${Directory.systemTemp.path}/sample.png');
    await file.writeAsBytes(data!.buffer.asUint8List(), flush: true);

    _imagePath = file.path;
    return file.path;
  }

  Future<void> _share(ShareTarget target) async {
    final List<String> files =
        _attachImage ? <String>[await _sampleImage()] : const <String>[];

    final ShareResult result = await SocialShareKit.shareTo(
      target,
      ShareContent(
        text: _text.text.isEmpty ? null : _text.text,
        url: _url.text.isEmpty ? null : _url.text,
        subject: 'Shared from social_share_kit',
        files: files,
      ),
    );

    if (!mounted) return;
    ScaffoldMessenger.of(context)
      ..clearSnackBars()
      ..showSnackBar(
        SnackBar(
          content: Text(
            result.message == null
                ? '${target.id}: ${result.status.name}'
                : '${target.id}: ${result.status.name}\n${result.message}',
          ),
          backgroundColor: result.isSuccess ? null : Colors.red.shade700,
          duration: Duration(seconds: result.isSuccess ? 2 : 6),
        ),
      );
  }

  Future<void> _shareStory(ShareTarget target) async {
    final ShareResult result = await SocialShareKit.shareStory(
      target,
      StoryContent(
        // Replace with your own Facebook app id; both story composers reject
        // the share without one.
        appId: '0000000000000000',
        backgroundImage: await _sampleImage(),
        text: _text.text,
      ),
    );

    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('${target.id}: ${result.status.name}')),
    );
  }

  @override
  Widget build(BuildContext context) {
    final List<ShareTarget> targets = SocialShareKit.supportedTargets();

    return Scaffold(
      appBar: AppBar(
        title: const Text('social_share_kit'),
        actions: <Widget>[
          IconButton(
            onPressed: _refreshInstalled,
            icon: const Icon(Icons.refresh),
            tooltip: 'Re-check installed apps',
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: <Widget>[
          TextField(
            controller: _text,
            maxLines: 3,
            decoration: const InputDecoration(
              labelText: 'Text',
              border: OutlineInputBorder(),
            ),
          ),
          const SizedBox(height: 12),
          TextField(
            controller: _url,
            decoration: const InputDecoration(
              labelText: 'Link',
              border: OutlineInputBorder(),
            ),
          ),
          SwitchListTile(
            value: _attachImage,
            onChanged: (bool value) => setState(() => _attachImage = value),
            title: const Text('Attach a generated PNG'),
            subtitle: const Text(
              'Targets that cannot take files will say so instead of sharing',
            ),
            contentPadding: EdgeInsets.zero,
          ),
          const Divider(height: 32),
          for (final ShareTarget target in targets)
            _TargetTile(
              target: target,
              installed: _installed[target],
              capabilities: SocialShareKit.capabilities(target),
              onShare: () => target.isStoryTarget
                  ? _shareStory(target)
                  : _share(target),
            ),
        ],
      ),
    );
  }
}

class _TargetTile extends StatelessWidget {
  const _TargetTile({
    required this.target,
    required this.installed,
    required this.capabilities,
    required this.onShare,
  });

  final ShareTarget target;
  final bool? installed;
  final ShareCapabilities capabilities;
  final VoidCallback onShare;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final bool missing = installed == false;

    final List<String> facts = <String>[
      if (capabilities.supportsText)
        capabilities.prefillsText ? 'text' : 'text (via clipboard)',
      if (capabilities.supportsUrl) 'link',
      if (capabilities.supportsFiles)
        'files${capabilities.maxFiles == null ? '' : ' ×${capabilities.maxFiles}'}',
      if (capabilities.supportsSubject) 'subject',
      if (capabilities.textLimit != null) '${capabilities.textLimit} chars',
    ];

    return Card(
      margin: const EdgeInsets.only(bottom: 8),
      child: ListTile(
        title: Text(target.id),
        subtitle: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(facts.join(' · ')),
            if (missing)
              Text(
                'not installed',
                style: TextStyle(color: theme.colorScheme.error),
              ),
            if (capabilities.note != null)
              Padding(
                padding: const EdgeInsets.only(top: 4),
                child: Text(
                  capabilities.note!,
                  style: theme.textTheme.bodySmall,
                ),
              ),
          ],
        ),
        isThreeLine: capabilities.note != null,
        trailing: FilledButton(
          // Left enabled even when the app is missing, so the resulting
          // appNotInstalled status is visible in the example.
          onPressed: onShare,
          child: const Text('Share'),
        ),
      ),
    );
  }
}
0
likes
150
points
85
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Share text, links and files directly to X, WhatsApp, Instagram, Threads, Telegram, LinkedIn, Messenger, TikTok, SMS and mail, or to the system share sheet. Reports per-target capabilities up front. Bundles no vendor SDKs.

Repository (GitHub)
View/report issues

Topics

#share #social #sharing #intent

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on social_share_kit

Packages that implement social_share_kit