diff --git a/lib/assets/animations/bookmark.gif b/lib/assets/animations/bookmark.gif new file mode 100644 index 0000000..9edbcf5 Binary files /dev/null and b/lib/assets/animations/bookmark.gif differ diff --git a/lib/constants/assets.dart b/lib/constants/assets.dart index 91e4793..214f320 100644 --- a/lib/constants/assets.dart +++ b/lib/constants/assets.dart @@ -42,6 +42,7 @@ class Assets { static String get studioLogo => '$_baseLogosPath/studio-$_themeSuffix.svg'; static String loadingAnimation = '$_baseAnimationsPath/loading.gif'; + static String bookmarkAnimation = '$_baseAnimationsPath/bookmark.gif'; static String get businessCategoryIcon => '$_baseCategoriesPath/business-$_themeSuffix.svg'; diff --git a/lib/main.dart b/lib/main.dart index 24a782b..861dcdb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -61,28 +61,24 @@ Future _backgroundCallbackHomeWidget(Uri? uri) async { } void main() async { - await runZonedGuarded(() async { - WidgetsFlutterBinding.ensureInitialized(); + WidgetsFlutterBinding.ensureInitialized(); - try { - if (!kIsWeb) { - HomeWidget.registerBackgroundCallback(_backgroundCallbackHomeWidget); - HomeWidget.registerInteractivityCallback(_backgroundCallbackHomeWidget); - await NotificationService.initializeNotification(); - } - - FirebaseMessaging.onBackgroundMessage(_initPushNotification); - await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform); - await FirebaseApi().initNotification(); - } catch (e) { - debugPrint; + try { + if (!kIsWeb) { + HomeWidget.registerBackgroundCallback(_backgroundCallbackHomeWidget); + HomeWidget.registerInteractivityCallback(_backgroundCallbackHomeWidget); + await NotificationService.initializeNotification(); } - runApp(const Didvan()); - }, (error, stack) async { - error.printError(); - }); + FirebaseMessaging.onBackgroundMessage(_initPushNotification); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform); + await FirebaseApi().initNotification(); + } catch (e) { + debugPrint; + } + + runApp(const Didvan()); } class Didvan extends StatefulWidget { diff --git a/lib/models/infography/infography_content.dart b/lib/models/infography/infography_content.dart index 5f9efad..d91b1c2 100644 --- a/lib/models/infography/infography_content.dart +++ b/lib/models/infography/infography_content.dart @@ -23,6 +23,7 @@ class Content { final String createdAt; bool marked; bool liked; + int likes; final List tags; @@ -30,6 +31,7 @@ class Content { {required this.id, required this.marked, required this.liked, + required this.likes, required this.createdAt, required this.title, required this.image, @@ -41,6 +43,7 @@ class Content { id: json['id'], marked: json['marked'], liked: json['liked'], + likes: json['likes'], createdAt: json['createdAt'], title: json['title'], image: json['image'], diff --git a/lib/models/news_details_data.dart b/lib/models/news_details_data.dart index bc11421..cfab02d 100644 --- a/lib/models/news_details_data.dart +++ b/lib/models/news_details_data.dart @@ -10,6 +10,7 @@ class NewsDetailsData { final String createdAt; bool marked; bool liked; + int likes; int comments; final int order; final List tags; @@ -25,6 +26,7 @@ class NewsDetailsData { required this.createdAt, required this.marked, required this.liked, + required this.likes, required this.comments, required this.tags, required this.contents, @@ -41,6 +43,7 @@ class NewsDetailsData { createdAt: json['createdAt'], marked: json['marked'], liked: json['liked'] ?? false, + likes: json['likes'], comments: json['comments'], order: json['order'], tags: List.from(json['tags'].map((tag) => Tag.fromJson(tag))), @@ -59,6 +62,7 @@ class NewsDetailsData { 'createdAt': createdAt, 'marked': marked, 'liked': liked, + 'likes': likes, 'comments': comments, 'tags': tags.map((e) => e.toJson()).toList(), 'contents': contents.map((e) => e.toJson()).toList(), diff --git a/lib/models/overview_data.dart b/lib/models/overview_data.dart index 2855509..169fdf9 100644 --- a/lib/models/overview_data.dart +++ b/lib/models/overview_data.dart @@ -20,6 +20,7 @@ class OverviewData { int comments; bool marked; bool liked; + int likes; final List? categories; OverviewData({ @@ -31,6 +32,7 @@ class OverviewData { required this.type, required this.marked, required this.liked, + required this.likes, required this.comments, required this.forManagers, this.category, @@ -87,6 +89,7 @@ class OverviewData { type: json['type'] ?? '', marked: json['marked'] ?? true, liked: json['liked'] ?? true, + likes: json['likes'] ?? 0, link: json['link'], iframe: json['iframe'], categories: json['categories'] != null diff --git a/lib/models/view/action_sheet_data.dart b/lib/models/view/action_sheet_data.dart index e463af9..4f3c2d5 100644 --- a/lib/models/view/action_sheet_data.dart +++ b/lib/models/view/action_sheet_data.dart @@ -4,8 +4,8 @@ class ActionSheetData { final Widget content; final String? confrimTitle; final String? dismissTitle; - final VoidCallback? onConfirmed; - final VoidCallback? onDismissed; + final Function()? onConfirmed; + final Function()? onDismissed; final String? title; final bool hasPadding; final IconData? titleIcon; diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart index 6c32ec3..5d75759 100644 --- a/lib/routes/route_generator.dart +++ b/lib/routes/route_generator.dart @@ -132,7 +132,9 @@ class RouteGenerator { ChangeNotifierProvider( create: (context) => NewStatisticState()) ], - child: const Home(), + child: Home( + showDialogs: settings.arguments as bool?, + ), ), ); case Routes.editProfile: diff --git a/lib/services/notification/firebase_api.dart b/lib/services/notification/firebase_api.dart index 6581c95..21786e0 100644 --- a/lib/services/notification/firebase_api.dart +++ b/lib/services/notification/firebase_api.dart @@ -20,7 +20,7 @@ class FirebaseApi { e.printError(); } - await _firebaseMessaging.requestPermission( + _firebaseMessaging.requestPermission( alert: true, announcement: true, badge: true, diff --git a/lib/utils/action_sheet.dart b/lib/utils/action_sheet.dart index 9f440a1..86677a9 100644 --- a/lib/utils/action_sheet.dart +++ b/lib/utils/action_sheet.dart @@ -169,8 +169,8 @@ class ActionSheetUtils { child: DidvanButton( style: ButtonStyleMode.primary, onPressed: () { - Navigator.of(context).pop(); data.onConfirmed?.call(); + pop(); }, title: data.confrimTitle ?? 'تایید', ), @@ -251,7 +251,10 @@ class ActionSheetUtils { if (data.hasDismissButton) Expanded( child: DidvanButton( - onPressed: data.onDismissed ?? () => pop(), + onPressed: () { + data.onDismissed?.call(); + pop(); + }, title: data.dismissTitle ?? 'بازگشت', style: ButtonStyleMode.flat, ), diff --git a/lib/views/ai/ai.dart b/lib/views/ai/ai.dart index 36024e5..20e07a7 100644 --- a/lib/views/ai/ai.dart +++ b/lib/views/ai/ai.dart @@ -58,7 +58,7 @@ class _AiState extends State { Column( children: [ const SizedBox( - height: 12, + height: 24, ), Icon( DidvanIcons.ai_solid, @@ -134,16 +134,6 @@ class _AiState extends State { const SizedBox( width: 8, ), - Container( - width: 32, - height: 32, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).colorScheme.border), - child: const Icon( - DidvanIcons.mic_regular, - ), - ), Expanded( child: Padding( padding: const EdgeInsets.symmetric( diff --git a/lib/views/ai/ai_chat_page.dart b/lib/views/ai/ai_chat_page.dart index 659c98c..bdcb2d7 100644 --- a/lib/views/ai/ai_chat_page.dart +++ b/lib/views/ai/ai_chat_page.dart @@ -409,9 +409,13 @@ class _AiChatPageState extends State { }, ); }), - SpinKitThreeBounce( - color: Theme.of(context).colorScheme.primary, - size: 18, + Padding( + padding: + const EdgeInsets.symmetric(vertical: 8.0), + child: SpinKitThreeBounce( + color: Theme.of(context).colorScheme.primary, + size: 18, + ), ) ], ) diff --git a/lib/views/ai/ai_chat_state.dart b/lib/views/ai/ai_chat_state.dart index 82ad607..a7e3f5e 100644 --- a/lib/views/ai/ai_chat_state.dart +++ b/lib/views/ai/ai_chat_state.dart @@ -34,11 +34,6 @@ class AiChatState extends CoreProvier { FilesModel? file; TextEditingController message = TextEditingController(); - @override - void dispose() { - super.dispose(); - } - Future _scrolledEnd() async { WidgetsBinding.instance.addPostFrameCallback((_) async { await scrollController.animateTo( @@ -166,12 +161,8 @@ class AiChatState extends CoreProvier { file = null; update(); - final stream = res - .transform(utf8.decoder) - .transform(const LineSplitter()); // <--- Add this line - - final r = stream.listen((str) { - // var str = utf8.decode(value); + final r = res.listen((value) async { + var str = utf8.decode(value); if (!kIsWeb) { if (str.contains('{{{')) { dataMessgae += str; @@ -197,6 +188,7 @@ class AiChatState extends CoreProvier { } } messageOnstream.value = Stream.value(responseMessgae); + print("responseMessgae: $str"); // update(); }); diff --git a/lib/views/ai/widgets/ai_message_bar.dart b/lib/views/ai/widgets/ai_message_bar.dart index 953e6b7..2063910 100644 --- a/lib/views/ai/widgets/ai_message_bar.dart +++ b/lib/views/ai/widgets/ai_message_bar.dart @@ -27,7 +27,6 @@ import 'package:get/get.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:provider/provider.dart'; import 'package:record/record.dart'; @@ -161,23 +160,25 @@ class _AiMessageBarState extends State { FilePickerResult? result = await MediaService.pickPdfFile(); if (result != null) { - // if (kIsWeb) { - // Uint8List bytes = result.files.first - // .bytes!; // Access the bytes property + if (kIsWeb) { + Uint8List? bytes = result.files.first + .bytes; // Access the bytes property + String? name = result.files.first.name; - // File file = File.fromRawPath(bytes); - // state.file = FilesModel(file.path, - // name: result.files.first.name, - // bytes: bytes, - // audio: false, - // image: false); - // print(result.files.first.name); - // } else { - state.file = FilesModel( - result.files.single.path!, + // Store bytes and file name directly in your state or model + state.file = FilesModel( + '', // No need for a file path on web + name: name, + bytes: bytes, audio: false, - image: false); - // } + image: false, + ); + } else { + state.file = FilesModel( + result.files.single.path!, + audio: false, + image: false); + } openAttach = false; } @@ -243,44 +244,45 @@ class _AiMessageBarState extends State { ); }, ), - if (historyState.bot!.attachmentType! - .contains('audio')) - attachBtn( - title: "صوت", - icon: CupertinoIcons.music_note_2, - color: Colors.indigoAccent, - click: () async { - MediaService.onLoadingPickFile(context); + if (!kIsWeb || !Platform.isIOS) + if (historyState.bot!.attachmentType! + .contains('audio')) + attachBtn( + title: "صوت", + icon: CupertinoIcons.music_note_2, + color: Colors.indigoAccent, + click: () async { + MediaService.onLoadingPickFile(context); - FilePickerResult? result = - await MediaService.pickAudioFile(); - if (result != null) { - if (kIsWeb) { - Uint8List bytes = result.files.first - .bytes!; // Access the bytes property + FilePickerResult? result = + await MediaService.pickAudioFile(); + if (result != null) { + if (kIsWeb) { + Uint8List bytes = result.files.first + .bytes!; // Access the bytes property - File file = File.fromRawPath(bytes); + File file = File.fromRawPath(bytes); - state.file = FilesModel(file.path, - name: result.files.first.name, - bytes: bytes, - audio: true, - image: false); - print(result.files.first.name); - } else { - state.file = FilesModel( - result.files.single.path!, - audio: true, - image: false); + state.file = FilesModel(file.path, + name: result.files.first.name, + bytes: bytes, + audio: true, + image: false); + print(result.files.first.name); + } else { + state.file = FilesModel( + result.files.single.path!, + audio: true, + image: false); + } + openAttach = false; } - openAttach = false; - } - await Future.delayed( - Duration.zero, - () => ActionSheetUtils(context).pop(), - ); - }, - ) + await Future.delayed( + Duration.zero, + () => ActionSheetUtils(context).pop(), + ); + }, + ) ], ), )), @@ -319,7 +321,8 @@ class _AiMessageBarState extends State { Padding( padding: const EdgeInsets.only( bottom: 8.0), - child: (snapshot.hasData && + child: (!kIsWeb && + snapshot.hasData && snapshot.data! != RecordState.stop) ? MessageBarBtn( @@ -342,7 +345,9 @@ class _AiMessageBarState extends State { state.update(); }, ) - : widget.bot.attachmentType! + : (!kIsWeb || !Platform.isIOS) && + widget.bot + .attachmentType! .contains( 'audio') && value.isEmpty && @@ -523,15 +528,27 @@ class _AiMessageBarState extends State { mainAxisAlignment: MainAxisAlignment .center, - children: List - .generate( - 3, - (index) => - SpinKitWave( - color: Theme.of(context).colorScheme.primary.withOpacity(0.4), - size: 32, - itemCount: 10, - ))), + children: List.generate( + 4, + (index) => snapshot.data! == RecordState.pause + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate( + 8, + (index) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 1.0, vertical: 12), + child: Container( + width: 3, + height: 8, + decoration: BoxDecoration(color: Theme.of(context).colorScheme.primary.withOpacity(0.4)), + ), + )), + ) + : SpinKitWave( + color: Theme.of(context).colorScheme.primary.withOpacity(0.4), + size: 32, + itemCount: 10, + ))), ), ValueListenableBuilder< int>( diff --git a/lib/views/ai/widgets/audio_wave.dart b/lib/views/ai/widgets/audio_wave.dart index 884272a..9f644ae 100644 --- a/lib/views/ai/widgets/audio_wave.dart +++ b/lib/views/ai/widgets/audio_wave.dart @@ -11,6 +11,7 @@ import 'package:didvan/views/ai/widgets/message_bar_btn.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:get/get.dart'; import 'package:just_audio/just_audio.dart'; @@ -35,6 +36,7 @@ class _AudioWaveState extends State { double currentPosition = 0; bool loading = true; bool faile = false; + bool onChanging = false; @override void initState() { @@ -56,7 +58,7 @@ class _AudioWaveState extends State { void setRandoms() { for (var i = 0; i < itemCount; i++) { randoms.value.add(0); - randomsDisable.value.add(2 + Random().nextDouble() * (42 - 2)); + randomsDisable.value.add(1 + Random().nextDouble() * (38 - 1)); } } @@ -94,7 +96,7 @@ class _AudioWaveState extends State { Future listeners() async { audioPlayer.positionStream.listen((position) async { - if (randomsDisable.value.isEmpty) return; + if (randomsDisable.value.isEmpty || onChanging) return; try { for (var i = 0; i < itemCount; i++) { @@ -219,12 +221,9 @@ class _AudioWaveState extends State { .primary .withOpacity(0.4)), if (totalDuration != Duration.zero) - Opacity( - opacity: 0, - child: Container( - width: 12, - color: Colors.transparent - .withOpacity(1), + Positioned.fill( + child: Opacity( + opacity: 0, child: Theme( data: Theme.of(context) .copyWith( @@ -252,22 +251,22 @@ class _AudioWaveState extends State { // audioPlayer.pause(); }, onChanged: (value) { - for (var i = 0; - i < itemCount; - i++) { - if (i < - ((value * 40) / - totalDuration - .inMilliseconds)) { - final ran = - randomsDisable - .value[i]; - randoms.value[i] = - ran; - } else { - randoms.value[i] = 0; - } - } + // for (var i = 0; + // i < itemCount; + // i++) { + // if (i < + // ((value * 40) / + // totalDuration + // .inMilliseconds)) { + // final ran = + // randomsDisable + // .value[i]; + // randoms.value[i] = + // ran; + // } else { + // randoms.value[i] = 0; + // } + // } setState(() { currentPosition = value; }); diff --git a/lib/views/authentication/screens/password.dart b/lib/views/authentication/screens/password.dart index 5145a15..872a919 100644 --- a/lib/views/authentication/screens/password.dart +++ b/lib/views/authentication/screens/password.dart @@ -80,78 +80,11 @@ class _PasswordInputState extends State { await ServerDataProvider.getData(); if (mounted) { - Future.delayed(Duration.zero, - () => Navigator.of(context).pushReplacementNamed(Routes.home)); + await Future.delayed( + Duration.zero, + () => Navigator.of(context) + .pushReplacementNamed(Routes.home, arguments: true)); } - - _showResetPasswordDialog(); } } - - void _showResetPasswordDialog() { - ActionSheetUtils(context).openDialog( - data: ActionSheetData( - content: const DidvanText( - 'خوش آمدید!\nبرای امنیت بیشتر، رمز عبور خود را تغییر دهید.', - ), - onConfirmed: () => Navigator.of(navigatorKey.currentContext!).pushNamed( - Routes.authenticaion, - arguments: true, - ), - isBackgroundDropBlur: false, - confrimTitle: 'تغییر رمز عبور', - onDismissed: Navigator.of(navigatorKey.currentContext!).pop, - dismissTitle: 'بعدا', - ), - ); - _showCustomizeDialog(); - } - - void _showCustomizeDialog() { - ActionSheetUtils(context).openDialog( - data: ActionSheetData( - backgroundColor: Theme.of(context).colorScheme.background, - isBackgroundDropBlur: true, - content: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWrapper( - onPressed: Navigator.of(navigatorKey.currentContext!).pop, - child: const Icon( - DidvanIcons.close_solid, - size: 24, - ), - ), - DidvanText( - 'شخصی سازی محتوا', - style: Theme.of(context).textTheme.displaySmall, - color: Theme.of(context).colorScheme.text, - ), - const InkWrapper( - child: Icon( - DidvanIcons.close_regular, - size: 24, - color: Colors.transparent, - ), - ), - ], - ), - const SizedBox( - height: 12, - ), - const DidvanText( - "کاربر گرامی\nلطفا جهت شخصی‌سازی و استفاده بهتر از برنامه، دسته‌بندی‌های مورد علاقه خود و زمان دریافت اعلانات را انتخاب نمایید.") - ], - ), - hasDismissButton: false, - onConfirmed: () => Navigator.of(navigatorKey.currentContext!).pushNamed( - Routes.favouritesStep, - arguments: {"toTimer": true}, - ), - confrimTitle: 'تایید', - ), - ); - } } diff --git a/lib/views/authentication/screens/username.dart b/lib/views/authentication/screens/username.dart index 16cde21..23ccb2a 100644 --- a/lib/views/authentication/screens/username.dart +++ b/lib/views/authentication/screens/username.dart @@ -51,7 +51,7 @@ class _UsernameInputState extends State { Padding( padding: const EdgeInsets.all(8.0), child: DidvanText( - 'نام کاربری می‌تواند شامل کاراکترهای کوچک و بزرگ انگلیسی و اعداد باشد.', + 'نام کاربری می‌تواند شامل کاراکترهای انگلیسی و اعداد باشد.', style: Theme.of(context).textTheme.labelSmall, ), ), diff --git a/lib/views/hashtag/hashtag.dart b/lib/views/hashtag/hashtag.dart index db26270..37ee34a 100644 --- a/lib/views/hashtag/hashtag.dart +++ b/lib/views/hashtag/hashtag.dart @@ -74,6 +74,7 @@ class _HashtagState extends State { liked: item.liked, onLikedChanged: (_, value, __) => _changeLiked(item.id, value, 'banner'), + likes: item.likes, ); case 'radar': diff --git a/lib/views/home/bookmarks/bookmarks.dart b/lib/views/home/bookmarks/bookmarks.dart index ad4df89..8a04010 100644 --- a/lib/views/home/bookmarks/bookmarks.dart +++ b/lib/views/home/bookmarks/bookmarks.dart @@ -1,11 +1,14 @@ import 'dart:async'; import 'package:didvan/config/design_config.dart'; +import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; +import 'package:didvan/constants/assets.dart'; import 'package:didvan/models/view/app_bar_data.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/views/home/bookmarks/bookmark_state.dart'; import 'package:didvan/views/widgets/didvan/scaffold.dart'; +import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/menu_item.dart'; import 'package:didvan/views/widgets/overview/multitype.dart'; // import 'package:didvan/views/widgets/search_field.dart'; @@ -124,7 +127,9 @@ class _BookmarksState extends State { ), ), SliverPadding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), sliver: SliverStateHandler( state: state, centerEmptyState: state.searching, @@ -144,9 +149,24 @@ class _BookmarksState extends State { }, placeholder: MultitypeOverview.placeholder, itemPadding: const EdgeInsets.only(bottom: 8), + paddingEmptyState: 0, emptyState: state.searching ? EmptyResult(onNewSearch: _focuseNode.requestFocus) - : const EmptyList(), + : Column( + children: [ + DidvanText( + 'در قسمت رصدخانه من، تمامی محتواهایی که در قسمت‌های مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشان‌دار) کرده‌اید، به تفکیک نمایش داده می‌شوند. هم‌چنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.', + fontSize: 14, + color: Theme.of(context).colorScheme.title, + textAlign: TextAlign.justify, + ), + Image.asset( + Assets.bookmarkAnimation, + width: MediaQuery.sizeOf(context).width, + height: 180, + ), + ], + ), enableEmptyState: state.bookmarks.isEmpty, childCount: state.bookmarks.length + (state.page != state.lastPage ? 1 : 0), diff --git a/lib/views/home/home.dart b/lib/views/home/home.dart index 4e9d5f5..df88bc7 100644 --- a/lib/views/home/home.dart +++ b/lib/views/home/home.dart @@ -27,6 +27,7 @@ import 'package:didvan/views/home/new_statistic/new_statistic.dart'; import 'package:didvan/views/home/search/search.dart'; import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:didvan/views/widgets/ink_wrapper.dart'; import 'package:didvan/views/widgets/logo_app_bar.dart'; import 'package:didvan/views/widgets/didvan/bnb.dart'; import 'package:didvan/views/widgets/shimmer_placeholder.dart'; @@ -35,13 +36,15 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:get/get.dart'; import 'package:provider/provider.dart'; import '../../services/app_home_widget/home_widget_repository.dart'; final GlobalKey homeScaffKey = GlobalKey(); class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); + final bool? showDialogs; + const Home({Key? key, this.showDialogs}) : super(key: key); @override State createState() => _HomeState(); @@ -51,8 +54,90 @@ class _HomeState extends State with SingleTickerProviderStateMixin, WidgetsBindingObserver { late final TabController _tabController; + Future _showDialog(BuildContext context) async { + WidgetsBinding.instance?.addPostFrameCallback((_) { + ActionSheetUtils(context) + .openDialog( + data: ActionSheetData( + content: const DidvanText( + 'خوش آمدید!\nبرای امنیت بیشتر، رمز عبور خود را تغییر دهید.', + ), + onConfirmed: () { + Future.delayed( + Duration.zero, + () => Navigator.of(context) + .pushNamed(Routes.authenticaion, arguments: true), + ); + }, + isBackgroundDropBlur: false, + confrimTitle: 'تغییر رمز عبور', + dismissTitle: 'بعدا', + ), + ) + .then((value) => ActionSheetUtils(context).openDialog( + data: ActionSheetData( + backgroundColor: Theme.of(context).colorScheme.background, + isBackgroundDropBlur: true, + content: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWrapper( + onPressed: () { + Future.delayed( + Duration.zero, + () => Navigator.of(context).pop(), + ); + }, + child: const Icon( + DidvanIcons.close_solid, + size: 24, + ), + ), + DidvanText( + 'شخصی سازی محتوا', + style: Theme.of(context).textTheme.displaySmall, + color: Theme.of(context).colorScheme.text, + ), + const InkWrapper( + child: Icon( + DidvanIcons.close_regular, + size: 24, + color: Colors.transparent, + ), + ), + ], + ), + const SizedBox( + height: 12, + ), + const DidvanText( + "کاربر گرامی\nلطفا جهت شخصی‌سازی و استفاده بهتر از برنامه، دسته‌بندی‌های مورد علاقه خود و زمان دریافت اعلانات را انتخاب نمایید.") + ], + ), + // hasDismissButton: false, + onConfirmed: () { + Future.delayed( + Duration.zero, + () => + Navigator.of(navigatorKey.currentContext!).pushNamed( + Routes.favouritesStep, + arguments: {"toTimer": true}, + ), + ); + }, + confrimTitle: 'تایید', + ), + )); + }); + } + @override void initState() { + if (widget.showDialogs ?? false) { + _showDialog(context); + } if (!kIsWeb) { NotificationService.startListeningNotificationEvents(); } diff --git a/lib/views/home/infography/infography_screen.dart b/lib/views/home/infography/infography_screen.dart index d76bca5..ce209cf 100644 --- a/lib/views/home/infography/infography_screen.dart +++ b/lib/views/home/infography/infography_screen.dart @@ -142,20 +142,21 @@ class _InfographyScreenState extends State { Wrap( children: [ for (var i = 0; i < state.categories.length; i++) - SizedBox( - width: (MediaQuery.of(context).size.width - 40) / 2, - child: DidvanCheckbox( - title: state.categories[i].label, - value: state.selectedCats.contains(state.categories[i]), - onChanged: (value) { - if (value) { - state.selectedCats.add(state.categories[i]); - return; - } - state.selectedCats.remove(state.categories[i]); - }, + if (state.categories[i].label != 'هوشان') + SizedBox( + width: (MediaQuery.of(context).size.width - 40) / 2, + child: DidvanCheckbox( + title: state.categories[i].label, + value: state.selectedCats.contains(state.categories[i]), + onChanged: (value) { + if (value) { + state.selectedCats.add(state.categories[i]); + return; + } + state.selectedCats.remove(state.categories[i]); + }, + ), ), - ), ], ), ], @@ -232,6 +233,7 @@ class _InfographyScreenState extends State { liked: state.contents[index].liked, onLikedChanged: (id, value, _) => state.changeLiked(id, value), + likes: state.contents[index].likes, ), ), ), diff --git a/lib/views/home/main/widgets/infography_item.dart b/lib/views/home/main/widgets/infography_item.dart index d29ad02..027e757 100644 --- a/lib/views/home/main/widgets/infography_item.dart +++ b/lib/views/home/main/widgets/infography_item.dart @@ -58,6 +58,7 @@ class InfographyItem extends StatelessWidget { final int id; final bool marked; final bool liked; + final int likes; final void Function(int id, bool value, bool shouldUpdate) onMarkChanged; final void Function(int id, bool value, bool shouldUpdate) onLikedChanged; @@ -72,6 +73,7 @@ class InfographyItem extends StatelessWidget { required this.id, required this.marked, required this.liked, + required this.likes, required this.onLikedChanged}); void _openInteractiveViewer(BuildContext context, String image) { @@ -152,6 +154,17 @@ class InfographyItem extends StatelessWidget { ), Row( children: [ + LikedButton( + itemId: id, + type: 'infography', + gestureSize: 32, + value: liked, + onMarkChanged: (value) => onLikedChanged(id, value, true), + likes: likes, + ), + const SizedBox( + width: 4.0, + ), DidvanIconButton( gestureSize: 32, onPressed: () => Navigator.of(context).pushNamed( @@ -164,19 +177,6 @@ class InfographyItem extends StatelessWidget { ), icon: DidvanIcons.mention_icon, ), - const SizedBox( - width: 8.0, - ), - LikedButton( - itemId: id, - type: 'infography', - gestureSize: 32, - value: liked, - onMarkChanged: (value) => onLikedChanged(id, value, true), - ), - const SizedBox( - width: 8.0, - ), BookmarkButton( itemId: id, type: 'infography', diff --git a/lib/views/home/search/search.dart b/lib/views/home/search/search.dart index 86d5ae8..2b3ad53 100644 --- a/lib/views/home/search/search.dart +++ b/lib/views/home/search/search.dart @@ -50,6 +50,7 @@ class SearchPage extends StatelessWidget { isColapsed: state.selectedCats.length <= 1, selectedCats: state.selectedCats, categories: state.categoryFilters, + disableHoushan: true, onSelected: (id) { state.selectedCats.clear(); final cat = state.categoryFilters diff --git a/lib/views/mentions/mentions.dart b/lib/views/mentions/mentions.dart index f415eb3..50e00fd 100644 --- a/lib/views/mentions/mentions.dart +++ b/lib/views/mentions/mentions.dart @@ -70,150 +70,166 @@ class _MentionsState extends State { } } _bottomPadding = bottomViewInset; - return Material( - child: Stack( - children: [ - DidvanScaffold( - hidePlayer: true, - physics: const BouncingScrollPhysics(), - backgroundColor: Theme.of(context).colorScheme.surface, - appBarData: _isPage - ? AppBarData( - hasBack: true, - title: 'فراخوانی‌ها', - subtitle: widget.pageData['title'], - ) - : null, - padding: const EdgeInsets.only(left: 16, right: 16, bottom: 92), - showSliversFirst: false, - slivers: [ - Consumer( - builder: (context, state, child) => - SliverStateHandler( - onRetry: state.getComments, - state: state, - itemPadding: const EdgeInsets.symmetric(vertical: 16), - childCount: state.comments.length, - placeholder: const _MentionPlaceholder(), - centerEmptyState: _isPage, - enableEmptyState: state.comments.isEmpty, - emptyState: EmptyState( - asset: Assets.emptyChat, - title: 'دوستان خود را فراخوانی کنید'), - builder: (context, state, index) => Mention( - key: ValueKey( - state.comments[index].id.toString() + - state.comments[index].text, + return WillPopScope( + onWillPop: () async { + if (mentionsState.showUsersForMentionsLayout) { + mentionsState.showUsersForMentionsLayout = false; + mentionsState.searchUsers.text = ''; + + mentionsState.update(); + return false; + } + return true; + }, + child: Material( + child: Stack( + children: [ + DidvanScaffold( + hidePlayer: true, + physics: const BouncingScrollPhysics(), + backgroundColor: Theme.of(context).colorScheme.surface, + appBarData: _isPage + ? AppBarData( + hasBack: true, + title: 'فراخوانی‌ها', + subtitle: widget.pageData['title'], + ) + : null, + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 92), + showSliversFirst: false, + slivers: [ + Consumer( + builder: (context, state, child) => + SliverStateHandler( + onRetry: state.getComments, + state: state, + itemPadding: const EdgeInsets.symmetric(vertical: 16), + childCount: state.comments.length, + placeholder: const _MentionPlaceholder(), + centerEmptyState: _isPage, + enableEmptyState: state.comments.isEmpty, + emptyState: EmptyState( + asset: Assets.emptyChat, + title: 'دوستان خود را فراخوانی کنید'), + builder: (context, state, index) => Mention( + key: ValueKey( + state.comments[index].id.toString() + + state.comments[index].text, + ), + focusNode: _focusNode, + comment: state.comments[index], ), - focusNode: _focusNode, - comment: state.comments[index], + ), + ), + ], + ), + AnimatedVisibility( + duration: DesignConfig.lowAnimationDuration, + isVisible: mentionsState.showUsersForMentionsLayout, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .focused + .withOpacity(0.5)), + child: DidvanScaffold( + hidePlayer: true, + appBarData: null, + padding: const EdgeInsets.only( + left: 16, right: 16, top: 16, bottom: 92), + backgroundColor: Colors.white.withOpacity(0.0), + showSliversFirst: false, + slivers: [ + Consumer( + builder: (context, state, child) => + SliverStateHandler( + onRetry: () { + state.getUsersMention( + context.read().user.id); + }, + state: state, + childCount: state.users.length, + placeholder: const _UsersPlaceholder(), + centerEmptyState: _isPage, + enableEmptyState: state.users.isEmpty, + emptyState: EmptyState( + asset: Assets.emptyBookmark, + title: 'لیست افراد خالی است', + ), + builder: (context, state, index) { + return UserMention( + user: state.users[index], + index: index, + ); + }, + ), + ), + ], + children: [ + Row( + children: [ + Expanded( + child: TextField( + controller: mentionsState.searchUsers, + focusNode: _focusNodeMention, + keyboardType: TextInputType.multiline, + textInputAction: TextInputAction.send, + style: Theme.of(context).textTheme.bodyMedium, + onEditingComplete: () {}, + onChanged: (val) => _onChange(mentionsState, val), + decoration: InputDecoration( + icon: const Icon(DidvanIcons.search_regular), + border: InputBorder.none, + hintText: 'نام فرد مورد نظر را بنویسید...', + hintStyle: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + color: Theme.of(context) + .colorScheme + .disabledText), + ), + ), + ), + DidvanIconButton( + icon: DidvanIcons.close_regular, + onPressed: () { + mentionsState.showUsersForMentionsLayout = + false; + mentionsState.searchUsers.text = ''; + + mentionsState.update(); + }), + ], + ), + const SizedBox( + height: 4, + ), + Divider( + height: 1, + color: Theme.of(context).colorScheme.splash, + ), + const SizedBox( + height: 12, + ) + ], ), ), ), - ], - ), - AnimatedVisibility( - duration: DesignConfig.lowAnimationDuration, - isVisible: mentionsState.showUsersForMentionsLayout, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), - child: Container( - decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.focused.withOpacity(0.5)), - child: DidvanScaffold( - appBarData: null, - padding: const EdgeInsets.only( - left: 16, right: 16, top: 16, bottom: 92), - backgroundColor: Colors.white.withOpacity(0.0), - showSliversFirst: false, - slivers: [ - Consumer( - builder: (context, state, child) => - SliverStateHandler( - onRetry: () { - state.getUsersMention( - context.read().user.id); - }, - state: state, - childCount: state.users.length, - placeholder: const _UsersPlaceholder(), - centerEmptyState: _isPage, - enableEmptyState: state.users.isEmpty, - emptyState: EmptyState( - asset: Assets.emptyBookmark, - title: 'لیست افراد خالی است', - ), - builder: (context, state, index) { - return UserMention( - user: state.users[index], - index: index, - ); - }, - ), - ), - ], - children: [ - Row( - children: [ - Expanded( - child: TextField( - controller: mentionsState.searchUsers, - focusNode: _focusNodeMention, - keyboardType: TextInputType.multiline, - textInputAction: TextInputAction.send, - style: Theme.of(context).textTheme.bodyMedium, - onEditingComplete: () {}, - onChanged: (val) => _onChange(mentionsState, val), - decoration: InputDecoration( - icon: const Icon(DidvanIcons.search_regular), - border: InputBorder.none, - hintText: 'نام فرد مورد نظر را بنویسید...', - hintStyle: Theme.of(context) - .textTheme - .bodySmall! - .copyWith( - color: Theme.of(context) - .colorScheme - .disabledText), - ), - ), - ), - DidvanIconButton( - icon: DidvanIcons.close_regular, - onPressed: () { - mentionsState.showUsersForMentionsLayout = false; - mentionsState.searchUsers.text = ''; - - mentionsState.update(); - }), - ], - ), - const SizedBox( - height: 4, - ), - Divider( - height: 1, - color: Theme.of(context).colorScheme.splash, - ), - const SizedBox( - height: 12, - ) - ], - ), + ), + Positioned( + left: 0, + right: 0, + bottom: MediaQuery.of(context).viewInsets.bottom, + child: _MessageBox( + focusNode: _focusNode, + focusNodeMention: _focusNodeMention, ), ), - ), - Positioned( - left: 0, - right: 0, - bottom: MediaQuery.of(context).viewInsets.bottom, - child: _MessageBox( - focusNode: _focusNode, - focusNodeMention: _focusNodeMention, - ), - ), - ], + ], + ), ), ); } diff --git a/lib/views/podcasts/widgets/slider.dart b/lib/views/podcasts/widgets/slider.dart index 71d08fe..41e53ff 100644 --- a/lib/views/podcasts/widgets/slider.dart +++ b/lib/views/podcasts/widgets/slider.dart @@ -80,11 +80,9 @@ class _StudioSliderState extends State { horizontal: 8, ), decoration: BoxDecoration( - color: (state.videosSelected - ? Theme.of(context) - .colorScheme - .secondaryDisabled - : Theme.of(context).colorScheme.focused) + color: Theme.of(context) + .colorScheme + .focused .withOpacity(0.9), borderRadius: const BorderRadius.vertical( bottom: Radius.circular(10), @@ -103,9 +101,11 @@ class _StudioSliderState extends State { width: 52, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context) - .colorScheme - .secondary + color: (state.videosSelected + ? Theme.of(context).colorScheme.secondary + : Theme.of(context) + .colorScheme + .focusedBorder) .withOpacity(0.7), ), child: Icon( @@ -155,13 +155,6 @@ class _SliderIndicator extends StatelessWidget { required this.isVideo, }) : super(key: key); - Color _color(BuildContext context) { - if (isVideo) { - return Theme.of(context).colorScheme.secondary; - } - return Theme.of(context).colorScheme.focusedBorder; - } - @override Widget build(BuildContext context) { return AnimatedContainer( @@ -171,10 +164,11 @@ class _SliderIndicator extends StatelessWidget { margin: const EdgeInsets.only(left: 4), decoration: BoxDecoration( border: Border.all( - color: _color(context), + color: Theme.of(context).colorScheme.focusedBorder, ), shape: BoxShape.circle, - color: isCurrentIndex ? _color(context) : null, + color: + isCurrentIndex ? Theme.of(context).colorScheme.focusedBorder : null, ), ); } diff --git a/lib/views/podcasts/widgets/tab_bar.dart b/lib/views/podcasts/widgets/tab_bar.dart index e480c94..31fa32f 100644 --- a/lib/views/podcasts/widgets/tab_bar.dart +++ b/lib/views/podcasts/widgets/tab_bar.dart @@ -29,7 +29,7 @@ class StudioTabBar extends StatelessWidget { Expanded( child: _StudioTypeButton( icon: DidvanIcons.video_solid, - selectedColor: Theme.of(context).colorScheme.secondary, + selectedColor: Theme.of(context).colorScheme.focusedBorder, title: 'ویدیو', onTap: () => state.videosSelected = true, isSelected: state.videosSelected, diff --git a/lib/views/profile/profile.dart b/lib/views/profile/profile.dart index d933cf9..c391646 100644 --- a/lib/views/profile/profile.dart +++ b/lib/views/profile/profile.dart @@ -347,7 +347,7 @@ class _ProfilePageState extends State { ), const SizedBox(height: 16), DidvanText( - 'نسخه نرم‌افزار: 3.2.2', + 'نسخه نرم‌افزار: 3.3.0', style: Theme.of(context).textTheme.bodySmall, ), ], diff --git a/lib/views/web/web_view.dart b/lib/views/web/web_view.dart index 05f0e0b..f1ac75c 100644 --- a/lib/views/web/web_view.dart +++ b/lib/views/web/web_view.dart @@ -1,6 +1,7 @@ // ignore_for_file: library_private_types_in_public_api, deprecated_member_use import 'package:didvan/constants/assets.dart'; +import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -62,14 +63,26 @@ class _WebViewState extends State { return true; } }, - child: loading - ? Center( - child: Image.asset( - Assets.loadingAnimation, - width: 60, - height: 60, - ), - ) - : WebViewWidget(controller: controller)); + child: Scaffold( + appBar: AppBar( + title: const Padding( + padding: EdgeInsets.only(top: 12.0), + child: DidvanText( + 'بازگشت به دیدوان', + fontSize: 18, + ), + ), + toolbarHeight: 32, + ), + body: loading + ? Center( + child: Image.asset( + Assets.loadingAnimation, + width: 60, + height: 60, + ), + ) + : WebViewWidget(controller: controller), + )); } } diff --git a/lib/views/widgets/categories_list.dart b/lib/views/widgets/categories_list.dart index 2f1af44..b62c741 100644 --- a/lib/views/widgets/categories_list.dart +++ b/lib/views/widgets/categories_list.dart @@ -10,6 +10,7 @@ class CategoriesList extends StatefulWidget { final bool isAppBar; final List selectedCats; final List categories; + final bool disableHoushan; final void Function(int id) onSelected; final double top; const CategoriesList({ @@ -19,6 +20,7 @@ class CategoriesList extends StatefulWidget { required this.categories, required this.onSelected, this.isAppBar = true, + this.disableHoushan = false, required this.top, }) : super(key: key); @@ -69,7 +71,9 @@ class _CategoriesListState extends State { context, ), for (var i = 0; i < widget.categories.length; i++) - _itemBuilder(widget.categories[i], context), + widget.disableHoushan && widget.categories[i].label == 'هوشان' + ? const SizedBox() + : _itemBuilder(widget.categories[i], context), ], ), ); diff --git a/lib/views/widgets/liked_button.dart b/lib/views/widgets/liked_button.dart index ba649e7..395784d 100644 --- a/lib/views/widgets/liked_button.dart +++ b/lib/views/widgets/liked_button.dart @@ -5,6 +5,7 @@ import 'package:didvan/providers/user.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/widgets/didvan/icon_button.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class LikedButton extends StatefulWidget { @@ -15,6 +16,7 @@ class LikedButton extends StatefulWidget { final double gestureSize; final String type; final int itemId; + final int likes; const LikedButton({ Key? key, required this.value, @@ -22,6 +24,7 @@ class LikedButton extends StatefulWidget { required this.gestureSize, required this.type, required this.itemId, + required this.likes, this.askForConfirmation = false, this.color, }) : super(key: key); @@ -45,38 +48,58 @@ class _LikedButtonState extends State { super.initState(); } + late int likes = widget.likes; + @override Widget build(BuildContext context) { - return DidvanIconButton( - gestureSize: widget.gestureSize, - color: widget.color ?? - (DesignConfig.isDark || !_value - ? null - : Theme.of(context).colorScheme.primary), - icon: _value ? DidvanIcons.like_solid : DidvanIcons.like_regular, - onPressed: () async { - bool confirm = false; - if (widget.askForConfirmation) { - await ActionSheetUtils(context).openDialog( - data: ActionSheetData( - content: const DidvanText( - 'آیا می‌خواهید این محتوا از نشان‌ شده‌ها حذف شود؟', - ), - titleIcon: DidvanIcons.bookmark_regular, - titleColor: Theme.of(context).colorScheme.secondary, - title: 'تایید عملیات', - onConfirmed: () => confirm = true, + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (likes != 0) + SizedBox( + height: 16, + child: DidvanText( + likes.toString(), + fontSize: 14, ), - ); - } - if (!widget.askForConfirmation || confirm) { - setState(() { - _value = !_value; - }); - widget.onMarkChanged(_value); - UserProvider.changeItemLiked(widget.type, widget.itemId, _value); - } - }, + ), + InkWell( + onTap: () async { + bool confirm = false; + if (widget.askForConfirmation) { + await ActionSheetUtils(context).openDialog( + data: ActionSheetData( + content: const DidvanText( + 'آیا می‌خواهید این محتوا از نشان‌ شده‌ها حذف شود؟', + ), + titleIcon: DidvanIcons.bookmark_regular, + titleColor: Theme.of(context).colorScheme.secondary, + title: 'تایید عملیات', + onConfirmed: () => confirm = true, + ), + ); + } + if (!widget.askForConfirmation || confirm) { + setState(() { + _value = !_value; + if (_value) { + likes += 1; + } else { + likes -= 1; + } + }); + widget.onMarkChanged(_value); + UserProvider.changeItemLiked(widget.type, widget.itemId, _value); + } + }, + child: Icon( + _value ? CupertinoIcons.heart_fill : CupertinoIcons.heart, + size: 24, + color: widget.color ?? + (!_value ? null : Theme.of(context).colorScheme.error), + ), + ), + ], ); } } diff --git a/lib/views/widgets/logo_app_bar.dart b/lib/views/widgets/logo_app_bar.dart index 0b7c1db..4476711 100644 --- a/lib/views/widgets/logo_app_bar.dart +++ b/lib/views/widgets/logo_app_bar.dart @@ -193,21 +193,22 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget { Wrap( children: [ for (var i = 0; i < state.categoryFilters.length; i++) - SizedBox( - width: (MediaQuery.of(context).size.width - 40) / 2, - child: DidvanCheckbox( - title: state.categoryFilters[i].label, - value: - state.selectedCats.contains(state.categoryFilters[i]), - onChanged: (value) { - if (value) { - state.selectedCats.add(state.categoryFilters[i]); - return; - } - state.selectedCats.remove(state.categoryFilters[i]); - }, + if (state.categoryFilters[i].label != 'هوشان') + SizedBox( + width: (MediaQuery.of(context).size.width - 40) / 2, + child: DidvanCheckbox( + title: state.categoryFilters[i].label, + value: state.selectedCats + .contains(state.categoryFilters[i]), + onChanged: (value) { + if (value) { + state.selectedCats.add(state.categoryFilters[i]); + return; + } + state.selectedCats.remove(state.categoryFilters[i]); + }, + ), ), - ), ], ), ], diff --git a/lib/views/widgets/overview/multitype.dart b/lib/views/widgets/overview/multitype.dart index 038e741..fa713f4 100644 --- a/lib/views/widgets/overview/multitype.dart +++ b/lib/views/widgets/overview/multitype.dart @@ -74,6 +74,7 @@ class MultitypeOverview extends StatelessWidget { case 'podcast': return DidvanIcons.podcast_light; case 'delphi': + case 'survey': return DidvanIcons.saha_light; case 'infography': return DidvanIcons.infography_regular; diff --git a/lib/views/widgets/overview/news.dart b/lib/views/widgets/overview/news.dart index 1cda2c1..4f67df2 100644 --- a/lib/views/widgets/overview/news.dart +++ b/lib/views/widgets/overview/news.dart @@ -93,6 +93,10 @@ class NewsOverview extends StatelessWidget { onMarkChanged: (value) => onLikedChanged(news.id, value, false), askForConfirmation: hasUnmarkConfirmation, + likes: news.likes, + ), + const SizedBox( + width: 4.0, ), BookmarkButton( itemId: news.id, diff --git a/lib/views/widgets/overview/radar.dart b/lib/views/widgets/overview/radar.dart index 72172d3..df13ec9 100644 --- a/lib/views/widgets/overview/radar.dart +++ b/lib/views/widgets/overview/radar.dart @@ -132,6 +132,10 @@ class RadarOverview extends StatelessWidget { onMarkChanged: (value) => onLikedChanged(radar.id, value, false), askForConfirmation: hasUnmarkConfirmation, + likes: radar.likes, + ), + const SizedBox( + width: 4.0, ), BookmarkButton( itemId: radar.id, diff --git a/lib/views/widgets/search_app_bar.dart b/lib/views/widgets/search_app_bar.dart index 269b3c9..0e607cf 100644 --- a/lib/views/widgets/search_app_bar.dart +++ b/lib/views/widgets/search_app_bar.dart @@ -133,21 +133,22 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget { Wrap( children: [ for (var i = 0; i < state.categoryFilters.length; i++) - SizedBox( - width: (MediaQuery.of(context).size.width - 40) / 2, - child: DidvanCheckbox( - title: state.categoryFilters[i].label, - value: - state.selectedCats.contains(state.categoryFilters[i]), - onChanged: (value) { - if (value) { - state.selectedCats.add(state.categoryFilters[i]); - return; - } - state.selectedCats.remove(state.categoryFilters[i]); - }, + if (state.categoryFilters[i].label != 'هوشان') + SizedBox( + width: (MediaQuery.of(context).size.width - 40) / 2, + child: DidvanCheckbox( + title: state.categoryFilters[i].label, + value: state.selectedCats + .contains(state.categoryFilters[i]), + onChanged: (value) { + if (value) { + state.selectedCats.add(state.categoryFilters[i]); + return; + } + state.selectedCats.remove(state.categoryFilters[i]); + }, + ), ), - ), ], ), ], diff --git a/lib/views/widgets/state_handlers/sliver_state_handler.dart b/lib/views/widgets/state_handlers/sliver_state_handler.dart index b05cbbe..689e5d3 100644 --- a/lib/views/widgets/state_handlers/sliver_state_handler.dart +++ b/lib/views/widgets/state_handlers/sliver_state_handler.dart @@ -15,6 +15,7 @@ class SliverStateHandler extends SliverList { final bool centerEmptyState; final bool hasConstraints; final int placeholderCount; + final double? paddingEmptyState; SliverStateHandler({ Key? key, required this.state, @@ -28,6 +29,7 @@ class SliverStateHandler extends SliverList { this.centerEmptyState = true, this.hasConstraints = false, this.placeholderCount = 3, + this.paddingEmptyState, }) : super( key: key, delegate: SliverChildBuilderDelegate( @@ -45,7 +47,8 @@ class SliverStateHandler extends SliverList { if (enableEmptyState && state.appState == AppState.idle) { return Padding( padding: EdgeInsets.only( - top: centerEmptyState ? deviceHight / 4 : deviceHight / 8, + top: paddingEmptyState ?? + (centerEmptyState ? deviceHight / 4 : deviceHight / 8), bottom: 20, ), child: emptyState, diff --git a/pubspec.yaml b/pubspec.yaml index ba42aa4..41033d7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.2.2+3220 +version: 3.3.0+3300 environment: sdk: ">=2.19.0 <3.0.0"