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

View File

@ -7,14 +7,18 @@ import 'package:flutter/material.dart';
class DidvanButton extends StatelessWidget {
final VoidCallback? onPressed;
final String? title;
final double? width;
final ButtonStyleMode style;
final bool enabled;
final double? height;
const DidvanButton({
Key? key,
this.onPressed,
this.title,
this.style = ButtonStyleMode.primary,
this.enabled = true,
this.width,
this.height = 48,
}) : super(key: key);
@override
@ -42,8 +46,8 @@ class DidvanButton extends StatelessWidget {
default:
}
return SizedBox(
height: 48,
width: double.infinity,
height: height,
width: width ?? double.infinity,
child: MaterialButton(
shape: RoundedRectangleBorder(
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:didvan/utils/date_time.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/skeleton_image.dart';
import 'package:didvan/widgets/tag_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
class DidvanPageView extends StatefulWidget {
final List items;
final int initialIndex;
final bool isRadar;
final ScrollController? scrollController;
final void Function(int index) onPageChanged;
const DidvanPageView({
Key? key,
@ -15,6 +21,7 @@ class DidvanPageView extends StatefulWidget {
required this.items,
this.scrollController,
required this.onPageChanged,
required this.isRadar,
}) : super(key: key);
@override
@ -36,62 +43,76 @@ class _DidvanPageViewState extends State<DidvanPageView> {
viewportFraction: 0.94,
enableInfiniteScroll: false,
),
itemBuilder: (context, index, realIndex) => SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
controller: index == 1 ? widget.scrollController : null,
physics: const BouncingScrollPhysics(),
padding: EdgeInsets.only(
left: 4,
right: 4,
top: 16 + deviceTopPadding,
bottom: 92,
),
child: DidvanCard(
padding: EdgeInsets.zero,
enableBorder: false,
child: Builder(
builder: (context) {
final item = widget.items[index];
if (item == null) {
return const SizedBox();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkeletonImage(
imageUrl: item.image,
aspectRatio: 16 / 9,
),
const SizedBox(height: 20),
for (var i = 0; i < item.contents.length; i++)
itemBuilder: (context, index, realIndex) => Directionality(
textDirection: TextDirection.rtl,
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
controller: index == 1 ? widget.scrollController : null,
physics: const BouncingScrollPhysics(),
padding: EdgeInsets.only(
left: 4,
right: 4,
top: 16 + deviceTopPadding,
bottom: 92,
),
child: DidvanCard(
padding: EdgeInsets.zero,
enableBorder: false,
child: Builder(
builder: (context) {
final item = widget.items[index];
if (item == null) {
return const SizedBox();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkeletonImage(
imageUrl: item.image,
aspectRatio: 16 / 9,
),
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
child: Builder(
builder: (context) {
final content = item.contents[i];
if (content.text != null) {
return DidvanText(
item.contents[i].text!,
);
}
if (content.image != null) {
return SkeletonImage(
imageUrl: content.image!,
aspectRatio: 16 / 9,
);
}
return const SizedBox();
},
padding: const EdgeInsets.symmetric(horizontal: 16),
child: DidvanText(
item.title,
style: Theme.of(context).textTheme.subtitle1,
),
),
const SizedBox(height: 20),
],
);
},
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: _subtitle(item),
),
for (var i = 0; i < item.contents.length; i++)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
child: _contentBuilder(item, i),
),
if (item.tags.isNotEmpty) const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (var i = 0; i < item.tags.length; i++)
TagItem(label: item.tags[i].label),
],
),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: DidvanDivider(),
),
],
);
},
),
),
),
),
@ -99,4 +120,53 @@ 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 AppBarData appBarData;
final EdgeInsets padding;
final Color? backgroundColor;
const DidvanScaffold({
Key? key,
this.slivers,
required this.appBarData,
this.children,
this.padding = const EdgeInsets.symmetric(horizontal: 16),
this.backgroundColor,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Scaffold(
backgroundColor: backgroundColor,
body: Padding(
padding: EdgeInsets.only(top: statusBarHeight),
child: CustomScrollView(
slivers: [
SliverAppBar(
toolbarHeight: kToolbarHeight,
backgroundColor: Theme.of(context).backgroundColor,
backgroundColor:
backgroundColor ?? Theme.of(context).colorScheme.background,
automaticallyImplyLeading: false,
pinned: true,
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 int? maxLines;
final bool isEnglishFont;
final TextOverflow? overflow;
const DidvanText(
this.text, {
@ -20,6 +21,7 @@ class DidvanText extends StatelessWidget {
this.textAlign = TextAlign.right,
this.maxLines,
this.isEnglishFont = false,
this.overflow,
}) : super(key: key);
@override
@ -31,6 +33,7 @@ class DidvanText extends StatelessWidget {
fontWeight: fontWeight,
fontSize: fontSize,
)).copyWith(fontFamily: isEnglishFont ? 'Dana' : null),
overflow: overflow,
textAlign: textAlign,
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/utils/action_sheet.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/icon_button.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/item_title.dart';
import 'package:flutter/material.dart';
class FloatingNavigationBar extends StatefulWidget {
@ -116,6 +118,7 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
value: _item.marked,
onMark: widget.onMark,
onUnmark: widget.onUnmark,
bigGestureSize: true,
),
SizedBox(
width: 48,
@ -127,7 +130,6 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
_item.comments.toString(),
color: foregroundColor,
),
const SizedBox(width: 4),
DidvanIconButton(
gestureSize: 32,
onPressed: () => Navigator.of(context).pushNamed(
@ -149,6 +151,7 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
value: _item.marked,
onMark: widget.onMark,
onUnmark: widget.onUnmark,
bigGestureSize: true,
),
if (_isRadar)
DidvanIconButton(
@ -166,16 +169,43 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
ActionSheetUtils.showBottomSheet(
data: ActionSheetData(
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MenuItem(
const ItemTitle(
title: 'ارتباط با سردبیر',
onTap: () {},
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(),
MenuItem(
title: 'گزارش اشکال',
onTap: () {},
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
Routes.direct,
arguments: 0,
);
},
icon: DidvanIcons.description_regular,
),
],

View File

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

View File

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

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,
),
],
),
);
}
}