VHS-Karten integriert, Bildzoom ergänzt und Chat-IDs korrigiert
Unterschriftenerfassung dauerhaft auf Deutsch anzeigen, lokale VHS-Buildkonfiguration und Regressionstests ergänzen sowie Version auf 357.0.0+357 anheben.
This commit is contained in:
1 parent
c0b667c4ee
commit
5e7babf265
26 files changed
+752
-93
No files matched your search
+40
-35
@@ -114,14 +114,13 @@ class _FileListItemState extends State<_FileListItem> {
|
||||
},
|
||||
);
|
||||
} else if (widget.file.isImage) {
|
||||
// Show image in a dialog on top of the files dialog
|
||||
// Bildanhänge wie PDFs vergrößern und im gezoomten Zustand verschieben.
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return Dialog(
|
||||
insetPadding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AppBar(
|
||||
title: Text(widget.file.name),
|
||||
@@ -131,41 +130,47 @@ class _FileListItemState extends State<_FileListItem> {
|
||||
),
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
Flexible(
|
||||
child: Image.network(
|
||||
widget.file.url,
|
||||
fit: BoxFit.contain,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.error_outline,
|
||||
size: 64,
|
||||
color: Colors.red,
|
||||
Expanded(
|
||||
child: InteractiveViewer(
|
||||
minScale: 1,
|
||||
maxScale: 5,
|
||||
child: SizedBox.expand(
|
||||
child: Image.network(
|
||||
widget.file.url,
|
||||
fit: BoxFit.contain,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Fehler beim Laden des Bildes:\n$error',
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.error_outline,
|
||||
size: 64,
|
||||
color: Colors.red,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Fehler beim Laden des Bildes:\n$error',
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stadtbote/content_views/vhs_map_page.dart';
|
||||
import 'package:stadtbote/model/job.dart';
|
||||
import 'package:stadtbote/model/job_tour.dart';
|
||||
import 'package:stadtbote/popups/map_popup.dart';
|
||||
import 'package:stadtbote/tools/app_localizations.dart';
|
||||
import 'package:stadtbote/tools/util.dart';
|
||||
|
||||
Future<void> showJobMapPopup(
|
||||
BuildContext context,
|
||||
Job job, {
|
||||
JobTour? currentTour,
|
||||
}) async {
|
||||
final mapUrl = job.mapUrl?.trim();
|
||||
if (mapUrl != null && mapUrl.isNotEmpty) {
|
||||
final uri = Uri.tryParse(mapUrl);
|
||||
if (uri == null) {
|
||||
await showAlertDialog('error'.tr, 'Die Kartenadresse ist ungültig.');
|
||||
return;
|
||||
}
|
||||
await Navigator.of(
|
||||
context,
|
||||
).push<void>(MaterialPageRoute(builder: (_) => VhsMapPage(uri: uri)));
|
||||
return;
|
||||
}
|
||||
|
||||
final tours = job.tours;
|
||||
final tour = currentTour ?? (tours.isNotEmpty ? tours.first : null);
|
||||
if (tour?.pos == null) {
|
||||
await showAlertDialog('information'.tr, 'no_position'.tr);
|
||||
return;
|
||||
}
|
||||
await showMapPopup(context, tour!, tours);
|
||||
}
|
||||
@@ -13,7 +13,7 @@ showSignaturePopup(BuildContext context, TaskInfo taskInfo, Function(String?) on
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (bool didPop, dynamic result) async {
|
||||
if (!didPop) {
|
||||
final shouldPop = await taskDialogSecurityException(context);
|
||||
final shouldPop = await taskDialogSecurityException(context, language: AppLanguage.german);
|
||||
if (shouldPop) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
if (context.mounted) {
|
||||
@@ -79,13 +79,18 @@ showSignaturePopup(BuildContext context, TaskInfo taskInfo, Function(String?) on
|
||||
),
|
||||
),
|
||||
getDefaultButton(
|
||||
'apply'.tr,
|
||||
AppLocalizations.tr('apply', language: AppLanguage.german),
|
||||
buttonHeight: 50,
|
||||
() => {
|
||||
if (controller.points.length > 50)
|
||||
{Navigator.of(context).pop(), onFinished(convertPoints(controller.points))}
|
||||
else
|
||||
{showAlertDialog('error'.tr, 'signature_too_short'.tr)}
|
||||
{
|
||||
showAlertDialog(
|
||||
AppLocalizations.tr('error', language: AppLanguage.german),
|
||||
AppLocalizations.tr('signature_too_short', language: AppLanguage.german),
|
||||
)
|
||||
}
|
||||
})
|
||||
],
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user