bug fixes

This commit is contained in:
MohammadTaha Basiri 2023-10-12 15:59:38 +03:30
parent 153db82742
commit 944409c69d
17 changed files with 292 additions and 136 deletions

View File

@ -16,7 +16,7 @@ class LightThemeConfig {
if (!states.contains(MaterialState.selected)) { if (!states.contains(MaterialState.selected)) {
return Colors.transparent; return Colors.transparent;
} }
return _colorScheme.primary; return _colorScheme.secondary;
}), }),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
@ -62,7 +62,7 @@ class DarkThemeConfig {
if (!states.contains(MaterialState.selected)) { if (!states.contains(MaterialState.selected)) {
return Colors.transparent; return Colors.transparent;
} }
return _colorScheme.primary; return _colorScheme.secondary;
}), }),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),

View File

@ -8,7 +8,7 @@ class NewsDetailsData {
final String reference; final String reference;
final String image; final String image;
final String createdAt; final String createdAt;
final bool marked; bool marked;
int comments; int comments;
final int order; final int order;
final List<Tag> tags; final List<Tag> tags;

View File

@ -13,7 +13,7 @@ class RadarDetailsData {
final String? podcast; final String? podcast;
final int? duration; final int? duration;
final bool forManagers; final bool forManagers;
final bool marked; bool marked;
int comments; int comments;
final List<Tag> tags; final List<Tag> tags;
final List<Content> contents; final List<Content> contents;

View File

@ -9,6 +9,9 @@ class ThemeProvider extends CoreProvier {
set themeMode(ThemeMode value) { set themeMode(ThemeMode value) {
_themeMode = value; _themeMode = value;
notifyListeners(); notifyListeners();
Future.delayed(
const Duration(milliseconds: 500),
).then((_) => notifyListeners());
} }
ThemeMode get themeMode => _themeMode; ThemeMode get themeMode => _themeMode;

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:didvan/main.dart'; import 'package:didvan/main.dart';
import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/news.dart';
import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/requests/radar.dart';
@ -127,11 +129,18 @@ class AppInitializer {
messagingSenderId: "935017686266", messagingSenderId: "935017686266",
appId: "1:935017686266:web:a93f7a19bed23c51d2d543", appId: "1:935017686266:web:a93f7a19bed23c51d2d543",
measurementId: "G-80B4H9E8Y0") measurementId: "G-80B4H9E8Y0")
: const FirebaseOptions( : Platform.isAndroid
? const FirebaseOptions(
apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw', apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543', appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
messagingSenderId: '935017686266', messagingSenderId: '935017686266',
projectId: 'didvan-9b7da', projectId: 'didvan-9b7da',
)
: const FirebaseOptions(
apiKey: 'AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U',
appId: '1:935017686266:ios:de47638bd662463fd2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
), ),
); );
} catch (e) { } catch (e) {

View File

@ -74,6 +74,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
onTabChanged: (index) { onTabChanged: (index) {
state.currentPageIndex = index; state.currentPageIndex = index;
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
state.resetFilters(false);
_tabController.animateTo(index); _tabController.animateTo(index);
}, },
), ),

View File

@ -35,6 +35,7 @@ class HomeState extends CoreProvier {
final List<OverviewData> results = []; final List<OverviewData> results = [];
late TabController tabController; late TabController tabController;
int unreadCount = 0; int unreadCount = 0;
final FocusNode searchFieldFocusNode = FocusNode();
void resetFilters(bool isInit) { void resetFilters(bool isInit) {
startDate = null; startDate = null;
@ -139,10 +140,7 @@ class HomeState extends CoreProvier {
CategoryData(id: 6, label: 'سها'), CategoryData(id: 6, label: 'سها'),
]; ];
void refresh() { void refresh() async {
menuItems.clear();
categories.clear();
menuItems = [ menuItems = [
MenuItemType( MenuItemType(
label: 'دنیای فولاد', label: 'دنیای فولاد',
@ -248,5 +246,6 @@ class HomeState extends CoreProvier {
asset: Assets.businessCategoryIcon, asset: Assets.businessCategoryIcon,
), ),
]; ];
Future.delayed(Duration.zero, notifyListeners);
} }
} }

View File

@ -1,5 +1,12 @@
import 'dart:math';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/views/home/main/main_page_state.dart'; import 'package:didvan/views/home/main/main_page_state.dart';
import 'package:didvan/views/widgets/animated_visibility.dart';
import 'package:didvan/views/widgets/didvan/slider.dart'; import 'package:didvan/views/widgets/didvan/slider.dart';
import 'package:didvan/views/widgets/ink_wrapper.dart';
import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -18,16 +25,76 @@ class MainPageBanner extends StatelessWidget {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
child: GestureDetector( child: GestureDetector(
onTap: item.link == null ? null : () => launchUrlString(item.link!), onTap: () => item.link == null || item.link!.isEmpty
? _openInteractiveViewer(context, item.image)
: launchUrlString(item.link!, mode: LaunchMode.inAppWebView),
child: SkeletonImage( child: SkeletonImage(
imageUrl: item.image, imageUrl: item.image,
), ),
), ),
); );
}, },
itemCount: state.content.banners.length, itemCount: state.content.banners[isFirst ? 0 : 1].length,
viewportFraction: 1, viewportFraction: 1,
enableIndicator: true, enableIndicator: true,
); );
} }
void _openInteractiveViewer(BuildContext context, String image) {
showDialog(
context: context,
builder: (context) => Stack(
children: [
Positioned.fill(
child: InteractiveViewer(
child: Center(
child: SkeletonImage(
width: min(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
imageUrl: image,
),
),
),
),
const Positioned(
right: 24,
top: 24,
child: _BackButton(),
),
],
),
);
}
}
class _BackButton extends StatefulWidget {
const _BackButton({Key? key}) : super(key: key);
@override
__BackButtonState createState() => __BackButtonState();
}
class __BackButtonState extends State<_BackButton> {
@override
Widget build(BuildContext context) {
return AnimatedVisibility(
duration: DesignConfig.lowAnimationDuration,
isVisible: true,
child: InkWrapper(
borderRadius: DesignConfig.lowBorderRadius,
onPressed: Navigator.of(context).pop,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.splash,
border: Border.all(color: Theme.of(context).colorScheme.border),
borderRadius: DesignConfig.lowBorderRadius,
),
child: const Icon(
DidvanIcons.back_regular,
size: 32,
),
),
),
);
}
} }

View File

@ -1,12 +1,16 @@
import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/home_page_content/content.dart'; import 'package:didvan/models/home_page_content/content.dart';
import 'package:didvan/models/requests/studio.dart';
import 'package:didvan/models/studio_details_data.dart'; import 'package:didvan/models/studio_details_data.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/views/direct/widgets/audio_widget.dart'; import 'package:didvan/views/direct/widgets/audio_widget.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/widgets/didvan/card.dart'; import 'package:didvan/views/widgets/didvan/card.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart';
class MainPagePodcastItem extends StatelessWidget { class MainPagePodcastItem extends StatelessWidget {
final MainPageContentType content; final MainPageContentType content;
@ -14,7 +18,22 @@ class MainPagePodcastItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack( return GestureDetector(
onTap: () async {
final state = context.read<StudioDetailsState>();
await state.getStudioDetails(
content.id,
args: const StudioRequestArgs(page: 0, type: 'podcast'),
);
MediaService.currentPodcast = state.studio;
MediaService.handleAudioPlayback(
audioSource: content.link,
id: content.id,
isNetworkAudio: true,
isVoiceMessage: false,
);
},
child: Stack(
children: [ children: [
const SizedBox( const SizedBox(
height: 180, height: 180,
@ -34,7 +53,8 @@ class MainPagePodcastItem extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width * 2 / 3 - 90, width:
MediaQuery.of(context).size.width * 2 / 3 - 90,
child: AudioWidget( child: AudioWidget(
id: content.id, id: content.id,
audioUrl: content.link, audioUrl: content.link,
@ -65,7 +85,8 @@ class MainPagePodcastItem extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 4), padding:
const EdgeInsets.symmetric(vertical: 4),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -100,6 +121,7 @@ class MainPagePodcastItem extends StatelessWidget {
imageUrl: content.image, imageUrl: content.image,
), ),
], ],
),
); );
} }
} }

View File

@ -3,7 +3,7 @@ import 'package:didvan/models/enums.dart';
import 'package:didvan/views/home/home_state.dart'; import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/home/search/widgets/search_result_item.dart'; import 'package:didvan/views/home/search/widgets/search_result_item.dart';
import 'package:didvan/views/widgets/categories_list.dart'; import 'package:didvan/views/widgets/categories_list.dart';
import 'package:didvan/views/widgets/state_handlers/empty_list.dart'; import 'package:didvan/views/widgets/state_handlers/empty_result.dart';
import 'package:didvan/views/widgets/state_handlers/state_handler.dart'; import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -23,7 +23,9 @@ class SearchPage extends StatelessWidget {
state: state, state: state,
enableEmptyState: enableEmptyState:
state.appState == AppState.idle && state.results.isEmpty, state.appState == AppState.idle && state.results.isEmpty,
emptyState: const EmptyList(), emptyState: EmptyResult(
onNewSearch: () => state.searchFieldFocusNode.requestFocus(),
),
onRetry: () => state.searchAll(page: state.page), onRetry: () => state.searchAll(page: state.page),
builder: (context, state) => ListView.builder( builder: (context, state) => ListView.builder(
padding: const EdgeInsets.all(16) padding: const EdgeInsets.all(16)

View File

@ -58,7 +58,7 @@ class _StatisticState extends State<Statistic> {
slivers: [ slivers: [
if (state.appState != AppState.failed) if (state.appState != AppState.failed)
const SliverToBoxAdapter( const SliverToBoxAdapter(
child: SizedBox(height: 120), child: SizedBox(height: 140),
), ),
if (state.appState != AppState.failed && if (state.appState != AppState.failed &&
state.markedStatistics.isNotEmpty) state.markedStatistics.isNotEmpty)

View File

@ -66,10 +66,13 @@ class _NewsDetailsState extends State<NewsDetails> {
scrollController: _scrollController, scrollController: _scrollController,
item: state.currentNews, item: state.currentNews,
onCommentsChanged: state.onCommentsChanged, onCommentsChanged: state.onCommentsChanged,
onMarkChanged: (value) => widget.pageData['onMarkChanged']( onMarkChanged: (value) {
state.currentNews.marked = value;
widget.pageData['onMarkChanged'](
state.currentNews.id, state.currentNews.id,
value, value,
), );
},
isRadar: false, isRadar: false,
), ),
), ),

View File

@ -65,11 +65,13 @@ class _RadarDetailsState extends State<RadarDetails> {
widget.pageData['hasUnmarkConfirmation'] ?? false, widget.pageData['hasUnmarkConfirmation'] ?? false,
isRadar: true, isRadar: true,
scrollController: _scrollController, scrollController: _scrollController,
onMarkChanged: (value) => onMarkChanged: (value) {
widget.pageData['onMarkChanged']?.call( state.currentRadar.marked = value;
widget.pageData['onMarkChanged'](
state.currentRadar.id, state.currentRadar.id,
value, value,
), );
},
item: state.currentRadar, item: state.currentRadar,
onCommentsChanged: (count) { onCommentsChanged: (count) {
state.onCommentsChanged(count); state.onCommentsChanged(count);

View File

@ -104,7 +104,10 @@ class _PlayerNavBar extends StatelessWidget {
return StreamBuilder<bool>( return StreamBuilder<bool>(
stream: MediaService.audioPlayer.isPlaying, stream: MediaService.audioPlayer.isPlaying,
builder: (context, snapshot) => GestureDetector( builder: (context, snapshot) => GestureDetector(
onTap: () => MediaService.currentPodcast == null || onTap: () => (MediaService.currentPodcast == null &&
(MediaService.audioPlayerTag ?? '')
.split('-')[1]
.isNotEmpty) ||
MediaService.currentPodcast?.description == 'radar' MediaService.currentPodcast?.description == 'radar'
? Navigator.of(context).pushNamed( ? Navigator.of(context).pushNamed(
Routes.radarDetails, Routes.radarDetails,
@ -116,7 +119,9 @@ class _PlayerNavBar extends StatelessWidget {
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
}, },
) )
: _showPlayerBottomSheet(context), : (MediaService.audioPlayerTag ?? '').split('-')[1].isNotEmpty
? _showPlayerBottomSheet(context)
: null,
child: Consumer<StudioDetailsState>( child: Consumer<StudioDetailsState>(
builder: (context, state, child) => AnimatedContainer( builder: (context, state, child) => AnimatedContainer(
padding: const EdgeInsets.only(top: 12), padding: const EdgeInsets.only(top: 12),
@ -147,7 +152,29 @@ class _PlayerNavBar extends StatelessWidget {
if (MediaService.currentPodcast == null) { if (MediaService.currentPodcast == null) {
return SizedBox( return SizedBox(
height: 32, height: 32,
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(
right: 12,
left: 16,
),
child: DidvanIconButton(
icon: DidvanIcons.close_regular,
color: DesignConfig.isDark
? null
: Theme.of(context).colorScheme.secondCTA,
gestureSize: 28,
onPressed: () {
MediaService.resetAudioPlayer();
state.update();
},
),
),
Expanded(
child: Center( child: Center(
child: Padding(
padding: const EdgeInsets.only(left: 48),
child: SpinKitThreeBounce( child: SpinKitThreeBounce(
size: 18, size: 18,
color: DesignConfig.isDark color: DesignConfig.isDark
@ -155,6 +182,10 @@ class _PlayerNavBar extends StatelessWidget {
: Theme.of(context).colorScheme.secondCTA, : Theme.of(context).colorScheme.secondCTA,
), ),
), ),
),
),
],
),
); );
} }
return SizedBox( return SizedBox(

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:didvan/config/theme_data.dart'; import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/providers/theme.dart';
import 'package:didvan/routes/routes.dart'; import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/home/home_state.dart'; import 'package:didvan/views/home/home_state.dart';
@ -49,7 +50,9 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const DidvanHorizontalLogo(), DidvanHorizontalLogo(
key: ValueKey(context.watch<ThemeProvider>().themeMode),
),
Row( Row(
children: [ children: [
DidvanIconButton( DidvanIconButton(
@ -95,12 +98,13 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Consumer<HomeState>( Consumer<HomeState>(
builder: (context, state, child) => SearchField( builder: (context, state, child) => SearchField(
key: ValueKey(state.search), key: state.search.isEmpty ? ValueKey(state.search) : null,
value: state.search,
title: state.currentPageIndex == 3 ? 'رصدهای من' : 'دیدوان', title: state.currentPageIndex == 3 ? 'رصدهای من' : 'دیدوان',
onChanged: (value) => _onChanged(value, context), onChanged: (value) => _onChanged(value, context),
focusNode: FocusNode(), focusNode: state.searchFieldFocusNode,
onFilterButtonPressed: () => _showFilterBottomSheet(context), onFilterButtonPressed: () => _showFilterBottomSheet(context),
isFiltered: state.filtering && state.search == '', isFiltered: state.filtering,
onGoBack: state.filtering onGoBack: state.filtering
? () { ? () {
state.resetFilters(false); state.resetFilters(false);

View File

@ -7,6 +7,7 @@ import 'package:didvan/models/requests/studio.dart';
import 'package:didvan/providers/user.dart'; import 'package:didvan/providers/user.dart';
import 'package:didvan/routes/routes.dart'; import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/utils/date_time.dart'; import 'package:didvan/utils/date_time.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/widgets/didvan/card.dart'; import 'package:didvan/views/widgets/didvan/card.dart';
@ -17,6 +18,7 @@ import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
class MultitypeOverview extends StatelessWidget { class MultitypeOverview extends StatelessWidget {
final OverviewData item; final OverviewData item;
@ -42,14 +44,20 @@ class MultitypeOverview extends StatelessWidget {
return StudioRequestArgs(page: 0, type: item.type); return StudioRequestArgs(page: 0, type: item.type);
} }
String get _targetPageRouteName { String? get _targetPageRouteName {
if (item.type == 'radar') { if (item.type == 'radar') {
return Routes.radarDetails; return Routes.radarDetails;
} }
if (item.type == 'news') { if (item.type == 'news') {
return Routes.newsDetails; return Routes.newsDetails;
} }
return Routes.studioDetails; if (item.type == 'podcast') {
return Routes.podcasts;
}
if (item.type == 'video') {
return Routes.videocasts;
}
return null;
} }
IconData get _icon { IconData get _icon {
@ -90,8 +98,15 @@ class MultitypeOverview extends StatelessWidget {
); );
return; return;
} }
if (_targetPageRouteName == null && item.link != null) {
launchUrlString(
'${item.link!}?accessToken=${RequestService.token}',
mode: LaunchMode.inAppWebView,
);
return;
}
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
_targetPageRouteName, _targetPageRouteName!,
arguments: { arguments: {
'onMarkChanged': onMarkChanged, 'onMarkChanged': onMarkChanged,
'id': item.id, 'id': item.id,

View File

@ -10,6 +10,7 @@ class SearchField extends StatefulWidget {
final void Function(String value) onChanged; final void Function(String value) onChanged;
final VoidCallback? onFilterButtonPressed; final VoidCallback? onFilterButtonPressed;
final VoidCallback? onGoBack; final VoidCallback? onGoBack;
final String? value;
const SearchField({ const SearchField({
Key? key, Key? key,
@ -19,6 +20,7 @@ class SearchField extends StatefulWidget {
this.onFilterButtonPressed, this.onFilterButtonPressed,
this.isFiltered, this.isFiltered,
this.onGoBack, this.onGoBack,
this.value,
}) : super(key: key); }) : super(key: key);
@override @override
@ -46,6 +48,7 @@ class _SearchFieldState extends State<SearchField> {
color: _fillColor(), color: _fillColor(),
), ),
child: TextFormField( child: TextFormField(
initialValue: widget.value,
focusNode: widget.focusNode, focusNode: widget.focusNode,
style: Theme.of(context).textTheme.bodyMedium, style: Theme.of(context).textTheme.bodyMedium,
textAlignVertical: TextAlignVertical.center, textAlignVertical: TextAlignVertical.center,
@ -109,20 +112,15 @@ class _SearchFieldState extends State<SearchField> {
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
), ),
prefix: widget.onGoBack != null prefixIcon: GestureDetector(
? DidvanIconButton( onTap: widget.onGoBack,
gestureSize: 32, child: Icon(
icon: DidvanIcons.back_light, widget.onGoBack == null
? DidvanIcons.search_regular
: DidvanIcons.back_light,
color: Theme.of(context).colorScheme.text, color: Theme.of(context).colorScheme.text,
onPressed: widget.onGoBack!, ),
) ),
: null,
prefixIcon: widget.onGoBack == null
? Icon(
DidvanIcons.search_regular,
color: Theme.of(context).colorScheme.text,
)
: null,
prefixIconColor: Theme.of(context).colorScheme.inputText, prefixIconColor: Theme.of(context).colorScheme.inputText,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(