Compare commits

..

2 Commits

Author SHA1 Message Date
Claude bb3106434b
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	mobile/lib/screens/conversation_list_screen.dart
#	mobile/pubspec.lock
2026-07-31 08:23:28 +00:00
Claude 79bce5e671
Redesign UI to a bolder aurora-glass system after visual QA with a real Flutter build
Actually installed the Flutter SDK, built the app (web + a local screenshot
harness through a real backend), and looked at the rendered screens instead
of judging the design from source alone. The previous gradient/glassmorphism
pass read as flat and generic: glass cards barely contrasted against the
pale background, the brand mark was a stock sparkle icon, and buttons were
flat solid fills.

Changes:
- Stronger, more saturated aurora gradient + blurred glow orbs in
  GradientBackdrop for real depth instead of a flat 3-stop pastel.
- Glass cards/inputs get higher-contrast fill/border and a brand-tinted
  shadow so they visibly lift off the backdrop.
- New BrandMark (gradient monogram), GradientText (gradient-filled
  wordmark), and PrimaryGradientButton (gradient CTA with shadow) replace
  the generic Material icon/flat button on splash, signup, onboarding and
  the conversation list empty state.
- Fixed a real pre-existing layout bug found via screenshot: the onboarding
  header badge was a direct ListView child with an explicit width, which
  Flutter's sliver list silently stretches to full width regardless of the
  Container's own width — invisible before because its old flat pale fill
  blended into the background. Wrapped it in Align to restore its intended
  size.

Verified with flutter analyze (0 errors) and flutter test (all passing),
plus manual screenshots of signup, onboarding, conversation list and a live
chat exchanged between two demo users through a real core-backend instance.
2026-07-31 08:16:44 +00:00
10 changed files with 300 additions and 101 deletions

View File

@ -4,6 +4,8 @@ import 'package:provider/provider.dart';
import '../models/models.dart';
import '../services/api_client.dart';
import '../state/session_state.dart';
import '../theme/app_theme.dart';
import '../widgets/gradient_text.dart';
import '../widgets/my_user_id_chip.dart';
import 'autonomy_settings_screen.dart';
import 'chat_screen.dart';
@ -172,7 +174,7 @@ class _ConversationListScreenState extends State<ConversationListScreen> {
return Scaffold(
appBar: AppBar(
title: const Text('와카뷰'),
title: GradientText('와카뷰', style: theme.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w800)),
actions: [
if (me != null) MyUserIdChip(userId: me, compact: true),
IconButton(
@ -249,11 +251,26 @@ class _ConversationListScreenState extends State<ConversationListScreen> {
),
if (_rooms.isEmpty)
Padding(
padding: const EdgeInsets.symmetric(vertical: 48, horizontal: 32),
padding: const EdgeInsets.fromLTRB(32, 48, 32, 32),
child: Column(
children: [
Icon(Icons.chat_bubble_outline, size: 40, color: theme.colorScheme.outline),
const SizedBox(height: 12),
Container(
width: 72,
height: 72,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: AppTheme.brandGradient,
boxShadow: [
BoxShadow(
color: const Color(0xFF6D5BD0).withValues(alpha: 0.3),
blurRadius: 24,
offset: const Offset(0, 10),
),
],
),
child: const Icon(Icons.chat_bubble_outline, size: 30, color: Colors.white),
),
const SizedBox(height: 16),
Text('대화방이 없습니다', style: theme.textTheme.titleMedium),
const SizedBox(height: 8),
Text(

View File

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../state/session_state.dart';
import '../theme/app_theme.dart';
import '../widgets/primary_gradient_button.dart';
/// Phase 1 onboarding skeleton: capture a few style samples locally.
/// Fine copy / import UX waits for human PoC (#1) do not invent §3 defaults here.
@ -62,11 +64,20 @@ class _OnboardingToneScreenState extends State<OnboardingToneScreen> {
child: ListView(
padding: const EdgeInsets.all(24),
children: [
Container(
width: 56,
height: 56,
decoration: BoxDecoration(color: scheme.primaryContainer, borderRadius: BorderRadius.circular(16)),
child: Icon(Icons.record_voice_over_outlined, size: 28, color: scheme.onPrimaryContainer),
Align(
alignment: Alignment.centerLeft,
child: Container(
width: 56,
height: 56,
decoration: BoxDecoration(
gradient: AppTheme.brandGradient,
borderRadius: BorderRadius.circular(18),
boxShadow: [
BoxShadow(color: const Color(0xFF6D5BD0).withValues(alpha: 0.3), blurRadius: 18, offset: const Offset(0, 8)),
],
),
child: const Icon(Icons.record_voice_over_outlined, size: 28, color: Colors.white),
),
),
const SizedBox(height: 16),
Text('와카뷰가 따라 쓸 말투', style: theme.textTheme.headlineSmall),
@ -104,9 +115,9 @@ class _OnboardingToneScreenState extends State<OnboardingToneScreen> {
const SizedBox(height: 12),
],
const SizedBox(height: 12),
FilledButton(
PrimaryGradientButton(
label: '이 말투로 시작',
onPressed: () => _save(markDone: true),
child: const Text('이 말투로 시작'),
),
],
),

View File

@ -5,6 +5,9 @@ import 'package:provider/provider.dart';
import '../config.dart';
import '../state/session_state.dart';
import '../theme/app_theme.dart';
import '../widgets/brand_mark.dart';
import '../widgets/gradient_text.dart';
import '../widgets/primary_gradient_button.dart';
class SignupScreen extends StatefulWidget {
const SignupScreen({super.key});
@ -42,20 +45,10 @@ class _SignupScreenState extends State<SignupScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Spacer(flex: 3),
Center(
child: Container(
width: 72,
height: 72,
decoration: BoxDecoration(
color: scheme.primaryContainer,
borderRadius: BorderRadius.circular(22),
),
child: Icon(Icons.auto_awesome, size: 34, color: scheme.onPrimaryContainer),
),
),
const Spacer(flex: 2),
const Center(child: BrandMark(size: 72)),
const SizedBox(height: 20),
Text(
GradientText(
'와카뷰',
textAlign: TextAlign.center,
style: theme.textTheme.displaySmall?.copyWith(fontWeight: FontWeight.w800),
@ -66,7 +59,7 @@ class _SignupScreenState extends State<SignupScreen> {
textAlign: TextAlign.center,
style: theme.textTheme.bodyLarge?.copyWith(color: scheme.onSurfaceVariant),
),
const Spacer(flex: 2),
const Spacer(flex: 1),
Text('초대 코드로 클로즈드 베타에 참여합니다', style: theme.textTheme.labelLarge),
const SizedBox(height: 12),
_DemoTestPanel(
@ -109,13 +102,12 @@ class _SignupScreenState extends State<SignupScreen> {
],
const SizedBox(height: 20),
_PressScale(
child: FilledButton(
child: PrimaryGradientButton(
label: '시작하기',
loading: session.loading,
onPressed: session.loading
? null
: () => session.signup(_invite.text.trim(), _name.text.trim()),
child: session.loading
? const SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))
: const Text('시작하기'),
),
),
const SizedBox(height: 32),
@ -140,7 +132,7 @@ class _DemoTestPanel extends StatelessWidget {
final theme = Theme.of(context);
final brightness = theme.brightness;
return Material(
color: AppTheme.glassFill(brightness),
color: Colors.transparent,
borderRadius: BorderRadius.circular(16),
child: InkWell(
onTap: onFill,
@ -148,8 +140,12 @@ class _DemoTestPanel extends StatelessWidget {
child: Container(
padding: const EdgeInsets.fromLTRB(16, 14, 12, 14),
decoration: BoxDecoration(
color: AppTheme.glassFill(brightness),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppTheme.glassBorder(brightness)),
boxShadow: [
BoxShadow(color: AppTheme.glassShadow(brightness), blurRadius: 20, offset: const Offset(0, 8)),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import '../widgets/brand_mark.dart';
import '../widgets/gradient_text.dart';
/// Shown while `SessionState.restore()` runs, before the real app (signup /
/// onboarding / conversation list) is ready to pick. Purely presentational
/// no navigation logic lives here, `main.dart` swaps it out once restore()
@ -17,31 +20,9 @@ class SplashScreen extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 88,
height: 88,
decoration: BoxDecoration(
color: scheme.primary.withOpacity(0.15),
shape: BoxShape.circle,
),
child: Center(
child: Container(
width: 64,
height: 64,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [scheme.primary, scheme.tertiary],
),
borderRadius: BorderRadius.circular(20),
),
child: const Icon(Icons.auto_awesome, color: Colors.white, size: 30),
),
),
),
const BrandMark(size: 72),
const SizedBox(height: 24),
Text(
GradientText(
'와카뷰',
style: theme.textTheme.headlineSmall?.copyWith(fontWeight: FontWeight.w800),
),

View File

@ -1,46 +1,72 @@
import 'package:flutter/material.dart';
/// Central design tokens for (Ykavu) soft-gradient + glassmorphism
/// direction. `backgroundGradient` paints behind every screen (wired into
/// `MaterialApp.builder`); cards/inputs/app bars are semi-transparent
/// "glass" surfaces that let the gradient read through. `twinAccent` stays a
/// separate warm accent so a twin-written bubble never reads as something
/// the human actually typed (PRD §3.1 ).
/// Central design tokens for (Ykavu) "aurora glass" direction.
/// `backgroundGradient` + the glow orbs in [GradientBackdrop] paint behind
/// every screen (wired into `MaterialApp.builder`); cards/inputs/app bars
/// are semi-transparent "glass" surfaces with a soft colored shadow so they
/// visibly lift off that background. `twinAccent` stays a separate warm
/// accent so a twin-written bubble never reads as something the human
/// actually typed (PRD §3.1 ).
class AppTheme {
AppTheme._();
static const _seed = Color(0xFF7C6FF0);
static const _seed = Color(0xFF6D5BD0);
/// Brand gradient used for the wordmark, brand mark and primary CTAs.
static const brandGradient = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Color(0xFF6D5BD0), Color(0xFFA855C9), Color(0xFFE0609A)],
);
static Color twinAccent(Brightness brightness) =>
brightness == Brightness.dark ? Colors.amber.shade300 : Colors.amber.shade800;
/// Soft diagonal gradient painted behind every screen. Light: pastel
/// lavender sky pink. Dark: desaturated indigo navy plum.
/// Diagonal aurora gradient painted behind every screen. Light: violet
/// sky pink, more saturated than a "safe" pastel so it reads as
/// intentional branding rather than a default Material backdrop. Dark:
/// deep indigo navy plum. Paired with the blurred glow orbs in
/// [GradientBackdrop].
static LinearGradient backgroundGradient(Brightness brightness) {
if (brightness == Brightness.dark) {
return const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF1B1730), Color(0xFF161C34), Color(0xFF2A1830)],
colors: [Color(0xFF201A3D), Color(0xFF16213E), Color(0xFF351C3C)],
);
}
return const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFFEDE9FE), Color(0xFFE0F2FE), Color(0xFFFCE7F3)],
colors: [Color(0xFFDCCBFF), Color(0xFFC3E4FF), Color(0xFFFFC9E8)],
);
}
/// Soft blurred accent blobs layered over [backgroundGradient] by
/// [GradientBackdrop] for depth ("aurora glow").
static Color glowPrimary(Brightness brightness) => brightness == Brightness.dark
? const Color(0xFF8B7CF6).withValues(alpha: 0.35)
: const Color(0xFFB79CFF).withValues(alpha: 0.55);
static Color glowSecondary(Brightness brightness) => brightness == Brightness.dark
? const Color(0xFFE879C4).withValues(alpha: 0.25)
: const Color(0xFFFFA9DC).withValues(alpha: 0.50);
/// "Glass" fill for cards/panels semi-transparent so the gradient
/// behind still reads through, with a faint light border for the classic
/// glassmorphism edge highlight.
/// behind still reads through, with a bright border for the classic
/// glassmorphism edge highlight and a tinted shadow so the surface
/// visibly lifts off the backdrop instead of blending into it.
static Color glassFill(Brightness brightness) => brightness == Brightness.dark
? Colors.white.withOpacity(0.06)
: Colors.white.withOpacity(0.55);
? Colors.white.withValues(alpha: 0.08)
: Colors.white.withValues(alpha: 0.72);
static Color glassBorder(Brightness brightness) => brightness == Brightness.dark
? Colors.white.withOpacity(0.10)
: Colors.white.withOpacity(0.65);
? Colors.white.withValues(alpha: 0.16)
: Colors.white.withValues(alpha: 0.85);
static Color glassShadow(Brightness brightness) => brightness == Brightness.dark
? Colors.black.withValues(alpha: 0.45)
: const Color(0xFF6D5BD0).withValues(alpha: 0.18);
static ThemeData light() => _build(Brightness.light);
static ThemeData dark() => _build(Brightness.dark);
@ -49,6 +75,7 @@ class AppTheme {
final scheme = ColorScheme.fromSeed(seedColor: _seed, brightness: brightness);
final glass = glassFill(brightness);
final glassEdge = glassBorder(brightness);
final glassShadowColor = glassShadow(brightness);
final glassShape = RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18),
side: BorderSide(color: glassEdge, width: 1),
@ -78,7 +105,8 @@ class AppTheme {
),
),
cardTheme: CardThemeData(
elevation: 0,
elevation: 8,
shadowColor: glassShadowColor,
color: glass,
shape: glassShape,
margin: EdgeInsets.zero,
@ -113,7 +141,7 @@ class AppTheme {
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: scheme.error, width: 1.6),
),
hintStyle: TextStyle(color: scheme.onSurfaceVariant.withOpacity(0.7)),
hintStyle: TextStyle(color: scheme.onSurfaceVariant.withValues(alpha: 0.7)),
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
@ -158,7 +186,7 @@ class AppTheme {
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: scheme.primary,
foregroundColor: scheme.onPrimary,
elevation: 1,
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
),
snackBarTheme: SnackBarThemeData(
@ -172,7 +200,7 @@ class AppTheme {
dialogTheme: DialogThemeData(
backgroundColor: brightness == Brightness.dark
? const Color(0xFF211D3D)
: Colors.white.withOpacity(0.92),
: Colors.white.withValues(alpha: 0.95),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
),
progressIndicatorTheme: ProgressIndicatorThemeData(color: scheme.primary),
@ -181,6 +209,7 @@ class AppTheme {
static TextTheme _textTheme() {
return const TextTheme(
displayLarge: TextStyle(fontWeight: FontWeight.w800, letterSpacing: -1.2),
displaySmall: TextStyle(fontWeight: FontWeight.w800, letterSpacing: -0.5),
headlineSmall: TextStyle(fontWeight: FontWeight.w800, letterSpacing: -0.3),
titleLarge: TextStyle(fontWeight: FontWeight.w700),

View File

@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
/// The app icon mark: a gradient-filled rounded badge with a bold
/// "Y" monogram and a soft brand-tinted shadow, used wherever the splash /
/// signup / onboarding screens need a small brand anchor instead of a
/// generic Material icon.
class BrandMark extends StatelessWidget {
const BrandMark({super.key, this.size = 64});
final double size;
@override
Widget build(BuildContext context) {
final radius = size * 0.32;
return Container(
width: size,
height: size,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(radius),
gradient: AppTheme.brandGradient,
boxShadow: [
BoxShadow(
color: const Color(0xFF6D5BD0).withValues(alpha: 0.38),
blurRadius: size * 0.35,
offset: Offset(0, size * 0.12),
),
],
),
alignment: Alignment.center,
child: Text(
'Y',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: size * 0.46,
height: 1,
),
),
);
}
}

View File

@ -1,11 +1,14 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
/// Paints the app-wide soft gradient behind [child]. Wired into
/// `MaterialApp.builder` so every screen gets it automatically without each
/// Scaffold needing its own background screens just need a transparent
/// `scaffoldBackgroundColor` (set globally in [AppTheme]).
/// Paints the app-wide aurora gradient + soft blurred glow orbs behind
/// [child]. Wired into `MaterialApp.builder` so every screen gets it
/// automatically without each Scaffold needing its own background
/// screens just need a transparent `scaffoldBackgroundColor` (set globally
/// in [AppTheme]).
class GradientBackdrop extends StatelessWidget {
const GradientBackdrop({super.key, required this.child});
@ -13,9 +16,44 @@ class GradientBackdrop extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(gradient: AppTheme.backgroundGradient(Theme.of(context).brightness)),
child: child,
final brightness = Theme.of(context).brightness;
return Stack(
fit: StackFit.expand,
children: [
DecoratedBox(decoration: BoxDecoration(gradient: AppTheme.backgroundGradient(brightness))),
Positioned(
top: -90,
right: -70,
child: _Glow(color: AppTheme.glowPrimary(brightness), size: 260),
),
Positioned(
bottom: -110,
left: -90,
child: _Glow(color: AppTheme.glowSecondary(brightness), size: 320),
),
if (child != null) child!,
],
);
}
}
class _Glow extends StatelessWidget {
const _Glow({required this.color, required this.size});
final Color color;
final double size;
@override
Widget build(BuildContext context) {
return IgnorePointer(
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 60, sigmaY: 60),
child: Container(
width: size,
height: size,
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
),
),
);
}
}

View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
/// Renders [text] filled with [AppTheme.brandGradient] instead of a flat
/// color used for the "와카뷰" wordmark so the brand reads as designed
/// rather than default black-on-gradient body text.
class GradientText extends StatelessWidget {
const GradientText(this.text, {super.key, this.style, this.textAlign});
final String text;
final TextStyle? style;
final TextAlign? textAlign;
@override
Widget build(BuildContext context) {
return ShaderMask(
blendMode: BlendMode.srcIn,
shaderCallback: (bounds) => AppTheme.brandGradient.createShader(Rect.fromLTWH(0, 0, bounds.width, bounds.height)),
child: Text(text, style: style, textAlign: textAlign),
);
}
}

View File

@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
/// Primary call-to-action button filled with [AppTheme.brandGradient] and a
/// soft brand-tinted shadow, so the one action per screen that matters most
/// ( / ) visibly outranks the flat glass buttons
/// around it.
class PrimaryGradientButton extends StatelessWidget {
const PrimaryGradientButton({
super.key,
required this.label,
required this.onPressed,
this.loading = false,
});
final String label;
final VoidCallback? onPressed;
final bool loading;
@override
Widget build(BuildContext context) {
final disabled = onPressed == null;
return Opacity(
opacity: disabled ? 0.6 : 1,
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(16),
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: onPressed,
child: Container(
height: 52,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: AppTheme.brandGradient,
boxShadow: [
BoxShadow(
color: const Color(0xFF6D5BD0).withValues(alpha: 0.35),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: loading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white),
)
: Text(
label,
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w700, fontSize: 16),
),
),
),
),
);
}
}

View File

@ -101,10 +101,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.4.1"
charcode:
dependency: transitive
description:
@ -412,26 +412,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@ -452,26 +452,26 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
version: "0.12.17"
version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
url: "https://pub.dev"
source: hosted
version: "1.16.0"
version: "1.18.0"
mime:
dependency: transitive
description:
@ -769,10 +769,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.11"
typed_data:
dependency: transitive
description:
@ -785,10 +785,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@ -854,5 +854,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.8.1 <4.0.0"
dart: ">=3.10.0-0 <4.0.0"
flutter: ">=3.29.0"