mirror of
https://github.com/Dvorinka/1356.git
synced 2026-06-05 04:22:55 +00:00
feat: Complete Phase 1 - Full Flutter app implementation with comprehensive features
Version: 1.1.0 Major changes: - Implemented complete Flutter app structure with all core features - Added comprehensive UI screens for auth, countdown, goals, profile, settings, and social features - Integrated Supabase backend with authentication and data repositories - Added offline support with Hive caching and local storage - Implemented comprehensive routing with go_router - Added location services with Google Maps integration - Implemented notifications and home widget support - Added voice recording capabilities and AI chat features - Created comprehensive test suite and documentation - Added Android and iOS platform configurations - Implemented achievements system and social features - Added calendar integration and bucket list functionality This represents a complete Phase 1 milestone with 3,775 additions across 31 files.
This commit is contained in:
@@ -1,160 +1,470 @@
|
||||
// ignore_for_file: deprecated_member_use
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class AppTheme {
|
||||
static const Color primaryColor = Color(0xFF6366F1);
|
||||
static const Color secondaryColor = Color(0xFF8B5CF6);
|
||||
static const Color accentColor = Color(0xFFEC4899);
|
||||
static const Color backgroundColor = Color(0xFFFAFAFA);
|
||||
static const Color primaryColor = Color(0xFF111827);
|
||||
static const Color secondaryColor = Color(0xFF4B5563);
|
||||
static const Color accentColor = Color(0xFF38BDF8);
|
||||
static const Color backgroundColor = Color(0xFFF5F5F5);
|
||||
static const Color surfaceColor = Color(0xFFFFFFFF);
|
||||
static const Color errorColor = Color(0xFFEF4444);
|
||||
static const Color warningColor = Color(0xFFF59E0B);
|
||||
static const Color successColor = Color(0xFF10B981);
|
||||
|
||||
static const Color pastelBlue = Color(0xFFBFDBFE);
|
||||
static const Color pastelGreen = Color(0xFFBBF7D0);
|
||||
static const Color pastelPurple = Color(0xFFDDD6FE);
|
||||
static const Color pastelPink = Color(0xFFFBCFE8);
|
||||
static const Color pastelYellow = Color(0xFFFDE68A);
|
||||
|
||||
static const Color neonGreen = Color(0xFF39FF14);
|
||||
static const Color neonBlue = Color(0xFF00F0FF);
|
||||
static const Color neonPink = Color(0xFFFF10F0);
|
||||
|
||||
static const ColorScheme lightColorScheme = ColorScheme(
|
||||
brightness: Brightness.light,
|
||||
primary: primaryColor,
|
||||
onPrimary: Color(0xFFFFFFFF),
|
||||
secondary: secondaryColor,
|
||||
onSecondary: Color(0xFFFFFFFF),
|
||||
secondary: accentColor,
|
||||
onSecondary: Color(0xFF111827),
|
||||
error: errorColor,
|
||||
onError: Color(0xFFFFFFFF),
|
||||
surface: surfaceColor,
|
||||
onSurface: Color(0xFF1F2937),
|
||||
onSurface: Color(0xFF111827),
|
||||
background: backgroundColor,
|
||||
onBackground: Color(0xFF1F2937),
|
||||
onBackground: Color(0xFF111827),
|
||||
);
|
||||
|
||||
static const ColorScheme darkColorScheme = ColorScheme(
|
||||
brightness: Brightness.dark,
|
||||
primary: primaryColor,
|
||||
onPrimary: Color(0xFFFFFFFF),
|
||||
secondary: secondaryColor,
|
||||
onSecondary: Color(0xFFFFFFFF),
|
||||
primary: accentColor,
|
||||
onPrimary: Color(0xFF020617),
|
||||
secondary: accentColor,
|
||||
onSecondary: Color(0xFF020617),
|
||||
error: errorColor,
|
||||
onError: Color(0xFFFFFFFF),
|
||||
surface: Color(0xFF1F2937),
|
||||
onSurface: Color(0xFFF9FAFB),
|
||||
background: Color(0xFF111827),
|
||||
onBackground: Color(0xFFF9FAFB),
|
||||
surface: Color(0xFF020617),
|
||||
onSurface: Color(0xFFE5E7EB),
|
||||
background: Color(0xFF020617),
|
||||
onBackground: Color(0xFFE5E7EB),
|
||||
);
|
||||
|
||||
static ThemeData get light {
|
||||
final textTheme = _buildLightTextTheme();
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
colorScheme: lightColorScheme,
|
||||
scaffoldBackgroundColor: backgroundColor,
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: surfaceColor,
|
||||
foregroundColor: Color(0xFF1F2937),
|
||||
foregroundColor: Color(0xFF111827),
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
color: surfaceColor,
|
||||
elevation: 2,
|
||||
elevation: 0,
|
||||
margin: const EdgeInsets.all(0),
|
||||
shadowColor: Colors.black.withValues(alpha: 0.06),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
height: 72,
|
||||
backgroundColor: surfaceColor,
|
||||
indicatorColor: primaryColor.withValues(alpha: 0.14),
|
||||
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||
iconTheme: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
final color = states.contains(MaterialState.selected)
|
||||
? const Color(0xFF111827)
|
||||
: const Color(0xFF9CA3AF);
|
||||
return IconThemeData(
|
||||
color: color,
|
||||
size: 24,
|
||||
);
|
||||
},
|
||||
),
|
||||
labelTextStyle: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
final color = states.contains(MaterialState.selected)
|
||||
? const Color(0xFF111827)
|
||||
: const Color(0xFF9CA3AF);
|
||||
return GoogleFonts.spaceGrotesk(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: color,
|
||||
letterSpacing: 0.2,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Color(0xFFFFFFFF),
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 14),
|
||||
textStyle: GoogleFonts.spaceGrotesk(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.4,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
),
|
||||
),
|
||||
textTheme: const TextTheme(
|
||||
displayLarge: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF1F2937),
|
||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: surfaceColor,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
displayMedium: TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF1F2937),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
headlineLarge: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1F2937),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide:
|
||||
BorderSide(color: primaryColor.withValues(alpha: 0.7), width: 1.5),
|
||||
),
|
||||
headlineMedium: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1F2937),
|
||||
),
|
||||
bodyLarge: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Color(0xFF4B5563),
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF6B7280),
|
||||
hintStyle: textTheme.bodyMedium?.copyWith(
|
||||
color: const Color(0xFF9CA3AF),
|
||||
),
|
||||
),
|
||||
chipTheme: ChipThemeData.fromDefaults(
|
||||
secondaryColor: primaryColor,
|
||||
brightness: Brightness.light,
|
||||
labelStyle: textTheme.bodyMedium!,
|
||||
).copyWith(
|
||||
backgroundColor: const Color(0xFFF3F4F6),
|
||||
selectedColor: primaryColor.withValues(alpha: 0.16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
),
|
||||
textTheme: textTheme,
|
||||
);
|
||||
}
|
||||
|
||||
static ThemeData get dark {
|
||||
final textTheme = _buildDarkTextTheme();
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.dark,
|
||||
colorScheme: darkColorScheme,
|
||||
scaffoldBackgroundColor: darkColorScheme.background,
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Color(0xFF1F2937),
|
||||
backgroundColor: Color(0xFF020617),
|
||||
foregroundColor: Color(0xFFF9FAFB),
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
color: const Color(0xFF374151),
|
||||
elevation: 2,
|
||||
color: const Color(0xFF020617),
|
||||
elevation: 0,
|
||||
margin: const EdgeInsets.all(0),
|
||||
shadowColor: Colors.black.withValues(alpha: 0.4),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
height: 72,
|
||||
backgroundColor: const Color(0xFF020617),
|
||||
indicatorColor: primaryColor.withValues(alpha: 0.18),
|
||||
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||
iconTheme: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
final color = states.contains(MaterialState.selected)
|
||||
? primaryColor
|
||||
: const Color(0xFF6B7280);
|
||||
return IconThemeData(
|
||||
color: color,
|
||||
size: 24,
|
||||
);
|
||||
},
|
||||
),
|
||||
labelTextStyle: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
final color = states.contains(MaterialState.selected)
|
||||
? primaryColor
|
||||
: const Color(0xFF9CA3AF);
|
||||
return GoogleFonts.spaceGrotesk(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: color,
|
||||
letterSpacing: 0.2,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Color(0xFFFFFFFF),
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: const Color(0xFF020617),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 14),
|
||||
textStyle: GoogleFonts.spaceGrotesk(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.4,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
),
|
||||
),
|
||||
textTheme: const TextTheme(
|
||||
displayLarge: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFFF9FAFB),
|
||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Color(0xFF020617),
|
||||
elevation: 0,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: const Color(0xFF020617),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
displayMedium: TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFFF9FAFB),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
headlineLarge: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFFF9FAFB),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
borderSide:
|
||||
BorderSide(color: primaryColor.withValues(alpha: 0.7), width: 1.5),
|
||||
),
|
||||
headlineMedium: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFFF9FAFB),
|
||||
hintStyle: textTheme.bodyMedium?.copyWith(
|
||||
color: const Color(0xFF6B7280),
|
||||
),
|
||||
bodyLarge: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Color(0xFFD1D5DB),
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF9CA3AF),
|
||||
),
|
||||
chipTheme: ChipThemeData.fromDefaults(
|
||||
secondaryColor: primaryColor,
|
||||
brightness: Brightness.dark,
|
||||
labelStyle: textTheme.bodyMedium!,
|
||||
).copyWith(
|
||||
backgroundColor: const Color(0xFF020617),
|
||||
selectedColor: primaryColor.withValues(alpha: 0.18),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
),
|
||||
progressIndicatorTheme: ProgressIndicatorThemeData(
|
||||
color: primaryColor,
|
||||
linearTrackColor: primaryColor.withValues(alpha: 0.2),
|
||||
circularTrackColor: primaryColor.withValues(alpha: 0.2),
|
||||
),
|
||||
textTheme: textTheme,
|
||||
);
|
||||
}
|
||||
|
||||
static TextTheme _buildLightTextTheme() {
|
||||
const primary = Color(0xFF111827);
|
||||
const secondary = Color(0xFF4B5563);
|
||||
const muted = Color(0xFF9CA3AF);
|
||||
|
||||
return TextTheme(
|
||||
displayLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 56,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -1.5,
|
||||
color: primary,
|
||||
),
|
||||
displayMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 44,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.8,
|
||||
color: primary,
|
||||
),
|
||||
displaySmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 34,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.4,
|
||||
color: primary,
|
||||
),
|
||||
headlineLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: primary,
|
||||
),
|
||||
headlineMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
headlineSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
titleLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
titleMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primary,
|
||||
),
|
||||
titleSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primary,
|
||||
),
|
||||
bodyLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: secondary,
|
||||
),
|
||||
bodyMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: secondary,
|
||||
),
|
||||
bodySmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.4,
|
||||
color: muted,
|
||||
),
|
||||
labelLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.4,
|
||||
color: primary,
|
||||
),
|
||||
labelMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0.3,
|
||||
color: secondary,
|
||||
),
|
||||
labelSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0.2,
|
||||
color: muted,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static TextTheme _buildDarkTextTheme() {
|
||||
const primary = Color(0xFFF9FAFB);
|
||||
const secondary = Color(0xFFD1D5DB);
|
||||
const muted = Color(0xFF9CA3AF);
|
||||
|
||||
return TextTheme(
|
||||
displayLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 56,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -1.5,
|
||||
color: primary,
|
||||
),
|
||||
displayMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 44,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.8,
|
||||
color: primary,
|
||||
),
|
||||
displaySmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 34,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.4,
|
||||
color: primary,
|
||||
),
|
||||
headlineLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: primary,
|
||||
),
|
||||
headlineMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
headlineSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
titleLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: primary,
|
||||
),
|
||||
titleMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primary,
|
||||
),
|
||||
titleSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primary,
|
||||
),
|
||||
bodyLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: secondary,
|
||||
),
|
||||
bodyMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.5,
|
||||
color: secondary,
|
||||
),
|
||||
bodySmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.4,
|
||||
color: muted,
|
||||
),
|
||||
labelLarge: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.4,
|
||||
color: primary,
|
||||
),
|
||||
labelMedium: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0.3,
|
||||
color: secondary,
|
||||
),
|
||||
labelSmall: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0.2,
|
||||
color: muted,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user