bug fixes
This commit is contained in:
parent
153db82742
commit
944409c69d
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in New Issue