import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart' show CupertinoIcons; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotiflac_android/providers/runtime_profile_provider.dart'; import 'package:spotiflac_android/theme/app_tokens.dart'; import 'package:spotiflac_android/theme/mornye_theme.dart'; import 'package:spotiflac_android/widgets/mornye_chrome.dart'; import 'package:spotiflac_android/widgets/settings_group.dart'; /// The standard search field used by top-level app surfaces. /// /// Keeping the decoration here prevents Settings, Store, and future search /// surfaces from drifting into slightly different shapes and colors. class AppSearchField extends StatelessWidget { const AppSearchField({ super.key, required this.controller, required this.hintText, required this.clearTooltip, this.onChanged, required this.onClear, this.onSubmitted, this.prefixIcon, this.suffixIcon, this.focusNode, this.autofocus = false, }); final TextEditingController controller; final String hintText; final String clearTooltip; final ValueChanged? onChanged; final VoidCallback onClear; final ValueChanged? onSubmitted; final Widget? prefixIcon; final Widget? suffixIcon; final FocusNode? focusNode; final bool autofocus; @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final mornye = context.isMornye; final radius = BorderRadius.circular( mornye ? 28 : context.tokens.radiusSheet, ); final field = ValueListenableBuilder( valueListenable: controller, builder: (context, value, _) => TextField( controller: controller, focusNode: focusNode, autofocus: autofocus, textInputAction: TextInputAction.search, decoration: InputDecoration( hintText: hintText, prefixIcon: prefixIcon ?? Icon(mornye ? CupertinoIcons.search : Icons.search), suffixIcon: suffixIcon ?? (value.text.isEmpty ? null : IconButton( tooltip: clearTooltip, icon: Icon( mornye ? CupertinoIcons.clear_circled_solid : Icons.clear, ), onPressed: () { controller.clear(); onClear(); }, )), border: OutlineInputBorder( borderRadius: radius, borderSide: mornye ? BorderSide.none : BorderSide(color: colorScheme.outlineVariant), ), enabledBorder: OutlineInputBorder( borderRadius: radius, borderSide: mornye ? BorderSide.none : BorderSide(color: colorScheme.outlineVariant), ), focusedBorder: OutlineInputBorder( borderRadius: radius, borderSide: mornye ? BorderSide.none : BorderSide(color: colorScheme.primary, width: 2), ), filled: true, fillColor: mornye ? Colors.transparent : settingsGroupColor(context), contentPadding: const EdgeInsets.symmetric( horizontal: 20, vertical: 16, ), ), onChanged: onChanged, onSubmitted: onSubmitted, onTapOutside: (_) => FocusScope.of(context).unfocus(), ), ); if (!mornye) return field; return Consumer( builder: (context, ref, child) => MornyeGlass.navigation( radius: 28, blurEnabled: !ref.watch(lowEndDeviceProvider) || ref.watch(backdropBlurEnabledProvider), child: child!, ), child: field, ); } }