Syncly

Sistema de sincronização independente e completo para aplicações Flutter com arquitetura moderna e flexível.

Características

  • Sincronização bidirecional (upload/download)
  • Sincronização em background com WorkManager
  • Sistema de tema independente (SyncTheme)
  • Gerenciamento de conectividade automático
  • Sistema de logs e debug configurável
  • Widgets de UI prontos (SyncIndicator, SyncDetailsBottomSheet)
  • Tratamento de erros robusto com retry automático
  • Arquitetura baseada em estratégias (Strategy Pattern)
  • Configuração centralizada via SyncConfig
  • Injeção de dependência com GetIt
  • Sistema de notificações integrado
  • Modo offline com fila de operações
  • Upload de arquivos e mídia
  • Autenticação integrada

Instalação

Como Pacote Local

dependencies:
  syncly:
    path: ../path/to/syncly

Como Dependência Git

dependencies:
  syncly:
    git:
      url: https://github.com/seu-usuario/syncly.git
      ref: main

Uso Básico

1. Implementar SyncConfig

class MeuSyncConfig extends SyncConfig {
  @override
  String get appName => 'Meu App';
  
  @override
  String get appVersion => '1.0.0';
  
  @override
  bool get enableDebugLogs => true;
  
  @override
  Duration get syncInterval => Duration(minutes: 5);
  
  // Implementar métodos HTTP obrigatórios
  @override
  Future<SyncHttpResponse<T>> httpPost<T>(
    String url, {
    dynamic data,
    Map<String, dynamic>? headers,
    Map<String, dynamic>? queryParameters,
    Duration? timeout,
  }) async {
    // Implementar usando Dio, http ou outro cliente
    // Retornar SyncHttpResponse<T>
  }
  
  // Implementar autenticação
  @override
  Future<bool> isAuthenticated() async {
    // Verificar se usuário está autenticado
  }
  
  @override
  Future<String?> getAuthToken() async {
    // Retornar token de autenticação
  }
  
  // Implementar estratégias de download
  @override
  List<IDownloadStrategy> get downloadStrategies => [
    MinhaDownloadStrategy(),
  ];
  
  // Implementar limpeza de dados
  @override
  Future<void> clearLocalData() async {
    // Limpar dados locais antes da sincronização
  }
}

2. Inicializar o Sistema

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Opção 1: Inicializar usando estratégias definidas no SyncConfig
  await SyncInitializer.initialize(MeuSyncConfig());
  
  // Opção 2: Passar estratégias de download diretamente (novo na v0.1.0)
  await SyncInitializer.initialize(
    MeuSyncConfig(),
    downloadStrategies: [
      MeuDownloader(),
      OutroDownloader(),
    ],
  );
  
  runApp(MeuApp());
}

3. Usar os Widgets

class MinhaTela extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Meu App'),
        actions: [
          SyncIndicator(
            onTap: () => SyncDetailsBottomSheet.show(context),
          ),
        ],
      ),
      body: MeuConteudo(),
    );
  }
}

4. Controlar Sincronização

// Forçar sincronização
await SyncConfigurator.syncService.forceSync();

// Verificar status
final syncData = SyncConfigurator.syncService.syncData.value;
print('Status: ${syncData.status}');
print('Itens pendentes: ${syncData.pendingItemsCount}');
print('Online: ${syncData.isOnline}');

// Escutar mudanças de status
SyncConfigurator.syncService.syncData.addListener(() {
  final data = SyncConfigurator.syncService.syncData.value;
  print('Status mudou para: ${data.status}');
});

// Adicionar operações à fila de sincronização
await SyncConfigurator.syncService.addToSyncQueue(
  SyncData(
    id: 'unique-id',
    entityType: 'todo',
    entityId: 'todo-123',
    operation: SyncOperation.create,
    data: {'title': 'Nova tarefa', 'completed': false},
  ),
);

// Parar/iniciar sincronização
await SyncConfigurator.syncService.stopSync();
await SyncConfigurator.syncService.startSync();

// Resetar estado de sincronização
await SyncConfigurator.syncService.resetSyncState();

Configuração Avançada

Tema Personalizado

final meuTema = SyncTheme(
  primary: Colors.blue,
  secondary: Colors.green,
  accent: Colors.orange,
  success: Colors.green,
  error: Colors.red,
  warning: Colors.amber,
  info: Colors.blue,
  surface: Colors.white,
  background: Colors.grey[50]!,
  onPrimary: Colors.white,
  onSecondary: Colors.white,
  onSurface: Colors.black87,
  onBackground: Colors.black87,
);

class MeuSyncConfig extends SyncConfig {
  @override
  SyncTheme? get theme => meuTema;
}

Configurações de Tempo e Comportamento

class MeuSyncConfig extends SyncConfig {
  @override
  bool get enableDebugLogs => true;
  
  @override
  bool get enableBackgroundSync => true;
  
  @override
  bool get enableNotifications => true;
  
  @override
  Duration get syncInterval => Duration(minutes: 5);
  
  @override
  Duration get backgroundSyncInterval => Duration(minutes: 15);
  
  @override
  int get maxRetryAttempts => 3;
  
  @override
  Duration get networkTimeout => Duration(seconds: 30);
  
  @override
  int get maxDataBatchSize => 20;
  
  @override
  int get maxFileBatchSize => 5;
}

Implementação Completa de Autenticação

class MeuSyncConfig extends SyncConfig {
  @override
  Future<bool> isAuthenticated() async {
    final token = await getAuthToken();
    return token != null && token.isNotEmpty;
  }
  
  @override
  Future<String?> getAuthToken() async {
    // Implementar recuperação do token
    return await SecureStorage.getToken();
  }
  
  @override
  Future<Map<String, String>> getAuthHeaders() async {
    final token = await getAuthToken();
    if (token != null) {
      return {'Authorization': 'Bearer $token'};
    }
    return {};
  }
  
  @override
  Future<String?> getCurrentUserId() async {
    // Implementar recuperação do ID do usuário
    return await UserService.getCurrentUserId();
  }
  

}

Sistema de Notificações Simplificado

🎉 Novidade na v0.1.0: O sistema de notificações agora é totalmente gerenciado internamente pelo Syncly!

class MeuSyncConfig extends SyncConfig {
  @override
  bool get enableNotifications => true; // Só isso é necessário!
  
  // ✅ Não é mais necessário implementar:
  // - initializeNotifications()
  // - showNotification()
  // - showProgressNotification()
  // - cancelNotification()
  // - cancelAllNotifications()
  // - areNotificationsEnabled()
}

Benefícios do novo sistema:

  • Menos código: Apenas uma propriedade para habilitar
  • Manutenção automática: Notificações gerenciadas internamente
  • Logs de desenvolvimento: Sistema de debug integrado
  • Compatibilidade: Funciona imediatamente sem configuração adicional

Migração da v0.0.x para v0.1.0:

// ❌ Antes (v0.0.x) - muito código boilerplate
class MeuSyncConfig extends SyncConfig {
  @override
  Future<void> initializeNotifications() async {
    await NotificationService.initialize();
  }
  
  @override
  Future<void> showNotification({...}) async {
    // Implementação manual...
  }
  // ... mais métodos obrigatórios
}

// ✅ Agora (v0.1.0) - simples e direto
class MeuSyncConfig extends SyncConfig {
  @override
  bool get enableNotifications => true;
}

Estratégias de Download Flexíveis

🎉 Novidade na v0.1.0: Agora você pode passar as estratégias de download diretamente no método initialize()!

Opção 1: Definir no SyncConfig (padrão)

class MeuSyncConfig extends SyncConfig {
  @override
  List<IDownloadStrategy> get downloadStrategies => [
    TodoDownloader(),
    UserDownloader(),
    FileDownloader(),
  ];
}

// Inicializar
await SyncInitializer.initialize(MeuSyncConfig());

Opção 2: Passar diretamente no initialize() (novo)

// Estratégias passadas diretamente - mais flexível!
await SyncInitializer.initialize(
  MeuSyncConfig(),
  downloadStrategies: [
    TodoDownloader(),
    UserDownloader(),
    FileDownloader(),
  ],
);

Benefícios da nova abordagem:

  • Flexibilidade: Diferentes estratégias para diferentes contextos
  • Testabilidade: Fácil de mockar estratégias em testes
  • Modularidade: Estratégias podem ser definidas em módulos separados
  • Compatibilidade: Funciona com a abordagem anterior

Quando usar cada opção:

  • SyncConfig: Quando as estratégias são fixas para toda a aplicação
  • initialize(): Quando você precisa de flexibilidade ou estratégias dinâmicas

Arquitetura

O Syncly utiliza uma arquitetura moderna baseada em camadas com injeção de dependência:

┌─────────────────────────────────────────────────────────────┐
│                        APP LAYER                           │
│  ┌─────────────────┐    ┌─────────────────┐                │
│  │   SyncConfig    │    │  UI Widgets     │                │
│  │ (User Implementation) │ (SyncIndicator) │                │
│  └─────────────────┘    └─────────────────┘                │
└─────────────────────────────────────────────────────────────┘
                           │
┌─────────────────────────────────────────────────────────────┐
│                    CONFIGURATION LAYER                     │
│  ┌─────────────────┐    ┌─────────────────┐                │
│  │SyncConfigurator │    │ SyncInitializer │                │
│  │ (Central Config)│    │ (Initialization)│                │
│  └─────────────────┘    └─────────────────┘                │
└─────────────────────────────────────────────────────────────┘
                           │
┌─────────────────────────────────────────────────────────────┐
│                      SERVICE LAYER                         │
│  ┌─────────────────┐    ┌─────────────────┐                │
│  │   SyncService   │    │ Background Sync │                │
│  │ (Main Logic)    │    │    Service      │                │
│  └─────────────────┘    └─────────────────┘                │
└─────────────────────────────────────────────────────────────┘
                           │
┌─────────────────────────────────────────────────────────────┐
│                     STRATEGY LAYER                         │
│  ┌─────────────────┐    ┌─────────────────┐                │
│  │ Upload Strategy │    │Download Strategy│                │
│  │ (Queue & Retry) │    │ (Data Fetching) │                │
│  └─────────────────┘    └─────────────────┘                │
└─────────────────────────────────────────────────────────────┘
                           │
┌─────────────────────────────────────────────────────────────┐
│                      CORE LAYER                            │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────┐ │
│  │ Connectivity    │  │ Error Manager   │  │ Log Manager │ │
│  │ Service         │  │ & Reporter      │  │ & Storage   │ │
│  └─────────────────┘  └─────────────────┘  └─────────────┘ │
└─────────────────────────────────────────────────────────────┘

Principais Componentes

  • SyncConfig: Interface que o usuário implementa com todas as configurações
  • SyncConfigurator: Gerencia a configuração central e injeção de dependência
  • SyncService: Lógica principal de sincronização com controle de estado
  • Strategies: Padrão Strategy para upload/download personalizáveis
  • Core Services: Serviços internos (conectividade, logs, erros, storage)
  • UI Components: Widgets prontos para uso (indicadores, detalhes, etc.)

Dependências

O Syncly utiliza as seguintes dependências principais:

  • flutter: SDK Flutter (>=3.10.0)
  • dio (^5.8.0+1): Cliente HTTP robusto para requisições de rede
  • get_it (^8.0.3): Injeção de dependência e service locator
  • workmanager (^0.8.0): Execução de tarefas em background
  • shared_preferences (^2.5.3): Armazenamento local de configurações
  • uuid (^4.5.1): Geração de identificadores únicos

Dependências de Desenvolvimento

  • flutter_test: Framework de testes do Flutter
  • flutter_lints (^6.0.0): Regras de linting recomendadas

Compatibilidade

  • Dart SDK: >=3.0.0 <4.0.0
  • Flutter: >=3.10.0
  • Plataformas: Android, iOS, Web, Desktop

Licença

MIT License - veja o arquivo LICENSE para detalhes.

Libraries

background_sync_service
core/config/sync_constants
core/contracts/sync_model_syncable
core/entities/sync_connectivity_status
core/entities/sync_data
core/entities/sync_error
core/entities/sync_http_exception
core/entities/sync_http_response
core/entities/sync_log
core/entities/sync_log_debug
core/entities/sync_logger_debug_config
core/enums/sync_batch_type
core/enums/sync_connectivity_type
core/enums/sync_http_exception_type
core/enums/sync_log_debug_level
core/enums/sync_operation
core/enums/sync_status
core/interfaces/i_download_strategy
core/interfaces/i_logger_debug_provider
core/interfaces/i_logger_provider
core/interfaces/i_storage_provider
core/interfaces/i_sync_log_manager
core/interfaces/i_sync_service
core/presentation/controllers/sync_indicator_controller
core/presentation/utils/sync_dialogs
core/presentation/utils/sync_icon_builder
core/presentation/utils/sync_status_helpers
core/presentation/widgets/sync_details_bottom_sheet
core/presentation/widgets/sync_indicator
core/providers/default_sync_logger_provider
core/services/storage_service
core/services/sync_connectivity_service
core/services/sync_data_cleanup_service
core/services/sync_error_manager
core/services/sync_error_reporter
core/services/sync_log_manager
core/services/sync_logger_service
core/services/sync_notification_service
core/theme/sync_theme
core/utils/sync_utils
strategies/sync_download_strategy
strategies/sync_upload_strategy
sync
Sistema de Sincronização Syncly
sync_config
sync_configurator
sync_initializer
sync_service