feat: Phase 2 — upgrade deps to null-safe, replace deprecated packages
- pubspec: bump all maintained deps to null-safe latest; flutter pub get resolves
- Remove 12 packages (0-ref or no null-safe): splashscreen, flappy_search_bar,
searchable_dropdown, share, platform_detect, flutter_inappwebview, countdown,
gender_selection, flutter_dash, smooth_star_rating, hovering, ffi
- Add flutter_rating_bar
- Keep discontinued-but-null-safe for now (Phase 5): pull_to_refresh, hive, catcher
- New null-safe custom components (API-compatible, callers change only imports):
utils/countdown.dart, widgets/general/{hover_widget,gender_selection,
smooth_star_rating,search_bar}.dart
- main.dart: drop dead SplashScreen _buildBody + _to field
- 23 consuming files: swap deprecated imports to local components
Null-safety migration + upgraded-API adaptation = Phase 3.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/breadcrumbs.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:gender_selection/gender_selection.dart';
|
||||
import '../general/gender_selection.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../events/eventbus.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/breadcrumbs.dart';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import 'package:email_validator/email_validator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/breadcrumbs.dart';
|
||||
import 'package:gender_selection/gender_selection.dart';
|
||||
import '../general/gender_selection.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/breadcrumbs.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/navigationbar.dart';
|
||||
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||
import 'package:smooth_star_rating/smooth_star_rating.dart';
|
||||
import '../general/smooth_star_rating.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../events/eventbus.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/breadcrumbs.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/navigationbar.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_wisetronic/pages/product_detail_page.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hovering/hovering.dart';
|
||||
import '../general/hover_widget.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
import '../../events/events.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
|
||||
111
lib/widgets/general/gender_selection.dart
Normal file
111
lib/widgets/general/gender_selection.dart
Normal file
@@ -0,0 +1,111 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 自定义实现,替代已停维的 `gender_selection` 包。
|
||||
///
|
||||
/// 保留原 `Gender` 枚举与 `GenderSelection` 组件的命名参数,
|
||||
/// 使调用方仅改 import 即可编译。大部分装饰性参数为兼容保留(暂未全部生效,
|
||||
/// 后续美化阶段 Phase 5 再完善视觉)。
|
||||
enum Gender { Male, Female }
|
||||
|
||||
class GenderSelection extends StatefulWidget {
|
||||
final String? maleText;
|
||||
final String? femaleText;
|
||||
final Color? selectedGenderIconBackgroundColor;
|
||||
final Alignment? checkIconAlignment;
|
||||
final IconData? selectedGenderCheckIcon;
|
||||
final void Function(Gender gender)? onChanged;
|
||||
final bool? equallyAligned;
|
||||
final Duration? animationDuration;
|
||||
final bool? isCircular;
|
||||
final bool? isSelectedGenderIconCircular;
|
||||
final double? opacityOfGradient;
|
||||
final EdgeInsets? padding;
|
||||
final double? size;
|
||||
final Gender? selectedGender;
|
||||
|
||||
const GenderSelection({
|
||||
super.key,
|
||||
this.maleText,
|
||||
this.femaleText,
|
||||
this.selectedGenderIconBackgroundColor,
|
||||
this.checkIconAlignment,
|
||||
this.selectedGenderCheckIcon,
|
||||
this.onChanged,
|
||||
this.equallyAligned,
|
||||
this.animationDuration,
|
||||
this.isCircular,
|
||||
this.isSelectedGenderIconCircular,
|
||||
this.opacityOfGradient,
|
||||
this.padding,
|
||||
this.size,
|
||||
this.selectedGender,
|
||||
});
|
||||
|
||||
@override
|
||||
State<GenderSelection> createState() => _GenderSelectionState();
|
||||
}
|
||||
|
||||
class _GenderSelectionState extends State<GenderSelection> {
|
||||
Gender? _selected;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selected = widget.selectedGender;
|
||||
}
|
||||
|
||||
Widget _buildOption(Gender gender, String label) {
|
||||
final selected = _selected == gender;
|
||||
final color = widget.selectedGenderIconBackgroundColor ?? Colors.indigo;
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: widget.padding ?? const EdgeInsets.all(3.0),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() => _selected = gender);
|
||||
widget.onChanged?.call(gender);
|
||||
},
|
||||
child: Container(
|
||||
height: widget.size ?? 50.0,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: selected ? color : color.withOpacity(0.06),
|
||||
borderRadius:
|
||||
(widget.isCircular ?? false) ? BorderRadius.circular(60) : null,
|
||||
border: Border.all(
|
||||
color: selected ? color : Colors.black26,
|
||||
width: selected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (selected && widget.selectedGenderCheckIcon != null)
|
||||
Icon(widget.selectedGenderCheckIcon, color: Colors.white, size: 18),
|
||||
if (selected && widget.selectedGenderCheckIcon != null)
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: selected ? Colors.white : Colors.black87,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
_buildOption(Gender.Male, widget.maleText ?? 'Mr'),
|
||||
_buildOption(Gender.Female, widget.femaleText ?? 'Ms'),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
46
lib/widgets/general/hover_widget.dart
Normal file
46
lib/widgets/general/hover_widget.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 自定义实现,替代已停维的 `hovering` 包的 [HoverWidget]。
|
||||
///
|
||||
/// API 兼容:
|
||||
/// ```dart
|
||||
/// HoverWidget(
|
||||
/// child: ...,
|
||||
/// hoverChild: ...,
|
||||
/// onHover: (PointerHoverEvent event) { ... },
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// 鼠标悬停时显示 [hoverChild],否则显示 [child]。
|
||||
class HoverWidget extends StatefulWidget {
|
||||
final Widget child;
|
||||
final Widget? hoverChild;
|
||||
final void Function(PointerHoverEvent)? onHover;
|
||||
|
||||
const HoverWidget({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.hoverChild,
|
||||
this.onHover,
|
||||
});
|
||||
|
||||
@override
|
||||
State<HoverWidget> createState() => _HoverWidgetState();
|
||||
}
|
||||
|
||||
class _HoverWidgetState extends State<HoverWidget> {
|
||||
bool _hovering = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onHover: widget.onHover,
|
||||
onEnter: (_) => setState(() => _hovering = true),
|
||||
onExit: (_) => setState(() => _hovering = false),
|
||||
child: (_hovering && widget.hoverChild != null)
|
||||
? widget.hoverChild!
|
||||
: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinput/pin_put/pin_put.dart';
|
||||
|
||||
|
||||
185
lib/widgets/general/search_bar.dart
Normal file
185
lib/widgets/general/search_bar.dart
Normal file
@@ -0,0 +1,185 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 轻量级异步搜索控制器,配合 [SearchBar] 使用。
|
||||
///
|
||||
/// 替代已停维的 `flappy_search_bar` 的 `SearchBarController`。
|
||||
/// 保留泛型 `<T>` 以兼容调用方 `SearchBarController<Product>()` 写法。
|
||||
/// [replayLastSearch] 用于“加载更多 / 分页”:外部 page++ 后触发重跑上一次搜索。
|
||||
class SearchBarController<T> {
|
||||
String lastQuery = '';
|
||||
VoidCallback? _replay;
|
||||
|
||||
void _register(VoidCallback replay) {
|
||||
_replay = replay;
|
||||
}
|
||||
|
||||
/// 重新执行上一次搜索(分页加载更多时调用)。
|
||||
void replayLastSearch() => _replay?.call();
|
||||
}
|
||||
|
||||
/// 轻量级 Web 异步搜索栏,替代已停维的 `flappy_search_bar` 的 `SearchBar`。
|
||||
///
|
||||
/// 基本流程:输入达到 [minimumChars] 个字符后,调用 [onSearch] 取结果,
|
||||
/// 用 [onItemFound] 渲染每一条;无结果时显示 [emptyWidget];出错显示 [onError]。
|
||||
///
|
||||
/// 注意:`searchBarController` 参数刻意使用裸类型(`SearchBarController?`),
|
||||
/// 以兼容调用方 `SearchBarController _controller = SearchBarController<Product>();`
|
||||
/// 的写法(Dart 3 sound 类型下避免泛型不变性报错)。
|
||||
class SearchBar<T> extends StatefulWidget {
|
||||
final SearchBarController? searchBarController;
|
||||
final int minimumChars;
|
||||
final String? hintText;
|
||||
final Widget? cancellationWidget;
|
||||
final Future<List<T>> Function(String text) onSearch;
|
||||
final Widget Function(T item, int index) onItemFound;
|
||||
final Widget Function(dynamic error)? onError;
|
||||
final Widget? emptyWidget;
|
||||
final Duration debounceDuration;
|
||||
|
||||
const SearchBar({
|
||||
super.key,
|
||||
this.searchBarController,
|
||||
this.minimumChars = 2,
|
||||
this.hintText,
|
||||
this.cancellationWidget,
|
||||
required this.onSearch,
|
||||
required this.onItemFound,
|
||||
this.onError,
|
||||
this.emptyWidget,
|
||||
this.debounceDuration = const Duration(milliseconds: 350),
|
||||
});
|
||||
|
||||
@override
|
||||
State<SearchBar<T>> createState() => _SearchBarState<T>();
|
||||
}
|
||||
|
||||
class _SearchBarState<T> extends State<SearchBar<T>> {
|
||||
final TextEditingController _textController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
Timer? _debounce;
|
||||
List<T> _results = <T>[];
|
||||
bool _loading = false;
|
||||
dynamic _error;
|
||||
bool _hasSearched = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.searchBarController?._register(_runSearch);
|
||||
_textController.addListener(_onTextChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounce?.cancel();
|
||||
_textController.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onTextChanged() {
|
||||
final text = _textController.text;
|
||||
_debounce?.cancel();
|
||||
if (text.length >= widget.minimumChars) {
|
||||
_debounce = Timer(widget.debounceDuration, _runSearch);
|
||||
} else if (text.isEmpty) {
|
||||
setState(() {
|
||||
_results = <T>[];
|
||||
_hasSearched = false;
|
||||
_error = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _runSearch() async {
|
||||
final query = _textController.text;
|
||||
if (query.length < widget.minimumChars) return;
|
||||
if (widget.searchBarController != null) {
|
||||
widget.searchBarController!.lastQuery = query;
|
||||
}
|
||||
setState(() {
|
||||
_loading = true;
|
||||
_error = null;
|
||||
_hasSearched = true;
|
||||
});
|
||||
try {
|
||||
final results = await widget.onSearch(query);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_results = results;
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_error = e;
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _cancel() {
|
||||
_textController.clear();
|
||||
_focusNode.unfocus();
|
||||
setState(() {
|
||||
_results = <T>[];
|
||||
_hasSearched = false;
|
||||
_error = null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
controller: _textController,
|
||||
focusNode: _focusNode,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
suffixIcon: _textController.text.isNotEmpty
|
||||
? GestureDetector(
|
||||
onTap: _cancel,
|
||||
child: widget.cancellationWidget ??
|
||||
const Icon(Icons.close, size: 20),
|
||||
)
|
||||
: null,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Expanded(child: _buildBody()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
if (_loading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (_error != null) {
|
||||
return widget.onError != null
|
||||
? widget.onError!(_error)
|
||||
: Center(child: Text('$_error'));
|
||||
}
|
||||
if (!_hasSearched) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
if (_results.isEmpty) {
|
||||
return widget.emptyWidget ?? const SizedBox.shrink();
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: _results.length,
|
||||
itemBuilder: (BuildContext context, int index) =>
|
||||
widget.onItemFound(_results[index], index),
|
||||
);
|
||||
}
|
||||
}
|
||||
90
lib/widgets/general/smooth_star_rating.dart
Normal file
90
lib/widgets/general/smooth_star_rating.dart
Normal file
@@ -0,0 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 自定义实现,替代已停维的 `smooth_star_rating` 包的 [SmoothStarRating]。
|
||||
///
|
||||
/// 保留原命名参数(`allowHalfRating`/`onRated`/`starCount`/`rating`/`size`/
|
||||
/// `filledIconData`/`color`/`borderColor`/`spacing`),调用方仅改 import 即可。
|
||||
class SmoothStarRating extends StatefulWidget {
|
||||
final bool allowHalfRating;
|
||||
final void Function(double)? onRated;
|
||||
final int starCount;
|
||||
final double rating;
|
||||
final double size;
|
||||
final IconData filledIconData;
|
||||
final IconData? halfFilledIconData;
|
||||
final IconData? defaultIconData;
|
||||
final Color color;
|
||||
final Color borderColor;
|
||||
final double spacing;
|
||||
|
||||
const SmoothStarRating({
|
||||
super.key,
|
||||
this.allowHalfRating = false,
|
||||
this.onRated,
|
||||
this.starCount = 5,
|
||||
this.rating = 0.0,
|
||||
this.size = 24.0,
|
||||
this.filledIconData = Icons.star,
|
||||
this.halfFilledIconData,
|
||||
this.defaultIconData,
|
||||
this.color = Colors.orange,
|
||||
this.borderColor = Colors.orange,
|
||||
this.spacing = 0.0,
|
||||
});
|
||||
|
||||
@override
|
||||
State<SmoothStarRating> createState() => _SmoothStarRatingState();
|
||||
}
|
||||
|
||||
class _SmoothStarRatingState extends State<SmoothStarRating> {
|
||||
late double _rating;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_rating = widget.rating;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant SmoothStarRating oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.rating != widget.rating) {
|
||||
_rating = widget.rating;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _star(int index) {
|
||||
IconData icon;
|
||||
Color iconColor;
|
||||
if (index < _rating.floor()) {
|
||||
icon = widget.filledIconData;
|
||||
iconColor = widget.color;
|
||||
} else if (widget.allowHalfRating &&
|
||||
index == _rating.floor() &&
|
||||
(_rating - index) >= 0.5) {
|
||||
icon = widget.halfFilledIconData ?? Icons.star_half;
|
||||
iconColor = widget.color;
|
||||
} else {
|
||||
icon = widget.defaultIconData ?? Icons.star_border;
|
||||
iconColor = widget.borderColor;
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() => _rating = (index + 1).toDouble());
|
||||
widget.onRated?.call(_rating);
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: widget.spacing / 2),
|
||||
child: Icon(icon, size: widget.size, color: iconColor),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: List<Widget>.generate(widget.starCount, _star),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_wisetronic/utils/utils.dart';
|
||||
import 'package:hovering/hovering.dart';
|
||||
import 'hover_widget.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../routes.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'package:flutter_wisetronic/store/store.dart';
|
||||
import 'package:flutter_wisetronic/utils/http_util.dart';
|
||||
import 'package:flutter_wisetronic/utils/utils.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:gender_selection/gender_selection.dart';
|
||||
import '../general/gender_selection.dart';
|
||||
|
||||
import '../../routes.dart';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import 'package:email_validator/email_validator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gender_selection/gender_selection.dart';
|
||||
import '../general/gender_selection.dart';
|
||||
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../models/located_address.dart';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import 'package:badges/badges.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||
import 'package:smooth_star_rating/smooth_star_rating.dart';
|
||||
import '../general/smooth_star_rating.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
import '../../events/events.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:countdown/countdown.dart';
|
||||
import '../../utils/countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
import 'package:badges/badges.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dash/flutter_dash.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:flutter_wisetronic/dialog/image_viewer.dart';
|
||||
import 'package:flutter_wisetronic/events/eventbus.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import '../general/search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
|
||||
@@ -28,7 +28,7 @@ import 'package:flutter_wisetronic/widgets/general/read_more_text.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/show_price.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/sliding_up_panel.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:smooth_star_rating/smooth_star_rating.dart';
|
||||
import '../general/smooth_star_rating.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user