diff --git a/example/lib/pages/components/html_view.dart b/example/lib/pages/components/html_view.dart
index 292be2d..6ffc12d 100644
--- a/example/lib/pages/components/html_view.dart
+++ b/example/lib/pages/components/html_view.dart
@@ -725,6 +725,9 @@ class HtmlPreview extends StatelessWidget {
return ZdsHtmlContainer(
data,
showReadMore: false,
+ onLinkTap: (_, __, ___) {
+ print('Link tapped');
+ },
);
},
itemCount: htmlList.length,
diff --git a/lib/src/components/organisms/camera/camera_page.dart b/lib/src/components/organisms/camera/camera_page.dart
index 4521593..d748a25 100644
--- a/lib/src/components/organisms/camera/camera_page.dart
+++ b/lib/src/components/organisms/camera/camera_page.dart
@@ -46,6 +46,7 @@ class ZdsCamera extends StatelessWidget {
this.cameraMode = ZdsCameraMode.photo,
this.maxVideoDuration,
this.showPreview = true,
+ this.saveGPSLocation = false,
this.photoPathBuilder,
this.videoPathBuilder,
this.filters,
@@ -60,6 +61,9 @@ class ZdsCamera extends StatelessWidget {
/// - [showPreview] determines whether the camera preview is shown before selecting a file, enabled by default.
final bool showPreview;
+ /// - [saveGPSLocation] determines whether the camera output be tagged with GPS location, disabled by default.
+ final bool saveGPSLocation;
+
/// A builder for the path to save the photo or video file.
///
/// This builder is used to specify the path to save the photo or video file.
@@ -87,6 +91,7 @@ class ZdsCamera extends StatelessWidget {
BuildContext context, {
bool showPreview = true,
bool rootNavigator = true,
+ bool saveGPSLocation = false,
CaptureRequestBuilder? photoPathBuilder,
CaptureRequestBuilder? videoPathBuilder,
List? filters,
@@ -98,6 +103,7 @@ class ZdsCamera extends StatelessWidget {
ZdsFadePageRouteBuilder(
builder: (context) => ZdsCamera(
showPreview: showPreview,
+ saveGPSLocation: saveGPSLocation,
photoPathBuilder: photoPathBuilder,
videoPathBuilder: videoPathBuilder,
filters: filters,
@@ -242,7 +248,7 @@ class ZdsCamera extends StatelessWidget {
),
)
: SaveConfig.photo(
- exifPreferences: ExifPreferences(saveGPSLocation: true),
+ exifPreferences: ExifPreferences(saveGPSLocation: saveGPSLocation),
pathBuilder: videoPathBuilder ??
(sensors) async {
final Directory extDir = await getTemporaryDirectory();
@@ -270,7 +276,8 @@ class ZdsCamera extends StatelessWidget {
..add(DiagnosticsProperty('showPreview', showPreview))
..add(ObjectFlagProperty.has('photoPathBuilder', photoPathBuilder))
..add(ObjectFlagProperty.has('videoPathBuilder', videoPathBuilder))
- ..add(IterableProperty('filters', filters));
+ ..add(IterableProperty('filters', filters))
+ ..add(DiagnosticsProperty('saveGPSLocation', saveGPSLocation));
}
}
@@ -357,7 +364,10 @@ class _CameraWrapperState extends State<_CameraWrapper> {
children: [
if (widget.state is! VideoRecordingCameraState)
GestureDetector(
- onTap: () => Navigator.of(context).pop(),
+ onTap: () async {
+ await ZdsSystemChrome.resetAppOrientations();
+ if (context.mounted) Navigator.of(context).pop();
+ },
child: AwesomeCircleWidget(
theme: theme,
size: 45,
@@ -782,18 +792,23 @@ class _PreviewActions extends StatelessWidget {
elevation: 0,
shape: const CircleBorder(),
backgroundColor: Colors.black38,
- onPressed: () => Navigator.of(context).pop(false),
+ onPressed: () async => _onPop(context, false),
child: const Icon(Icons.close, color: ZetaColorBase.white),
),
FloatingActionButton(
elevation: 0,
shape: const CircleBorder(),
backgroundColor: Colors.black38,
- onPressed: () => Navigator.of(context).pop(true),
+ onPressed: () async => _onPop(context, true),
child: const Icon(Icons.done, color: ZetaColorBase.white),
),
],
),
);
}
+
+ Future _onPop(BuildContext context, bool result) async {
+ await ZdsSystemChrome.resetAppOrientations();
+ if (context.mounted) Navigator.of(context).pop(result);
+ }
}
diff --git a/lib/src/components/organisms/html_preview/table_html_extension.dart b/lib/src/components/organisms/html_preview/table_html_extension.dart
index 94977c8..4ec36dc 100644
--- a/lib/src/components/organisms/html_preview/table_html_extension.dart
+++ b/lib/src/components/organisms/html_preview/table_html_extension.dart
@@ -1,10 +1,12 @@
import 'dart:math';
+import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_table/flutter_html_table.dart';
import 'package:flutter_layout_grid/flutter_layout_grid.dart';
import 'package:html/dom.dart' as html;
+import 'package:zeta_flutter/zeta_flutter.dart';
/// Supported tags for [TableHtmlExtension] to use with flutter_html library.
const zdsTableTags = {
@@ -261,6 +263,18 @@ class ZdsTableHtmlExtension extends HtmlExtension {
),
node: context.node,
);
+ } else if (context.elementName == 'a') {
+ return InteractiveElement(
+ name: context.elementName,
+ children: children,
+ href: context.attributes['href'],
+ style: Style(
+ color: ZetaColorBase.blue.shade50,
+ textDecoration: TextDecoration.underline,
+ ),
+ node: context.node,
+ elementId: context.id,
+ );
}
return StyledElement(
@@ -295,6 +309,14 @@ class ZdsTableHtmlExtension extends HtmlExtension {
),
),
);
+ } else if (context.elementName == 'a' &&
+ context.inlineSpanChildren != null &&
+ context.inlineSpanChildren!.isNotEmpty) {
+ return TextSpan(
+ children: context.inlineSpanChildren!.map((childSpan) {
+ return _processInteractableChild(context, childSpan);
+ }).toList(),
+ );
}
return WidgetSpan(
@@ -306,6 +328,35 @@ class ZdsTableHtmlExtension extends HtmlExtension {
}
}
+InlineSpan _processInteractableChild(
+ ExtensionContext context,
+ InlineSpan childSpan,
+) {
+ void onTap() => context.parser.internalOnAnchorTap?.call(
+ (context.styledElement! as InteractiveElement).href,
+ context.attributes,
+ context.node as html.Element,
+ );
+
+ if (childSpan is TextSpan) {
+ return TextSpan(
+ text: childSpan.text,
+ children: childSpan.children?.map((e) => _processInteractableChild(context, e)).toList(),
+ style: childSpan.style,
+ semanticsLabel: childSpan.semanticsLabel,
+ recognizer: TapGestureRecognizer()..onTap = onTap,
+ );
+ } else {
+ return WidgetSpan(
+ child: GestureDetector(
+ key: AnchorKey.of(context.parser.key, context.styledElement),
+ onTap: onTap,
+ child: (childSpan as WidgetSpan).child,
+ ),
+ );
+ }
+}
+
/// Recursively gets a flattened list of the table's
/// cell descendants
List _getCellDescendants(List children) {
diff --git a/lib/src/utils/tools.dart b/lib/src/utils/tools.dart
index 12c0ec0..8bbfafb 100644
--- a/lib/src/utils/tools.dart
+++ b/lib/src/utils/tools.dart
@@ -4,5 +4,6 @@ export 'tools/frame_mixin.dart';
export 'tools/keyboard_dismiss.dart';
export 'tools/modifiers.dart';
export 'tools/nested_flow.dart';
+export 'tools/system_chrome.dart';
export 'tools/tab_navigator.dart';
export 'tools/utils.dart';
diff --git a/lib/src/utils/tools/system_chrome.dart b/lib/src/utils/tools/system_chrome.dart
new file mode 100644
index 0000000..25c26c0
--- /dev/null
+++ b/lib/src/utils/tools/system_chrome.dart
@@ -0,0 +1,48 @@
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+/// Controls orientations of the application interface
+class ZdsSystemChrome {
+ static List _orientations = [
+ DeviceOrientation.portraitUp,
+ DeviceOrientation.portraitDown,
+ DeviceOrientation.landscapeLeft,
+ DeviceOrientation.landscapeRight,
+ ];
+
+ /// Get the set of orientations the application interface can
+ /// be displayed in.
+ static List get appOrientations => _orientations;
+
+ /// Specifies the set of orientations the application interface can
+ /// be displayed in.
+ ///
+ /// The `orientation` argument is a list of [DeviceOrientation] enum values.
+ static Future setPreferredOrientations(List? orientations) async {
+ final platformMediaQuery = MediaQueryData.fromView(PlatformDispatcher.instance.views.first);
+ if (orientations == null || orientations.isEmpty) {
+ if (platformMediaQuery.size.shortestSide < 600) {
+ _orientations = [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown];
+ } else {
+ _orientations = [
+ DeviceOrientation.portraitUp,
+ DeviceOrientation.portraitDown,
+ DeviceOrientation.landscapeLeft,
+ DeviceOrientation.landscapeRight,
+ ];
+ }
+ } else {
+ _orientations = orientations;
+ }
+
+ await resetAppOrientations();
+ }
+
+ /// Set the set of orientations the application interface can
+ /// be displayed in.
+ static Future resetAppOrientations() async {
+ await SystemChrome.setPreferredOrientations(appOrientations);
+ }
+}