userjot_flutter 0.0.1 copy "userjot_flutter: ^0.0.1" to clipboard
userjot_flutter: ^0.0.1 copied to clipboard

A Flutter package that ports the Swift UserJot SDK functionality for both Android and iOS.

example/lib/main.dart

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize UserJot with your project ID
  // Replace 'your-project-id' with your actual UserJot project ID
  await UserJot.setup('your-project-id');
  
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'UserJot Flutter Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const UserJotExamplePage(),
    );
  }
}

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

  @override
  State<UserJotExamplePage> createState() => _UserJotExamplePageState();
}

class _UserJotExamplePageState extends State<UserJotExamplePage> {
  final TextEditingController _projectIdController = TextEditingController(text: 'your-project-id');
  final TextEditingController _userIdController = TextEditingController(text: 'user123');
  final TextEditingController _emailController = TextEditingController(text: 'user@example.com');
  final TextEditingController _firstNameController = TextEditingController(text: 'John');
  final TextEditingController _lastNameController = TextEditingController(text: 'Doe');
  final TextEditingController _boardController = TextEditingController();
  
  bool _isIdentified = false;
  PresentationStyle _selectedStyle = PresentationStyle.sheet;

  @override
  void dispose() {
    _projectIdController.dispose();
    _userIdController.dispose();
    _emailController.dispose();
    _firstNameController.dispose();
    _lastNameController.dispose();
    _boardController.dispose();
    super.dispose();
  }

  Future<void> _setupUserJot() async {
    final projectId = _projectIdController.text.trim();
    if (projectId.isEmpty) {
      _showSnackBar('Please enter a project ID');
      return;
    }
    
    try {
      await UserJot.setup(projectId);
      _showSnackBar('UserJot setup successful!');
    } catch (e) {
      _showSnackBar('Setup failed: $e');
    }
  }

  void _identifyUser() {
    final userId = _userIdController.text.trim();
    if (userId.isEmpty) {
      _showSnackBar('Please enter a user ID');
      return;
    }

    UserJot.identify(
      userId: userId,
      email: _emailController.text.trim().isEmpty ? null : _emailController.text.trim(),
      firstName: _firstNameController.text.trim().isEmpty ? null : _firstNameController.text.trim(),
      lastName: _lastNameController.text.trim().isEmpty ? null : _lastNameController.text.trim(),
    );

    setState(() {
      _isIdentified = true;
    });
    _showSnackBar('User identified: $userId');
  }

  void _logout() {
    UserJot.logout();
    setState(() {
      _isIdentified = false;
    });
    _showSnackBar('User logged out');
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('UserJot Flutter Example'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Setup Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Setup',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _projectIdController,
                      decoration: const InputDecoration(
                        labelText: 'Project ID',
                        border: OutlineInputBorder(),
                        hintText: 'Enter your UserJot project ID',
                      ),
                    ),
                    const SizedBox(height: 8),
                    ElevatedButton(
                      onPressed: _setupUserJot,
                      child: const Text('Setup UserJot'),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            // User Identification Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Text(
                          'User Identification',
                          style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                        ),
                        if (_isIdentified)
                          Chip(
                            label: const Text('Identified'),
                            backgroundColor: Colors.green[100],
                          ),
                      ],
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _userIdController,
                      decoration: const InputDecoration(
                        labelText: 'User ID *',
                        border: OutlineInputBorder(),
                      ),
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _emailController,
                      decoration: const InputDecoration(
                        labelText: 'Email',
                        border: OutlineInputBorder(),
                      ),
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _firstNameController,
                      decoration: const InputDecoration(
                        labelText: 'First Name',
                        border: OutlineInputBorder(),
                      ),
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _lastNameController,
                      decoration: const InputDecoration(
                        labelText: 'Last Name',
                        border: OutlineInputBorder(),
                      ),
                    ),
                    const SizedBox(height: 8),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton(
                            onPressed: _identifyUser,
                            child: const Text('Identify User'),
                          ),
                        ),
                        if (_isIdentified) ...[
                          const SizedBox(width: 8),
                          Expanded(
                            child: OutlinedButton(
                              onPressed: _logout,
                              child: const Text('Logout'),
                            ),
                          ),
                        ],
                      ],
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            // Presentation Style Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Presentation Style',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    SegmentedButton<PresentationStyle>(
                      segments: const [
                        ButtonSegment(
                          value: PresentationStyle.sheet,
                          label: Text('Sheet'),
                        ),
                        ButtonSegment(
                          value: PresentationStyle.mediumSheet,
                          label: Text('Medium Sheet'),
                        ),
                      ],
                      selected: {_selectedStyle},
                      onSelectionChanged: (Set<PresentationStyle> newSelection) {
                        setState(() {
                          _selectedStyle = newSelection.first;
                        });
                      },
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            // Actions Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Actions',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _boardController,
                      decoration: const InputDecoration(
                        labelText: 'Board Name (optional)',
                        border: OutlineInputBorder(),
                        hintText: 'Leave empty for default board',
                      ),
                    ),
                    const SizedBox(height: 16),
                    ElevatedButton.icon(
                      onPressed: () {
                        final board = _boardController.text.trim().isEmpty
                            ? null
                            : _boardController.text.trim();
                        UserJot.showFeedback(
                          context,
                          board: board,
                          presentationStyle: _selectedStyle,
                        );
                      },
                      icon: const Icon(Icons.feedback),
                      label: const Text('Show Feedback'),
                      style: ElevatedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                    const SizedBox(height: 8),
                    ElevatedButton.icon(
                      onPressed: () {
                        UserJot.showRoadmap(
                          context,
                          presentationStyle: _selectedStyle,
                        );
                      },
                      icon: const Icon(Icons.map),
                      label: const Text('Show Roadmap'),
                      style: ElevatedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                    const SizedBox(height: 8),
                    ElevatedButton.icon(
                      onPressed: () {
                        UserJot.showChangelog(
                          context,
                          presentationStyle: _selectedStyle,
                        );
                      },
                      icon: const Icon(Icons.update),
                      label: const Text('Show Changelog'),
                      style: ElevatedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            // URL Generation Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'URL Generation',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    const Text(
                      'Get URLs for custom WebView implementations:',
                      style: TextStyle(fontSize: 14),
                    ),
                    const SizedBox(height: 8),
                    OutlinedButton.icon(
                      onPressed: () {
                        final url = UserJot.feedbackURL(
                          board: _boardController.text.trim().isEmpty
                              ? null
                              : _boardController.text.trim(),
                        );
                        _showURLDialog('Feedback URL', url);
                      },
                      icon: const Icon(Icons.link),
                      label: const Text('Get Feedback URL'),
                      style: OutlinedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                    const SizedBox(height: 8),
                    OutlinedButton.icon(
                      onPressed: () {
                        final url = UserJot.roadmapURL();
                        _showURLDialog('Roadmap URL', url);
                      },
                      icon: const Icon(Icons.link),
                      label: const Text('Get Roadmap URL'),
                      style: OutlinedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                    const SizedBox(height: 8),
                    OutlinedButton.icon(
                      onPressed: () {
                        final url = UserJot.changelogURL();
                        _showURLDialog('Changelog URL', url);
                      },
                      icon: const Icon(Icons.link),
                      label: const Text('Get Changelog URL'),
                      style: OutlinedButton.styleFrom(
                        minimumSize: const Size(double.infinity, 48),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showURLDialog(String title, Uri? url) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(title),
        content: SelectableText(
          url?.toString() ?? 'URL not available. Make sure UserJot.setup() has been called.',
          style: const TextStyle(fontSize: 12),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
178
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package that ports the Swift UserJot SDK functionality for both Android and iOS.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, http, webview_flutter

More

Packages that depend on userjot_flutter