Skip to content

Commit

Permalink
feature updates and bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nixrajput committed Sep 4, 2022
1 parent 352cfb6 commit 82f07b5
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 193 deletions.
134 changes: 134 additions & 0 deletions lib/global_widgets/expandable_text_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:social_media_app/constants/colors.dart';
import 'package:social_media_app/constants/styles.dart';
import 'package:social_media_app/helpers/utils.dart';

class NxExpandableText extends StatefulWidget {
const NxExpandableText({
super.key,
required this.text,
});

final String text;

@override
NxExpandableTextState createState() => NxExpandableTextState();
}

class NxExpandableTextState extends State<NxExpandableText> {
String? text;
bool canExpand = false;
bool isExpand = false;

@override
Widget build(BuildContext context) {
canExpand = widget.text.length >= 200;
text = canExpand
? (isExpand ? widget.text : widget.text.substring(0, 200))
: (widget.text);

return AnimatedSize(
duration: const Duration(milliseconds: 400),
child: canExpand
? buildTextWithLinks(text!.trim())
: RichText(
text: TextSpan(
text: text,
style: AppStyles.style14Normal.copyWith(
color: Theme.of(context).textTheme.bodyText1!.color,
height: 1.25,
),
),
),
);
}

Text buildTextWithLinks(String textToLink, {String? text}) => Text.rich(
TextSpan(
children: [
...linkify(textToLink),
TextSpan(
text: isExpand ? ' ...show less' : ' ...show more',
style: AppStyles.style14Bold.copyWith(
color: ColorValues.primaryColor,
),
recognizer: TapGestureRecognizer()
..onTap = () {
setState(() {
isExpand = !isExpand;
});
},
),
],
style: AppStyles.style14Normal.copyWith(
color: Theme.of(context).textTheme.bodyText1!.color,
height: 1.25,
),
),
);
}

const String urlPattern =
r"(https?|http)://([-A-Z0-9.]+)(/[-A-Z0-9+&@#/%=~_|!:,.;]*)?(\?[A-Z0-9+&@#/%=~_|!:‌​,.;]*)?";
const String emailPattern = r'\S+@\S+';
const String phonePattern = r'[\d-]{9,}';
final RegExp linkRegExp = RegExp(
'($urlPattern)|($emailPattern)|($phonePattern)',
caseSensitive: false);

WidgetSpan buildLinkComponent(String text, String linkToOpen) => WidgetSpan(
child: InkWell(
child: Text(
text,
style: AppStyles.style14Normal.copyWith(
color: ColorValues.primaryColor,
decoration: TextDecoration.underline,
),
),
onTap: () => AppUtils.openUrl(Uri.parse(linkToOpen)),
),
);

List<InlineSpan> linkify(String text) {
final list = <InlineSpan>[];
final match = linkRegExp.firstMatch(text);
if (match == null) {
list.add(
TextSpan(
text: text,
style: AppStyles.style14Normal.copyWith(
color: Theme.of(Get.context!).textTheme.bodyText1!.color,
),
),
);
return list;
}

if (match.start > 0) {
list.add(
TextSpan(
text: text.substring(0, match.start),
style: AppStyles.style14Normal.copyWith(
color: Theme.of(Get.context!).textTheme.bodyText1!.color,
),
),
);
}

final linkText = match.group(0);
if (linkText!.contains(RegExp(urlPattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, linkText));
} else if (linkText.contains(RegExp(emailPattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, 'mailto:$linkText'));
} else if (linkText.contains(RegExp(phonePattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, 'tel:$linkText'));
} else {
throw Exception('Unexpected match: $linkText');
}

list.addAll(linkify(text.substring(match.start + linkText.length)));

return list;
}
58 changes: 29 additions & 29 deletions lib/helpers/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,34 @@ import 'package:url_launcher/url_launcher.dart';
import 'package:video_compress/video_compress.dart';

abstract class AppUtils {
/// Close any open snack bar.
static void closeSnackBar() {
if (Get.isSnackbarOpen) Get.back<void>();
}

/// Close any open dialog.
static void closeDialog() {
if (Get.isDialogOpen!) Get.back<void>();
}

/// Close any open bottom sheet.
static void closeBottomSheet() {
if (Get.isBottomSheetOpen ?? false) Get.back<void>();
}

static void closeFocus() {
if (FocusManager.instance.primaryFocus!.hasFocus) {
FocusManager.instance.primaryFocus?.unfocus();
}
}

/// Show Loading Dialog
static void showLoadingDialog({double? value}) {
closeDialog();
Get.dialog<void>(
static void showLoadingDialog({double? value, bool? barrierDismissible}) {
Get.dialog(
WillPopScope(
onWillPop: () async => false,
child: Scaffold(
Expand Down Expand Up @@ -53,7 +76,7 @@ abstract class AppUtils {
Dimens.boxHeight12,
Text(
'Please wait...',
style: AppStyles.style16Bold.copyWith(
style: AppStyles.style16Normal.copyWith(
color: Theme.of(Get.context!).textTheme.bodyText1!.color,
),
),
Expand All @@ -63,7 +86,7 @@ abstract class AppUtils {
),
),
),
barrierDismissible: false,
barrierDismissible: barrierDismissible ?? false,
);
}

Expand Down Expand Up @@ -116,7 +139,6 @@ abstract class AppUtils {

static void showError(String message) {
closeSnackBar();
closeDialog();
closeBottomSheet();
if (message.isEmpty) return;
Get.rawSnackbar(
Expand Down Expand Up @@ -148,7 +170,6 @@ abstract class AppUtils {
WillPopScope(
onWillPop: () async => false,
child: Scaffold(
backgroundColor: Colors.black26,
body: Padding(
padding: Dimens.edgeInsets16,
child: Column(
Expand All @@ -165,7 +186,7 @@ abstract class AppUtils {
'No Internet!',
textAlign: TextAlign.center,
style: AppStyles.style24Bold.copyWith(
color: ColorValues.whiteColor,
color: ColorValues.errorColor,
),
),
],
Expand Down Expand Up @@ -290,27 +311,6 @@ abstract class AppUtils {
return CupertinoIcons.info_circle_fill;
}

/// Close any open snack bar.
static void closeSnackBar() {
if (Get.isSnackbarOpen) Get.back<void>();
}

/// Close any open dialog.
static void closeDialog() {
if (Get.isDialogOpen ?? false) Get.back<void>();
}

/// Close any open bottom sheet.
static void closeBottomSheet() {
if (Get.isBottomSheetOpen ?? false) Get.back<void>();
}

static void closeFocus() {
if (FocusManager.instance.primaryFocus!.hasFocus) {
FocusManager.instance.primaryFocus?.unfocus();
}
}

static Future<void> saveLoginDataToLocalStorage(
String token, int expiresAt) async {
final storage = GetStorage();
Expand Down
105 changes: 56 additions & 49 deletions lib/modules/home/views/widgets/post_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
import 'package:get/get.dart';
import 'package:get_time_ago/get_time_ago.dart';
import 'package:social_media_app/apis/models/entities/post.dart';
import 'package:social_media_app/constants/assets.dart';
import 'package:social_media_app/constants/colors.dart';
import 'package:social_media_app/constants/dimens.dart';
import 'package:social_media_app/constants/strings.dart';
import 'package:social_media_app/constants/styles.dart';
import 'package:social_media_app/extensions/string_extensions.dart';
import 'package:social_media_app/global_widgets/avatar_widget.dart';
import 'package:social_media_app/global_widgets/cached_network_image.dart';
import 'package:social_media_app/global_widgets/circular_asset_image.dart';
import 'package:social_media_app/global_widgets/circular_network_image.dart';
import 'package:social_media_app/global_widgets/elevated_card.dart';
import 'package:social_media_app/global_widgets/expandable_text_widget.dart';
import 'package:social_media_app/global_widgets/primary_icon_btn.dart';
import 'package:social_media_app/global_widgets/primary_text_btn.dart';
import 'package:social_media_app/global_widgets/video_player_widget.dart';
Expand Down Expand Up @@ -70,51 +69,23 @@ class _PostWidgetState extends State<PostWidget> {
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(widget.post.owner.avatar != null &&
widget.post.owner.avatar?.url != null)
? GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id),
child: NxCircleNetworkImage(
imageUrl: widget.post.owner.avatar!.url!,
radius: Dimens.twenty,
),
)
: GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id),
child: NxCircleAssetImage(
imgAsset: AssetValues.avatar,
radius: Dimens.twenty,
),
),
GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id,
),
child: AvatarWidget(
avatar: widget.post.owner.avatar,
size: Dimens.twenty,
),
),
Dimens.boxWidth8,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id),
child: Text(
"${widget.post.owner.fname} ${widget.post.owner.lname}",
style: AppStyles.style14Bold,
),
),
GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id),
child: Text(
"@${widget.post.owner.uname}",
style: TextStyle(
color: Theme.of(Get.context!)
.textTheme
.subtitle1!
.color,
),
),
)
_buildFullName(),
_buildUsername(),
],
),
],
Expand All @@ -134,6 +105,7 @@ class _PostWidgetState extends State<PostWidget> {
NxIconButton(
icon: CupertinoIcons.ellipsis_vertical,
iconSize: Dimens.twenty,
iconColor: Theme.of(context).textTheme.bodyText1!.color,
onTap: _showHeaderOptionBottomSheet,
),
],
Expand All @@ -144,6 +116,46 @@ class _PostWidgetState extends State<PostWidget> {
),
);

Widget _buildFullName() => GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(
widget.post.owner.id,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
RichText(
text: TextSpan(
text: '${widget.post.owner.fname} ${widget.post.owner.lname}',
style: AppStyles.style14Bold.copyWith(
color: Theme.of(Get.context!).textTheme.bodyText1!.color,
),
),
maxLines: 1,
),
if (widget.post.owner.isVerified) Dimens.boxWidth4,
if (widget.post.owner.isVerified)
Icon(
CupertinoIcons.checkmark_seal_fill,
color: Theme.of(Get.context!).brightness == Brightness.dark
? Theme.of(Get.context!).textTheme.bodyText1?.color
: ColorValues.primaryColor,
size: Dimens.fourteen,
)
],
),
);

Widget _buildUsername() => GestureDetector(
onTap: () => RouteManagement.goToUserProfileView(widget.post.owner.id),
child: Text(
"@${widget.post.owner.uname}",
style: TextStyle(
color: Theme.of(Get.context!).textTheme.subtitle1!.color,
),
),
);

Widget _buildPostBody() {
return Column(
mainAxisSize: MainAxisSize.min,
Expand Down Expand Up @@ -228,13 +240,8 @@ class _PostWidgetState extends State<PostWidget> {
if (widget.post.caption != null && widget.post.caption!.isNotEmpty)
Dimens.boxHeight4,
if (widget.post.caption != null && widget.post.caption!.isNotEmpty)
RichText(
text: TextSpan(
text: widget.post.caption!,
style: AppStyles.style14Normal.copyWith(
color: Theme.of(Get.context!).textTheme.bodyText1!.color,
),
),
NxExpandableText(
text: widget.post.caption!,
),
Dimens.dividerWithHeight,
Padding(
Expand Down
Loading

0 comments on commit 82f07b5

Please sign in to comment.