rar 0.3.0 copy "rar: ^0.3.0" to clipboard
rar: ^0.3.0 copied to clipboard

A Flutter plugin for handling RAR files. Extract and list contents of RAR archives on Android, iOS, macOS, and Web platforms.

example/lib/main.dart

// example/lib/main.dart
//
// RAR Archive Browser - A two-pane file browser for RAR archives.
// Features:
// - Open RAR button to select archives
// - Two-pane layout on wide screens, tabs on narrow screens (<800px)
// - File tree with expandable folders
// - Content viewer for text and images

import 'package:flutter/material.dart';

import 'file_browser.dart';
import 'services/archive_service.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RAR Browser',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.indigo,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      home: const RarBrowserPage(),
    );
  }
}

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

  @override
  State<RarBrowserPage> createState() => _RarBrowserPageState();
}

class _RarBrowserPageState extends State<RarBrowserPage> {
  final _archiveService = ArchiveService();
  FileNode? _root;
  bool _isLoading = false;
  String? _error;
  String? _warning;
  String? _archiveName;
  String? _extractPath;
  String? _password;
  String? _rarVersion;

  @override
  void initState() {
    super.initState();
    _archiveService.requestPermissions();
  }

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

  Future<void> _openRarFile() async {
    setState(() {
      _isLoading = true;
      _error = null;
      _warning = null;
      _rarVersion = null;
    });

    final result = await _archiveService.pickAndOpenArchive(
      password: _password,
    );

    if (result == null) {
      setState(() => _isLoading = false);
      return;
    }

    if (!result.isSuccess) {
      setState(() {
        _error = result.errorMessage ?? 'Failed to open archive';
        _isLoading = false;
      });
      return;
    }

    setState(() {
      _root = FileNode.buildTree(
        result.files,
        rootName: result.archiveName ?? 'Archive',
      );
      _archiveName = result.archiveName;
      _extractPath = result.extractPath;
      _rarVersion = result.rarVersion;
      _warning = result.errorMessage; // Warning message if any
      _isLoading = false;
    });
  }

  void _showPasswordDialog() {
    showDialog(
      context: context,
      builder: (context) {
        String password = _password ?? '';
        return AlertDialog(
          title: const Text('Archive Password'),
          content: TextField(
            obscureText: true,
            decoration: const InputDecoration(
              hintText: 'Enter password (leave empty for none)',
              border: OutlineInputBorder(),
            ),
            onChanged: (value) => password = value,
            controller: TextEditingController(text: _password),
          ),
          actions: [
            TextButton(
              onPressed: () {
                setState(() => _password = null);
                Navigator.pop(context);
              },
              child: const Text('Clear'),
            ),
            FilledButton(
              onPressed: () {
                setState(() => _password = password.isEmpty ? null : password);
                Navigator.pop(context);
              },
              child: const Text('Set'),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_archiveName ?? 'RAR Browser'),
        actions: [
          IconButton(
            icon: Icon(_password != null ? Icons.lock : Icons.lock_open),
            tooltip: 'Set password',
            onPressed: _showPasswordDialog,
          ),
          const SizedBox(width: 8),
          Padding(
            padding: const EdgeInsets.only(right: 8),
            child: FilledButton.icon(
              onPressed: _isLoading ? null : _openRarFile,
              icon: const Icon(Icons.folder_open),
              label: const Text('Open RAR'),
            ),
          ),
        ],
      ),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    if (_isLoading) {
      return const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(),
            SizedBox(height: 16),
            Text('Opening archive...'),
          ],
        ),
      );
    }

    if (_error != null) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.error_outline, size: 64, color: Colors.red.shade300),
            const SizedBox(height: 16),
            Text(_error!, style: TextStyle(color: Colors.red.shade700)),
            const SizedBox(height: 24),
            FilledButton.icon(
              onPressed: _openRarFile,
              icon: const Icon(Icons.folder_open),
              label: const Text('Try Again'),
            ),
          ],
        ),
      );
    }

    if (_root == null) {
      return _buildEmptyState();
    }

    return FileBrowser(
      root: _root!,
      title: _archiveName ?? 'File Browser',
      rarVersion: _rarVersion,
      warning: _warning,
      onLoadContent: (path) async {
        if (_extractPath == null) return null;
        final fullPath = '$_extractPath/$path';
        return _archiveService.loadContent(fullPath);
      },
    );
  }

  Widget _buildEmptyState() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.archive, size: 80, color: Colors.grey.shade400),
          const SizedBox(height: 24),
          Text(
            'RAR Archive Browser',
            style: Theme.of(
              context,
            ).textTheme.headlineSmall?.copyWith(color: Colors.grey.shade600),
          ),
          const SizedBox(height: 8),
          Text(
            'Open a RAR file to browse its contents',
            style: TextStyle(color: Colors.grey.shade500),
          ),
          const SizedBox(height: 32),
          FilledButton.icon(
            onPressed: _openRarFile,
            icon: const Icon(Icons.folder_open),
            label: const Text('Open RAR File'),
          ),
          const SizedBox(height: 16),
          Text(
            'Supports RAR v4 and v5 formats',
            style: TextStyle(color: Colors.grey.shade400, fontSize: 12),
          ),
        ],
      ),
    );
  }
}
2
likes
150
points
133
downloads

Publisher

verified publisherlkrjangid.tech

Weekly Downloads

A Flutter plugin for handling RAR files. Extract and list contents of RAR archives on Android, iOS, macOS, and Web platforms.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

ffi, flutter, plugin_platform_interface, web

More

Packages that depend on rar

Packages that implement rar