Skip to content

Commit

Permalink
Merge pull request #263 from takenet/release/0.1.2
Browse files Browse the repository at this point in the history
[Release] 0.1.2
  • Loading branch information
mpamaro authored Jun 21, 2024
2 parents fbf3383 + 8b7d939 commit 672429d
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 96 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.2

- [DSLocationMessageBubble] Added app selection when touching the map preview.

## 0.1.1

- [DSVideoMessageBubble] Added title to this bubble.
Expand Down
231 changes: 162 additions & 69 deletions lib/src/widgets/chat/ds_location_message_bubble.widget.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:map_launcher/map_launcher.dart';

import '../../enums/ds_align.enum.dart';
import '../../enums/ds_border_radius.enum.dart';
import '../../models/ds_message_bubble_style.model.dart';
import '../../models/ds_reply_content.model.dart';
import '../../services/ds_auth.service.dart';
import '../../services/ds_bottom_sheet.service.dart';
import '../../themes/colors/ds_colors.theme.dart';
import '../../themes/icons/ds_icons.dart';
import '../../utils/ds_utils.util.dart';
import '../animations/ds_spinner_loading.widget.dart';
import '../buttons/ds_icon_button.widget.dart';
import '../texts/ds_body_text.widget.dart';
import '../texts/ds_headline_large_text.widget.dart';
import '../utils/ds_cached_network_image_view.widget.dart';
import '../utils/ds_divider.widget.dart';
import 'ds_message_bubble.widget.dart';

class DSLocationMessageBubble extends StatelessWidget {
class DSLocationMessageBubble extends StatefulWidget {
final DSAlign align;
final DSMessageBubbleStyle style;
final String? title;
Expand All @@ -35,81 +40,169 @@ class DSLocationMessageBubble extends StatelessWidget {
}) : style = style ?? DSMessageBubbleStyle();

@override
Widget build(BuildContext context) {
final foregroundColor = style.isLightBubbleBackground(align)
State<DSLocationMessageBubble> createState() =>
_DSLocationMessageBubbleState();
}

class _DSLocationMessageBubbleState extends State<DSLocationMessageBubble> {
late final Future<List<AvailableMap>> _installedMaps;
late final bool _hasValidCoordinates;
late final Color _foregroundColor;
late final double? _doubleLatitude;
late final double? _doubleLongitude;

@override
void initState() {
super.initState();

_foregroundColor = widget.style.isLightBubbleBackground(widget.align)
? DSColors.neutralDarkCity
: DSColors.neutralLightSnow;

final lat = double.tryParse(latitude);
final long = double.tryParse(longitude);

final hasValidCoordinates = lat != null && long != null;
return GestureDetector(
onTap: () async {
final availableMaps = await MapLauncher.installedMaps;

if (hasValidCoordinates) {
await availableMaps.first.showMarker(
coords: Coords(lat, long),
title: title ?? '',
);
}
},
child: DSMessageBubble(
shouldUseDefaultSize: true,
defaultMaxSize: DSUtils.bubbleMinSize,
defaultMinSize: DSUtils.bubbleMinSize,
borderRadius: borderRadius,
replyContent: replyContent,
padding: EdgeInsets.zero,
align: align,
style: style,
child: Padding(
padding: replyContent == null
? EdgeInsets.zero
: const EdgeInsets.only(top: 8.0),
_doubleLatitude = double.tryParse(widget.latitude);
_doubleLongitude = double.tryParse(widget.longitude);

_hasValidCoordinates = _doubleLatitude != null && _doubleLongitude != null;

_installedMaps = MapLauncher.installedMaps;
}

@override
Widget build(BuildContext context) => GestureDetector(
onTap: _hasValidCoordinates ? _openMapList : null,
child: DSMessageBubble(
shouldUseDefaultSize: true,
defaultMaxSize: DSUtils.bubbleMinSize,
defaultMinSize: DSUtils.bubbleMinSize,
borderRadius: widget.borderRadius,
replyContent: widget.replyContent,
padding: EdgeInsets.zero,
align: widget.align,
style: widget.style,
child: _buildBody(),
),
);

Widget _buildBody() => Padding(
padding: widget.replyContent == null
? EdgeInsets.zero
: const EdgeInsets.only(top: 8.0),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
hasValidCoordinates
? DSCachedNetworkImageView(
url:
'https://maps.googleapis.com/maps/api/staticmap?&size=360x360&markers=$latitude,$longitude&key=${DSAuthService.googleKey}',
placeholder: (_, __) => _buildLoading(),
align: align,
style: style,
)
: SizedBox(
width: 240,
height: 240,
child: Icon(
DSIcons.file_image_broken_outline,
size: 80,
color: style.isLightBubbleBackground(align)
? DSColors.neutralMediumElephant
: DSColors.neutralMediumCloud,
),
),
if (title?.isNotEmpty ?? false)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Align(
alignment: Alignment.topLeft,
child: DSBodyText(
title!,
color: foregroundColor,
isSelectable: true,
overflow: TextOverflow.visible,
),
),
),
_hasValidCoordinates
? _buildThumbnail()
: _buildBrokenThumbnail(),
if (widget.title?.isNotEmpty ?? false) _buildTitle(),
],
),
),
);

Widget _buildTitle() => Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Align(
alignment: Alignment.topLeft,
child: DSBodyText(
widget.title!,
color: _foregroundColor,
isSelectable: true,
overflow: TextOverflow.visible,
),
),
);

Widget _buildThumbnail() => DSCachedNetworkImageView(
url:
'https://maps.googleapis.com/maps/api/staticmap?&size=360x360&markers=${widget.latitude},${widget.longitude}&key=${DSAuthService.googleKey}',
placeholder: (_, __) => _buildLoading(),
align: widget.align,
style: widget.style,
);

Widget _buildBrokenThumbnail() => SizedBox(
width: 240,
height: 240,
child: Icon(
DSIcons.file_image_broken_outline,
size: 80,
color: widget.style.isLightBubbleBackground(widget.align)
? DSColors.neutralMediumElephant
: DSColors.neutralMediumCloud,
),
);

void _openMapList() {
DSBottomSheetService(
context: context,
fixedHeader: _buildBottomSheetHeader(),
builder: (_) => _buildBottomSheetBody(),
).show();
}

Widget _buildBottomSheetHeader() {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: SafeArea(
top: false,
bottom: false,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
DSHeadlineLargeText(
'Selecione uma ação',
),
DSIconButton(
onPressed: () {
Get.back();
},
icon: const Icon(DSIcons.close_outline,
color: DSColors.neutralDarkRooftop),
),
],
),
),
),
const DSDivider()
],
);
}

Widget _buildBottomSheetBody() {
return SafeArea(
child: FutureBuilder(
future: _installedMaps,
builder: (_, snapshot) => snapshot.hasData && snapshot.data!.isNotEmpty
? ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (_, index) {
final map = snapshot.data![index];

return ListTile(
onTap: () {
map.showMarker(
coords: Coords(
_doubleLatitude!,
_doubleLongitude!,
),
title: widget.title ?? '',
);

Get.back();
},
title: DSBodyText(
'Abrir com ${map.mapName}',
),
);
},
)
: _buildLoading(),
),
);
}
Expand All @@ -123,7 +216,7 @@ class DSLocationMessageBubble extends StatelessWidget {
),
child: Center(
child: DSSpinnerLoading(
color: style.isLightBubbleBackground(align)
color: widget.style.isLightBubbleBackground(widget.align)
? DSColors.primaryNight
: DSColors.neutralLightSnow,
size: 32.0,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: blip_ds
description: Blip Design System for Flutter.
version: 0.1.1
version: 0.1.2
homepage: https://github.com/takenet/blip-ds-flutter#readme
repository: https://github.com/takenet/blip-ds-flutter

Expand Down
Loading

0 comments on commit 672429d

Please sign in to comment.