component updates

This commit is contained in:
MohammadTaha Basiri 2022-01-24 02:26:43 +03:30
parent 17287f4b5f
commit d29f6fa60e
10 changed files with 268 additions and 81 deletions

View File

@ -6,12 +6,14 @@ class BookmarkButton extends StatefulWidget {
final bool value; final bool value;
final VoidCallback onMark; final VoidCallback onMark;
final VoidCallback onUnmark; final VoidCallback onUnmark;
const BookmarkButton( final bool bigGestureSize;
{Key? key, const BookmarkButton({
Key? key,
required this.value, required this.value,
required this.onMark, required this.onMark,
required this.onUnmark}) required this.onUnmark,
: super(key: key); this.bigGestureSize = false,
}) : super(key: key);
@override @override
State<BookmarkButton> createState() => _BookmarkButtonState(); State<BookmarkButton> createState() => _BookmarkButtonState();
@ -35,7 +37,7 @@ class _BookmarkButtonState extends State<BookmarkButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DidvanIconButton( return DidvanIconButton(
gestureSize: 24, gestureSize: widget.bigGestureSize ? 32 : 24,
icon: _value ? DidvanIcons.bookmark_solid : DidvanIcons.bookmark_regular, icon: _value ? DidvanIcons.bookmark_solid : DidvanIcons.bookmark_regular,
onPressed: () { onPressed: () {
setState(() { setState(() {

View File

@ -7,14 +7,18 @@ import 'package:flutter/material.dart';
class DidvanButton extends StatelessWidget { class DidvanButton extends StatelessWidget {
final VoidCallback? onPressed; final VoidCallback? onPressed;
final String? title; final String? title;
final double? width;
final ButtonStyleMode style; final ButtonStyleMode style;
final bool enabled; final bool enabled;
final double? height;
const DidvanButton({ const DidvanButton({
Key? key, Key? key,
this.onPressed, this.onPressed,
this.title, this.title,
this.style = ButtonStyleMode.primary, this.style = ButtonStyleMode.primary,
this.enabled = true, this.enabled = true,
this.width,
this.height = 48,
}) : super(key: key); }) : super(key: key);
@override @override
@ -42,8 +46,8 @@ class DidvanButton extends StatelessWidget {
default: default:
} }
return SizedBox( return SizedBox(
height: 48, height: height,
width: double.infinity, width: width ?? double.infinity,
child: MaterialButton( child: MaterialButton(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: DesignConfig.lowBorderRadius, borderRadius: DesignConfig.lowBorderRadius,

View File

@ -0,0 +1,35 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/ink_wrapper.dart';
import 'package:flutter/material.dart';
class DidvanChip extends StatelessWidget {
final String label;
final VoidCallback? onTap;
const DidvanChip({
Key? key,
required this.label,
this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWrapper(
borderRadius: DesignConfig.highBorderRadius,
onPressed: onTap,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8),
decoration: BoxDecoration(
borderRadius: DesignConfig.highBorderRadius,
color: Theme.of(context).colorScheme.primary,
),
child: DidvanText(
label,
style: Theme.of(context).textTheme.caption,
color: Theme.of(context).colorScheme.white,
),
),
);
}
}

View File

@ -1,13 +1,19 @@
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/widgets/didvan/card.dart'; import 'package:didvan/widgets/didvan/card.dart';
import 'package:didvan/widgets/didvan/divider.dart';
import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/skeleton_image.dart'; import 'package:didvan/widgets/skeleton_image.dart';
import 'package:didvan/widgets/tag_item.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
class DidvanPageView extends StatefulWidget { class DidvanPageView extends StatefulWidget {
final List items; final List items;
final int initialIndex; final int initialIndex;
final bool isRadar;
final ScrollController? scrollController; final ScrollController? scrollController;
final void Function(int index) onPageChanged; final void Function(int index) onPageChanged;
const DidvanPageView({ const DidvanPageView({
Key? key, Key? key,
@ -15,6 +21,7 @@ class DidvanPageView extends StatefulWidget {
required this.items, required this.items,
this.scrollController, this.scrollController,
required this.onPageChanged, required this.onPageChanged,
required this.isRadar,
}) : super(key: key); }) : super(key: key);
@override @override
@ -36,7 +43,9 @@ class _DidvanPageViewState extends State<DidvanPageView> {
viewportFraction: 0.94, viewportFraction: 0.94,
enableInfiniteScroll: false, enableInfiniteScroll: false,
), ),
itemBuilder: (context, index, realIndex) => SizedBox( itemBuilder: (context, index, realIndex) => Directionality(
textDirection: TextDirection.rtl,
child: SizedBox(
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
child: SingleChildScrollView( child: SingleChildScrollView(
controller: index == 1 ? widget.scrollController : null, controller: index == 1 ? widget.scrollController : null,
@ -64,31 +73,42 @@ class _DidvanPageViewState extends State<DidvanPageView> {
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: DidvanText(
item.title,
style: Theme.of(context).textTheme.subtitle1,
),
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: _subtitle(item),
),
for (var i = 0; i < item.contents.length; i++) for (var i = 0; i < item.contents.length; i++)
Padding( Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 16, horizontal: 16,
vertical: 4, vertical: 4,
), ),
child: Builder( child: _contentBuilder(item, i),
builder: (context) { ),
final content = item.contents[i]; if (item.tags.isNotEmpty) const SizedBox(height: 20),
if (content.text != null) { Padding(
return DidvanText( padding: const EdgeInsets.symmetric(horizontal: 16),
item.contents[i].text!, child: Wrap(
); spacing: 8,
} runSpacing: 8,
if (content.image != null) { children: [
return SkeletonImage( for (var i = 0; i < item.tags.length; i++)
imageUrl: content.image!, TagItem(label: item.tags[i].label),
aspectRatio: 16 / 9, ],
);
}
return const SizedBox();
},
), ),
), ),
const SizedBox(height: 20), const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: DidvanDivider(),
),
], ],
); );
}, },
@ -97,6 +117,56 @@ class _DidvanPageViewState extends State<DidvanPageView> {
), ),
), ),
), ),
),
); );
} }
Widget _contentBuilder(dynamic item, int index) {
final content = item.contents[index];
if (content.text != null) {
return Html(data: item.contents[index].text!);
}
if (content.image != null) {
return SkeletonImage(
imageUrl: content.image!,
aspectRatio: 16 / 9,
);
}
return const SizedBox();
}
Widget _subtitle(dynamic item) {
if (widget.isRadar) {
return Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
DidvanText(
'رادار ',
style: Theme.of(context).textTheme.caption,
),
for (var i = 0; i < item.categories.length; i++)
DidvanText(
item.categories[i].label +
' - ' +
DateTimeUtils.momentGenerator(item.createdAt) +
'${i != item.categories.length - 1 ? '،' : ''} ',
style: Theme.of(context).textTheme.caption,
),
],
);
} else {
return Row(
children: [
DidvanText(
item.reference,
style: Theme.of(context).textTheme.caption,
),
DidvanText(
' - ' + DateTimeUtils.momentGenerator(item.createdAt),
style: Theme.of(context).textTheme.caption,
),
],
);
}
}
} }

View File

@ -7,25 +7,29 @@ class DidvanScaffold extends StatelessWidget {
final List<Widget>? children; final List<Widget>? children;
final AppBarData appBarData; final AppBarData appBarData;
final EdgeInsets padding; final EdgeInsets padding;
final Color? backgroundColor;
const DidvanScaffold({ const DidvanScaffold({
Key? key, Key? key,
this.slivers, this.slivers,
required this.appBarData, required this.appBarData,
this.children, this.children,
this.padding = const EdgeInsets.symmetric(horizontal: 16), this.padding = const EdgeInsets.symmetric(horizontal: 16),
this.backgroundColor,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top; final double statusBarHeight = MediaQuery.of(context).padding.top;
return Scaffold( return Scaffold(
backgroundColor: backgroundColor,
body: Padding( body: Padding(
padding: EdgeInsets.only(top: statusBarHeight), padding: EdgeInsets.only(top: statusBarHeight),
child: CustomScrollView( child: CustomScrollView(
slivers: [ slivers: [
SliverAppBar( SliverAppBar(
toolbarHeight: kToolbarHeight, toolbarHeight: kToolbarHeight,
backgroundColor: Theme.of(context).backgroundColor, backgroundColor:
backgroundColor ?? Theme.of(context).colorScheme.background,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
pinned: true, pinned: true,
flexibleSpace: DidvanAppBar(appBarData: appBarData), flexibleSpace: DidvanAppBar(appBarData: appBarData),
@ -43,7 +47,12 @@ class DidvanScaffold extends StatelessWidget {
), ),
), ),
), ),
if (slivers != null) ...slivers!, if (slivers != null)
for (var i = 0; i < slivers!.length; i++)
SliverPadding(
padding: padding,
sliver: slivers![i],
),
], ],
), ),
), ),

View File

@ -9,6 +9,7 @@ class DidvanText extends StatelessWidget {
final TextAlign textAlign; final TextAlign textAlign;
final int? maxLines; final int? maxLines;
final bool isEnglishFont; final bool isEnglishFont;
final TextOverflow? overflow;
const DidvanText( const DidvanText(
this.text, { this.text, {
@ -20,6 +21,7 @@ class DidvanText extends StatelessWidget {
this.textAlign = TextAlign.right, this.textAlign = TextAlign.right,
this.maxLines, this.maxLines,
this.isEnglishFont = false, this.isEnglishFont = false,
this.overflow,
}) : super(key: key); }) : super(key: key);
@override @override
@ -31,6 +33,7 @@ class DidvanText extends StatelessWidget {
fontWeight: fontWeight, fontWeight: fontWeight,
fontSize: fontSize, fontSize: fontSize,
)).copyWith(fontFamily: isEnglishFont ? 'Dana' : null), )).copyWith(fontFamily: isEnglishFont ? 'Dana' : null),
overflow: overflow,
textAlign: textAlign, textAlign: textAlign,
maxLines: maxLines, maxLines: maxLines,
); );

View File

@ -8,9 +8,11 @@ import 'package:didvan/pages/home/settings/widgets/menu_item.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/widgets/bookmark_button.dart'; import 'package:didvan/widgets/bookmark_button.dart';
import 'package:didvan/widgets/didvan/chip.dart';
import 'package:didvan/widgets/didvan/divider.dart'; import 'package:didvan/widgets/didvan/divider.dart';
import 'package:didvan/widgets/didvan/icon_button.dart'; import 'package:didvan/widgets/didvan/icon_button.dart';
import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/item_title.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FloatingNavigationBar extends StatefulWidget { class FloatingNavigationBar extends StatefulWidget {
@ -116,6 +118,7 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
value: _item.marked, value: _item.marked,
onMark: widget.onMark, onMark: widget.onMark,
onUnmark: widget.onUnmark, onUnmark: widget.onUnmark,
bigGestureSize: true,
), ),
SizedBox( SizedBox(
width: 48, width: 48,
@ -127,7 +130,6 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
_item.comments.toString(), _item.comments.toString(),
color: foregroundColor, color: foregroundColor,
), ),
const SizedBox(width: 4),
DidvanIconButton( DidvanIconButton(
gestureSize: 32, gestureSize: 32,
onPressed: () => Navigator.of(context).pushNamed( onPressed: () => Navigator.of(context).pushNamed(
@ -149,6 +151,7 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
value: _item.marked, value: _item.marked,
onMark: widget.onMark, onMark: widget.onMark,
onUnmark: widget.onUnmark, onUnmark: widget.onUnmark,
bigGestureSize: true,
), ),
if (_isRadar) if (_isRadar)
DidvanIconButton( DidvanIconButton(
@ -166,16 +169,43 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
ActionSheetUtils.showBottomSheet( ActionSheetUtils.showBottomSheet(
data: ActionSheetData( data: ActionSheetData(
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
MenuItem( const ItemTitle(
title: 'ارتباط با سردبیر', title: 'ارتباط با سردبیر',
onTap: () {},
icon: DidvanIcons.profile_regular, icon: DidvanIcons.profile_regular,
), ),
const SizedBox(height: 16),
for (var i = 0; i < _item.categories.length; i++) ...[
Padding(
padding: const EdgeInsets.only(right: 20),
child: MenuItem(
titleWidget: DidvanChip(label: _item.categories[i].label),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
Routes.direct,
arguments: _item.categories[i].id,
);
},
),
),
if (i != _item.categories.length - 1)
const Padding(
padding: EdgeInsets.only(right: 20),
child: DidvanDivider(verticalPadding: 8),
),
],
const DidvanDivider(), const DidvanDivider(),
MenuItem( MenuItem(
title: 'گزارش اشکال', title: 'گزارش اشکال',
onTap: () {}, onTap: () {
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
Routes.direct,
arguments: 0,
);
},
icon: DidvanIcons.description_regular, icon: DidvanIcons.description_regular,
), ),
], ],

View File

@ -1,3 +1,4 @@
import 'package:didvan/config/design_config.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class InkWrapper extends StatelessWidget { class InkWrapper extends StatelessWidget {
@ -13,7 +14,7 @@ class InkWrapper extends StatelessWidget {
this.highlightColor, this.highlightColor,
required this.child, required this.child,
this.onPressed, this.onPressed,
this.borderRadius, this.borderRadius = DesignConfig.lowBorderRadius,
}) : super(key: key); }) : super(key: key);
@override @override

View File

@ -6,12 +6,10 @@ import 'package:didvan/widgets/shimmer_placeholder.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart'; import 'package:didvan/services/network/request_helper.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:skeleton_text/skeleton_text.dart';
class SkeletonImage extends StatefulWidget { class SkeletonImage extends StatefulWidget {
final String imageUrl; final String imageUrl;
@ -110,16 +108,7 @@ class _SkeletonImageState extends State<SkeletonImage> {
), ),
), ),
progressIndicatorBuilder: (context, url, progress) => progressIndicatorBuilder: (context, url, progress) =>
SkeletonAnimation( const ShimmerPlaceholder(),
shimmerColor: Theme.of(context).colorScheme.border,
borderRadius: widget.borderRadius ?? DesignConfig.lowBorderRadius,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.disabledBackground,
borderRadius: widget.borderRadius,
),
),
),
); );
}), }),
); );

44
lib/widgets/tag_item.dart Normal file
View File

@ -0,0 +1,44 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class TagItem extends StatelessWidget {
final String label;
const TagItem({
Key? key,
required this.label,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 8,
),
decoration: BoxDecoration(
borderRadius: DesignConfig.lowBorderRadius,
border: Border.all(
color: Theme.of(context).colorScheme.focusedBorder,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
DidvanIcons.hashtag_regular,
color: Theme.of(context).colorScheme.focusedBorder,
),
DidvanText(
label,
color: Theme.of(context).colorScheme.focusedBorder,
style: Theme.of(context).textTheme.bodyText1,
),
],
),
);
}
}