tenzor 5.1.0 copy "tenzor: ^5.1.0" to clipboard
tenzor: ^5.1.0 copied to clipboard

A comprehensive Flutter utility & UI toolkit containing widgets, utilities, helpers, and integrations for rapid development.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:file_picker/file_picker.dart';
// Tüm Tenzor bileşenlerini içe aktar
import 'package:tenzor/tenzor.dart';

Future<void> main() async {
  // Flutter binding'lerini başlat
  WidgetsFlutterBinding.ensureInitialized();
  
  // Firebase'i başlat - Sadece kendi Firebase projenizin konfigürasyonunu eklemeniz yeterli
  await Firebase.initializeApp();
  
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tenzor Firebase Örneği',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const AuthPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

// Firebase ile Giriş/Kayıt Sayfası Örneği
class AuthPage extends StatefulWidget {
  const AuthPage({super.key});

  @override
  State<AuthPage> createState() => _AuthPageState();
}

class _AuthPageState extends State<AuthPage> {
  // Tenzor'un Firebase servisini oluştur
  final _firebase = TenzorFirebaseService();
  
  // Form kontrolleri
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  final _nameController = TextEditingController();
  
  bool _isLogin = true;
  bool _isLoading = false;

  // Giriş yapma fonksiyonu
  Future<void> _submit() async {
    setState(() => _isLoading = true);
    
    if (_isLogin) {
      // Giriş yap
      final result = await _firebase.signInWithEmailAndPassword(
        email: _emailController.text.trim(),
        password: _passwordController.text.trim(),
      );
      
      if (result is TenzorSuccess<UserCredential>) {
        if (mounted) {
          // Giriş başarılı, ana sayfaya yönlendir
          TenzorSnackbar.success(context, "Giriş başarılı!");
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(builder: (context) => const HomePage()),
          );
        }
      } else if (result is TenzorFailure) {
        if (mounted) {
          TenzorSnackbar.error(context, "Hata: ${result.errorOrNull}");
        }
      }
    } else {
      // Kayıt ol
      final result = await _firebase.registerWithEmailAndPassword(
        email: _emailController.text.trim(),
        password: _passwordController.text.trim(),
        displayName: _nameController.text.trim(),
        additionalData: {
          "createdAt": DateTime.now().toIso8601String(),
        },
      );
      
      if (result is TenzorSuccess<UserCredential>) {
        if (mounted) {
          TenzorSnackbar.success(context, "Kayıt başarılı!");
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(builder: (context) => const HomePage()),
          );
        }
      } else if (result is TenzorFailure) {
        if (mounted) {
          TenzorSnackbar.error(context, "Hata: ${result.error}");
        }
      }
    }
    
    setState(() => _isLoading = false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_isLogin ? "Giriş Yap" : "Kayıt Ol"),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Logo/Başlık
            const Icon(
              Icons.flutter_dash,
              size: 80,
              color: Colors.blue,
            ),
            const SizedBox(height: 32),
            
            // İsim alanı (sadece kayıt sırasında göster)
            if (!_isLogin)
              TenzorTextField(
                controller: _nameController,
                labelText: "Ad Soyad",
                prefixIcon: const Icon(Icons.person),
              ),
            if (!_isLogin) const SizedBox(height: 16),
            
            // Email alanı
            TenzorEmailField(
              controller: _emailController,
              labelText: "E-posta",
            ),
            const SizedBox(height: 16),
            
            // Şifre alanı
            TenzorPasswordField(
              controller: _passwordController,
              labelText: "Şifre",
            ),
            const SizedBox(height: 24),
            
            // Gönder butonu
            TenzorLoadingButton(
              onPressed: _submit,
              text: _isLogin ? "Giriş Yap" : "Kayıt Ol",
              isLoading: _isLoading,
            ),
            const SizedBox(height: 16),
            
            // Mod değiştirme butonu
            TextButton(
              onPressed: () {
                setState(() {
                  _isLogin = !_isLogin;
                });
              },
              child: Text(
                _isLogin
                    ? "Hesabınız yok mu? Kayıt olun"
                    : "Zaten hesabınız var mı? Giriş yapın",
              ),
            ),
            
            // Şifremi unuttum butonu (sadece giriş ekranında)
            if (_isLogin)
              TextButton(
                onPressed: () async {
                  if (_emailController.text.isNotEmpty) {
                    await _firebase.auth.sendPasswordResetEmail(
                      _emailController.text.trim(),
                    );
                    if (mounted) {
                      TenzorAlert.show(
                        context,
                        title: "Şifre Sıfırlama",
                        message: "Şifre sıfırlama bağlantısı e-posta adresinize gönderildi.",
                      );
                    }
                  } else {
                    showDialog(
                      context: context,
                      builder: (context) => const ResetPasswordDialog(),
                    );
                  }
                },
                child: const Text("Şifremi unuttum"),
              ),

            const SizedBox(height: 24),
            // Ayraç çizgisi
            const Row(
              children: [
                Expanded(child: Divider()),
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 16),
                  child: Text("veya"),
                ),
                Expanded(child: Divider()),
              ],
            ),
            const SizedBox(height: 24),

            // Sosyal giriş butonları
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // Google ile giriş
                IconButton(
                  icon: Image.asset(
                    'assets/google_logo.png',
                    height: 40,
                    width: 40,
                    errorBuilder: (context, error, stackTrace) {
                      return const Icon(Icons.g_mobiledata, size: 40, color: Colors.blue);
                    },
                  ),
                  onPressed: _isLoading ? null : () async {
                    setState(() => _isLoading = true);
                    final result = await _firebase.signInWithGoogle();
                    
                    if (result is TenzorSuccess<UserCredential> && mounted) {
                      TenzorSnackbar.success(context, "Google ile giriş başarılı!");
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(builder: (context) => const HomePage()),
                      );
                    } else if (result is TenzorFailure && mounted) {
                      TenzorSnackbar.error(context, "Hata: ${result.error}");
                    }
                    
                    setState(() => _isLoading = false);
                  },
                  tooltip: "Google ile giriş yap",
                ),
                const SizedBox(width: 32),
                // Apple ile giriş
                IconButton(
                  icon: const Icon(Icons.apple, size: 40, color: Colors.black),
                  onPressed: _isLoading ? null : () async {
                    setState(() => _isLoading = true);
                    final result = await _firebase.signInWithApple();
                    
                    if (result is TenzorSuccess<UserCredential> && mounted) {
                      TenzorSnackbar.success(context, "Apple ile giriş başarılı!");
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(builder: (context) => const HomePage()),
                      );
                    } else if (result is TenzorFailure && mounted) {
                      TenzorSnackbar.error(context, "Hata: ${result.error}");
                    }
                    
                    setState(() => _isLoading = false);
                  },
                  tooltip: "Apple ile giriş yap",
                ),
                const SizedBox(width: 32),
                // Telefon ile giriş
                IconButton(
                  icon: const Icon(Icons.phone_android, size: 40, color: Colors.green),
                  onPressed: _isLoading ? null : () {
                    // Telefon ile giriş modalını aç
                    showDialog(
                      context: context,
                      builder: (context) => const PhoneLoginDialog(),
                    );
                  },
                  tooltip: "Telefon ile giriş yap",
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// Giriş sonrası ana sayfa
class HomePage extends StatefulWidget {
  const HomePage({super.key});

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

class _HomePageState extends State<HomePage> {
  final _firebase = TenzorFirebaseService();
  
  // Kullanıcı modeli
  UserModel? _currentUser;

  @override
  void initState() {
    super.initState();
    // Kullanıcı verilerini yükle
    _loadUserData();
  }

  Future<void> _loadUserData() async {
    final result = await _firebase.getCurrentUserData(
      fromMap: (map) => UserModel.fromMap(map!),
    );
    
    if (result is TenzorSuccess<UserModel?>) {
      setState(() {
        _currentUser = result.data;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: TenzorAppBar(
        title: const Text("Ana Sayfa"),
        actions: [
          IconButton(
            icon: const Icon(Icons.edit),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const ProfileEditPage()),
              );
            },
            tooltip: "Profili Düzenle",
          ),
          if (!_firebase.auth.isEmailVerified)
            IconButton(
              icon: const Icon(Icons.mark_email_unread, color: Colors.orange),
              onPressed: () async {
                final result = await _firebase.sendEmailVerification();
                if (result is TenzorSuccess && mounted) {
                  TenzorSnackbar.success(context, "Doğrulama e-postası gönderildi!");
                }
              },
              tooltip: "E-posta Doğrula",
            ),
          IconButton(
            icon: const Icon(Icons.delete_forever, color: Colors.red),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: const Text("Hesabı Sil"),
                  content: const Text("Hesabınızı kalıcı olarak silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.pop(context),
                      child: const Text("İptal"),
                    ),
                    TextButton(
                      onPressed: () async {
                        Navigator.pop(context);
                        final result = await _firebase.deleteAccount();
                        if (result is TenzorSuccess && mounted) {
                          TenzorSnackbar.success(context, "Hesap başarıyla silindi");
                          Navigator.pushReplacement(
                            context,
                            MaterialPageRoute(builder: (context) => const AuthPage()),
                          );
                        } else if (result is TenzorFailure && mounted) {
                          TenzorSnackbar.error(context, "Hata: ${result.error}");
                        }
                      },
                      child: const Text("Sil", style: TextStyle(color: Colors.red)),
                    ),
                  ],
                ),
              );
            },
            tooltip: "Hesabı Sil",
          ),
          IconButton(
            icon: const Icon(Icons.verified_user),
            onPressed: () async {
              await _firebase.auth.sendEmailVerification();
              if (mounted) {
                TenzorSnackbar.show(context, "E-posta doğrulama bağlantısı gönderildi!");
              }
            },
            tooltip: "E-postayı Doğrula",
          ),
          IconButton(
            icon: const Icon(Icons.delete_forever, color: Colors.red),
            onPressed: () async {
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: const Text("Hesabı Sil"),
                  content: const Text("Hesabınızı kalıcı olarak silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.pop(context),
                      child: const Text("İptal"),
                    ),
                    TextButton(
                      onPressed: () async {
                        Navigator.pop(context);
                        await _firebase.deleteAccount();
                        if (mounted) {
                          TenzorSnackbar.show(context, "Hesap başarıyla silindi");
                          Navigator.pushReplacement(
                            context,
                            MaterialPageRoute(builder: (context) => const AuthPage()),
                          );
                        }
                      },
                      child: const Text("Sil", style: TextStyle(color: Colors.red)),
                    ),
                  ],
                ),
              );
            },
            tooltip: "Hesabı Sil",
          ),
          IconButton(
            icon: const Icon(Icons.logout),
            onPressed: () async {
              await _firebase.signOut();
              if (mounted) {
                Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => const AuthPage()),
                );
              }
            },
            tooltip: "Çıkış Yap",
          ),
        ],
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            children: [
              // Kullanıcı bilgileri kartı
              TenzorContextualCard(
                contentItems: [
                  TenzorCardContentItem(
                    id: 'user_info',
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        children: [
                          const CircleAvatar(
                            radius: 40,
                            child: Icon(Icons.person, size: 40),
                          ),
                          const SizedBox(height: 16),
                          Text(
                            "Hoş geldiniz, ${_firebase.auth.currentUser?.displayName ?? 'Kullanıcı'}!",
                            style: const TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          const SizedBox(height: 8),
                          Text(
                            _firebase.auth.currentUser?.email ?? '',
                            style: TextStyle(color: Colors.grey[600]),
                          ),
                          if (_currentUser != null) ...[
                            const SizedBox(height: 16),
                            const Divider(),
                            const SizedBox(height: 16),
                            Text(
                              "Kayıt tarihi: ${_currentUser?.formattedDate ?? 'Bilinmiyor'}",
                              style: const TextStyle(fontSize: 14),
                            ),
                            const SizedBox(height: 8),
                            Text(
                              "Giriş yöntemi: ${_currentUser?.provider ?? 'Bilinmiyor'}",
                              style: const TextStyle(fontSize: 14),
                            ),
                          ],
                        ],
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 32),
              
              // Tüm kullanıcıları listele
              ExpansionTile(
                title: const Text("Tüm Kullanıcılar (Admin)", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                children: [
                  StreamBuilder<QuerySnapshot>(
                    stream: _firebase.getAllUsers(),
                    builder: (context, snapshot) {
                      if (snapshot.hasError) {
                        return const Padding(
                          padding: EdgeInsets.all(16.0),
                          child: Text("Kullanıcılar yüklenemedi"),
                        );
                      }
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return const Padding(
                          padding: EdgeInsets.all(16.0),
                          child: TenzorCircularLoader(),
                        );
                      }
                      final users = snapshot.data?.docs ?? [];
                      return ListView.builder(
                        shrinkWrap: true,
                        physics: const NeverScrollableScrollPhysics(),
                        itemCount: users.length,
                        itemBuilder: (context, index) {
                          final userData = users[index].data() as Map<String, dynamic>;
                          return ListTile(
                            leading: const CircleAvatar(child: Icon(Icons.person)),
                            title: Text(userData['displayName'] ?? "Bilinmeyen Kullanıcı"),
                            subtitle: Text(userData['email'] ?? ""),
                          );
                        },
                      );
                    },
                  ),
                ],
              ),
              const SizedBox(height: 24),
              
              // Firebase servisleri bilgisi
              const Text(
                "Tenzor Firebase Servisleri Aktif!",
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
              ),
              const SizedBox(height: 16),
              const Text(
                "• Auth oturum durumu: Aktif\n• Firestore bağlantısı: Hazır\n• Kullanıcı verileri: Senkronize",
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.grey),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// Şifre sıfırlama dialogu
class ResetPasswordDialog extends StatefulWidget {
  const ResetPasswordDialog({super.key});

  @override
  State<ResetPasswordDialog> createState() => _ResetPasswordDialogState();
}

class _ResetPasswordDialogState extends State<ResetPasswordDialog> {
  final _firebase = TenzorFirebaseService();
  final _emailController = TextEditingController();
  bool _isLoading = false;

  Future<void> _sendResetLink() async {
    setState(() => _isLoading = true);
    final result = await _firebase.sendPasswordResetEmail(
      email: _emailController.text.trim(),
    );
    
    if (result is TenzorSuccess && mounted) {
      Navigator.pop(context);
      TenzorSnackbar.success(context, "Şifre sıfırlama bağlantısı e-postanıza gönderildi!");
    } else if (result is TenzorFailure && mounted) {
      TenzorSnackbar.error(context, "Hata: ${result.error}");
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text("Şifremi Unuttum"),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          TenzorTextField(
                controller: _emailController,
                labelText: "E-posta Adresiniz",
                prefixIcon: const Icon(Icons.email),
                keyboardType: TextInputType.emailAddress,
              ),
          const SizedBox(height: 16),
          TenzorLoadingButton(
              onPressed: _sendResetLink,
              text: "Sıfırlama Bağlantısı Gönder",
              isLoading: _isLoading,
            ),
        ],
      ),
    );
  }
}

// Telefon ile giriş dialogu
class PhoneLoginDialog extends StatefulWidget {
  const PhoneLoginDialog({super.key});

  @override
  State<PhoneLoginDialog> createState() => _PhoneLoginDialogState();
}

class _PhoneLoginDialogState extends State<PhoneLoginDialog> {
  final _firebase = TenzorFirebaseService();
  final _phoneController = TextEditingController();
  final _otpController = TextEditingController();
  String? _verificationId;
  bool _codeSent = false;
  bool _isLoading = false;

  Future<void> _sendOTP() async {
    setState(() => _isLoading = true);
    await _firebase.verifyPhoneNumber(
      phoneNumber: _phoneController.text.trim(),
      onCodeSent: (verificationId) {
        setState(() {
          _verificationId = verificationId;
          _codeSent = true;
          _isLoading = false;
        });
        if (mounted) {
          TenzorSnackbar.show(context, "Doğrulama kodu gönderildi");
        }
      },
      onError: (error) {
        setState(() => _isLoading = false);
        if (mounted) {
          TenzorSnackbar.show(context, "Hata: $error");
        }
      },
    );
  }

  Future<void> _verifyOTP() async {
    if (_verificationId == null) return;
    
    setState(() => _isLoading = true);
    final result = await _firebase.signInWithPhoneNumber(
      verificationId: _verificationId!,
      smsCode: _otpController.text.trim(),
    );

    if (result is TenzorSuccess<UserCredential> && mounted) {
      Navigator.pop(context);
      TenzorSnackbar.success(context, "Telefon ile giriş başarılı!");
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => const HomePage()),
      );
    } else if (result is TenzorFailure && mounted) {
      TenzorSnackbar.error(context, "Hata: ${result.error}");
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text("Telefon ile Giriş"),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          if (!_codeSent)
            TenzorTextField(
              controller: _phoneController,
              labelText: "Telefon Numarası (+90...)",
              prefixIcon: const Icon(Icons.phone),
              keyboardType: TextInputType.phone,
            )
          else
            TenzorTextField(
              controller: _otpController,
              labelText: "Doğrulama Kodu",
              prefixIcon: const Icon(Icons.pin),
              keyboardType: TextInputType.number,
            ),
          const SizedBox(height: 16),
          TenzorLoadingButton(
              onPressed: _codeSent ? _verifyOTP : _sendOTP,
              text: _codeSent ? "Doğrula" : "Kod Gönder",
              isLoading: _isLoading,
            ),
        ],
      ),
    );
  }
}

// Profil düzenleme sayfası
class ProfileEditPage extends StatefulWidget {
  const ProfileEditPage({super.key});

  @override
  State<ProfileEditPage> createState() => _ProfileEditPageState();
}

class _ProfileEditPageState extends State<ProfileEditPage> {
  final _firebase = TenzorFirebaseService();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    _nameController.text = _firebase.auth.currentUserName ?? '';
    _emailController.text = _firebase.auth.currentUserEmail ?? '';
  }

  Future<void> _saveProfile() async {
    setState(() => _isLoading = true);
    final newEmail = _emailController.text.trim();
    final currentEmail = _firebase.auth.currentUserEmail;
    
    // E-posta değiştiyse güncelle
    if (newEmail != currentEmail) {
      await _firebase.auth.updateEmail(newEmail);
    }
    
    // Profili güncelle
    await _firebase.updateProfile(
      displayName: _nameController.text.trim(),
    );
    
    setState(() => _isLoading = false);
    if (mounted) {
      TenzorSnackbar.show(context, "Profil başarıyla güncellendi!");
      Navigator.pop(context);
    }
  }

  Future<void> _pickAndUploadPhoto() async {
    try {
      final result = await FilePicker.platform.pickFiles(
        type: FileType.image,
        allowMultiple: false,
      );
      
      if (result != null && result.files.single.path != null) {
        setState(() => _isLoading = true);
        final uploadResult = await _firebase.uploadProfilePhoto(
          filePath: result.files.single.path!,
        );
        
        if (uploadResult is TenzorSuccess<String> && mounted) {
            TenzorSnackbar.success(context, "Profil fotoğrafı yüklendi");
            setState(() {}); // UI'ı yenile
          } else if (uploadResult is TenzorFailure && mounted) {
            TenzorSnackbar.error(context, "Hata: ${uploadResult.error}");
          }
        setState(() => _isLoading = false);
      }
    } catch (e) {
      if (mounted) {
        TenzorSnackbar.show(context, "Dosya seçilemedi: $e");
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Profili Düzenle")),
      body: Padding(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          children: [
            Stack(
              children: [
                CircleAvatar(
                  radius: 50,
                  backgroundImage: _firebase.auth.currentUser?.photoURL != null
                      ? NetworkImage(_firebase.auth.currentUser!.photoURL!)
                      : null,
                  child: _firebase.auth.currentUser?.photoURL == null
                      ? const Icon(Icons.person, size: 50)
                      : null,
                ),
                Positioned(
                  bottom: 0,
                  right: 0,
                  child: IconButton(
                    icon: const Icon(Icons.camera_alt, color: Colors.blue),
                    onPressed: _isLoading ? null : _pickAndUploadPhoto,
                  ),
                ),
              ],
            ),
            const SizedBox(height: 32),
            TenzorTextField(
              controller: _nameController,
              labelText: "Ad Soyad",
              prefixIcon: const Icon(Icons.person),
            ),
            const SizedBox(height: 16),
            TenzorTextField(
              controller: _emailController,
              labelText: "E-posta",
              prefixIcon: const Icon(Icons.email),
              keyboardType: TextInputType.emailAddress,
            ),
            const SizedBox(height: 24),
            TenzorLoadingButton(
                onPressed: _saveProfile,
                text: "Kaydet",
                isLoading: _isLoading,
              ),
          ],
        ),
      ),
    );
  }
}

// Kullanıcı Modeli
class UserModel {
  final String? email;
  final String? displayName;
  final String? photoURL;
  final DateTime? createdAt;
  final String? provider;

  UserModel.fromMap(Map<String, dynamic> map)
      : email = map['email'],
        displayName = map['displayName'],
        photoURL = map['photoURL'],
        provider = map['provider'],
        createdAt = (map['createdAt'] as Timestamp?)?.toDate();

  String get formattedDate => createdAt != null
      ? "${createdAt!.day}.${createdAt!.month}.${createdAt!.year}"
      : "Bilinmiyor";
}
0
likes
125
points
233
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter utility & UI toolkit containing widgets, utilities, helpers, and integrations for rapid development.

Repository
View/report issues

License

MIT (license)

Dependencies

audio_service, battery_plus, cached_network_image, chopper, cloud_firestore, collection, connectivity_plus, crypto, csv, device_calendar, device_info_plus, dio, drift, file_picker, firebase_auth, firebase_core, firebase_messaging, firebase_storage, fl_chart, floor, flutter, flutter_blue_plus, flutter_email_sender, flutter_keyboard_visibility, flutter_launcher_icons, flutter_local_notifications, flutter_localizations, flutter_native_splash, flutter_pdfview, flutter_phone_direct_caller, flutter_screenutil, flutter_secure_storage, flutter_sound, freezed_annotation, geocoding, geolocator, google_mlkit_face_detection, google_mlkit_image_labeling, google_mlkit_object_detection, google_mlkit_pose_detection, google_mlkit_text_recognition, google_mobile_ads, google_sign_in, hive, http, image_cropper, image_picker, in_app_purchase, intl, json_annotation, just_audio, logger, mobile_scanner, model_viewer_plus, mqtt_client, objectbox, open_file, package_info_plus, path, path_provider, pdf, permission_handler, pretty_dio_logger, printing, provider, qr_flutter, retrofit, sembast, sensors_plus, share_plus, shared_preferences, sign_in_with_apple, sms_autofill, sqflite, tflite_flutter, timezone, url_launcher, vector_math, video_player, wakelock_plus, web3dart, web_socket_channel, xml

More

Packages that depend on tenzor