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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,6 +35,7 @@ class HomeState extends CoreProvier {
final List<OverviewData> results = [];
late TabController tabController;
int unreadCount = 0;
final FocusNode searchFieldFocusNode = FocusNode();
void resetFilters(bool isInit) {
startDate = null;
@ -139,10 +140,7 @@ class HomeState extends CoreProvier {
CategoryData(id: 6, label: 'سها'),
];
void refresh() {
menuItems.clear();
categories.clear();
void refresh() async {
menuItems = [
MenuItemType(
label: 'دنیای فولاد',
@ -248,5 +246,6 @@ class HomeState extends CoreProvier {
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/widgets/animated_visibility.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:flutter/material.dart';
import 'package:provider/provider.dart';
@ -18,16 +25,76 @@ class MainPageBanner extends StatelessWidget {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
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(
imageUrl: item.image,
),
),
);
},
itemCount: state.content.banners.length,
itemCount: state.content.banners[isFirst ? 0 : 1].length,
viewportFraction: 1,
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/models/home_page_content/content.dart';
import 'package:didvan/models/requests/studio.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/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/widgets/didvan/card.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart';
class MainPagePodcastItem extends StatelessWidget {
final MainPageContentType content;
@ -14,7 +18,22 @@ class MainPagePodcastItem extends StatelessWidget {
@override
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: [
const SizedBox(
height: 180,
@ -34,7 +53,8 @@ class MainPagePodcastItem extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 2 / 3 - 90,
width:
MediaQuery.of(context).size.width * 2 / 3 - 90,
child: AudioWidget(
id: content.id,
audioUrl: content.link,
@ -65,7 +85,8 @@ class MainPagePodcastItem extends StatelessWidget {
overflow: TextOverflow.ellipsis,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
padding:
const EdgeInsets.symmetric(vertical: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -100,6 +121,7 @@ class MainPagePodcastItem extends StatelessWidget {
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/search/widgets/search_result_item.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:flutter/material.dart';
import 'package:provider/provider.dart';
@ -23,7 +23,9 @@ class SearchPage extends StatelessWidget {
state: state,
enableEmptyState:
state.appState == AppState.idle && state.results.isEmpty,
emptyState: const EmptyList(),
emptyState: EmptyResult(
onNewSearch: () => state.searchFieldFocusNode.requestFocus(),
),
onRetry: () => state.searchAll(page: state.page),
builder: (context, state) => ListView.builder(
padding: const EdgeInsets.all(16)

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.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/utils/action_sheet.dart';
import 'package:didvan/views/home/home_state.dart';
@ -49,7 +50,9 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const DidvanHorizontalLogo(),
DidvanHorizontalLogo(
key: ValueKey(context.watch<ThemeProvider>().themeMode),
),
Row(
children: [
DidvanIconButton(
@ -95,12 +98,13 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget {
const SizedBox(height: 16),
Consumer<HomeState>(
builder: (context, state, child) => SearchField(
key: ValueKey(state.search),
key: state.search.isEmpty ? ValueKey(state.search) : null,
value: state.search,
title: state.currentPageIndex == 3 ? 'رصدهای من' : 'دیدوان',
onChanged: (value) => _onChanged(value, context),
focusNode: FocusNode(),
focusNode: state.searchFieldFocusNode,
onFilterButtonPressed: () => _showFilterBottomSheet(context),
isFiltered: state.filtering && state.search == '',
isFiltered: state.filtering,
onGoBack: state.filtering
? () {
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/routes/routes.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/views/podcasts/studio_details/studio_details_state.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:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
class MultitypeOverview extends StatelessWidget {
final OverviewData item;
@ -42,14 +44,20 @@ class MultitypeOverview extends StatelessWidget {
return StudioRequestArgs(page: 0, type: item.type);
}
String get _targetPageRouteName {
String? get _targetPageRouteName {
if (item.type == 'radar') {
return Routes.radarDetails;
}
if (item.type == 'news') {
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 {
@ -90,8 +98,15 @@ class MultitypeOverview extends StatelessWidget {
);
return;
}
if (_targetPageRouteName == null && item.link != null) {
launchUrlString(
'${item.link!}?accessToken=${RequestService.token}',
mode: LaunchMode.inAppWebView,
);
return;
}
Navigator.of(context).pushNamed(
_targetPageRouteName,
_targetPageRouteName!,
arguments: {
'onMarkChanged': onMarkChanged,
'id': item.id,

View File

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