import ‘dart:convert’;

import ‘package:flutter/material.dart’;
import ‘package:intl/locale.dart’ as intl;
import ‘package:patient_app/models/api_configuration.dart’;
import ‘package:patient_app/repositories/secure_store.dart’;

class SettingsRepository {
static final SettingsRepository _instance = SettingsRepository._internal();

factory SettingsRepository() => _instance;

SettingsRepository._internal();

static const _applicationIdStorageKey = ‘pbeApplicationId’;
static const _localeStorageKey = ‘pbeLocale’;
static const _apiConfigurationStorageKey = ‘pbeApiConfiguration’;

static const phoneAppLaunchPermission = ‘phoneAppLaunchPermission’;
static const mailAppLaunchPermission = ‘mailAppLaunchPermission’;
static const mapAppLaunchPermission = ‘mapAppLaunchPermission’;

String? _applicationId;
Locale? _locale;
ApiConfiguration? _apiConfiguration;

Future<void> store(String key, bool value) async {
SecureStore().write(key, value.toString());
}

Future<bool?> read(String key) async {
String? storedValue = await SecureStore().read(key);
if (storedValue != null) {
return storedValue.toLowerCase() == ‘true’;
}
return null;
}

Future<void> clear(String key) async {
await SecureStore().delete(key);
}

Future<void> storeApplicationId(String applicationId) async {
SecureStore().write(_applicationIdStorageKey, applicationId);
_applicationId = applicationId;
}

Future<String?> readApplicationId() async {
return _applicationId ??=
await SecureStore().read(_applicationIdStorageKey);
}

Future<void> clearApplicationId() async {
await SecureStore().delete(_applicationIdStorageKey);
_applicationId = null;
}

Future<void> storeLocale(Locale locale) async {
SecureStore().write(_localeStorageKey, locale.toLanguageTag());
_locale = locale;
}

Future<Locale?> readLocale() async {
if (_locale != null) {
return _locale;
}
String? localeIdentifier = await SecureStore().read(_localeStorageKey);
if (localeIdentifier != null) {
// Flutter/Flutter Locale class does not have a parser method,
// the intl package’s LocaleParser is used instead
// also see https://github.com/flutter/flutter/issues/55720
intl.Locale? parsedLocale = intl.Locale.tryParse(localeIdentifier);
if (parsedLocale != null) {
return Locale.fromSubtags(
languageCode: parsedLocale.languageCode,
countryCode: parsedLocale.countryCode,
scriptCode: parsedLocale.scriptCode,
);
}
}
return null;
}

Future<void> clearLocale() async {
await SecureStore().delete(_localeStorageKey);
_locale = null;
}

Future<void> storeApiConfiguration(ApiConfiguration apiConfiguration) async {
await SecureStore().write(
_apiConfigurationStorageKey, json.encode(apiConfiguration.toJson()));
_apiConfiguration = apiConfiguration;
}

Future<ApiConfiguration?> readApiConfiguration() async {
ApiConfiguration? apiConfiguration;

String? apiConfigurationString =
await SecureStore().read(_apiConfigurationStorageKey);
if (apiConfigurationString != null) {
try {
apiConfiguration =
ApiConfiguration.fromJson(json.decode(apiConfigurationString));
} catch (e) {
// do not prevent app start on failure, just delete old stored apiConfiguration
await clearApiConfiguration();
}
}
_apiConfiguration = apiConfiguration;
return _apiConfiguration;
}

Future<void> clearApiConfiguration() async {
await SecureStore().delete(_apiConfigurationStorageKey);
_apiConfiguration = null;
}
}

/* Future<void> store(String key, bool value) async {
SecureStore().write(key, value.toString());
}

Future<bool?> read(String key) async {
String? storedValue = await SecureStore().read(key);
if (storedValue != null) {
return storedValue.toLowerCase() == ‘true’;
}
return null;
}

Future<void> clear(String key) async {
await SecureStore().delete(key);
}

// Launch permissions
Future<void> storeLaunchPermission(String key, bool value) async {
await store(key, value);
}

Future<bool?> readLaunchPermission(String key) async {
return await read(key);
}

Future<void> clearLaunchPermission(String key) async {
await clear(key);
}*/

import ‘package:patient_app/repositories/settings_repository.dart’;

class LaunchPermissionProvider {
static final LaunchPermissionProvider _instance =
LaunchPermissionProvider._internal();

factory LaunchPermissionProvider() => _instance;

LaunchPermissionProvider._internal();

SettingsRepository settingsRepository = SettingsRepository();

// Phone app launch permission
Future<void> storePhoneAppLaunchPermission(bool permission) async {
await settingsRepository.store(
SettingsRepository.phoneAppLaunchPermission, permission);
}

Future<bool?> readPhoneAppLaunchPermission() async {
return await settingsRepository
.read(SettingsRepository.phoneAppLaunchPermission);
}

Future<void> clearPhoneAppLaunchPermission() async {
await settingsRepository.clear(SettingsRepository.phoneAppLaunchPermission);
}

// Mail app launch permission
Future<void> storeMailAppLaunchPermission(bool permission) async {
await settingsRepository.store(
SettingsRepository.mailAppLaunchPermission, permission);
}

Future<bool?> readMailAppLaunchPermission() async {
return await settingsRepository
.read(SettingsRepository.mailAppLaunchPermission);
}

Future<void> clearMailAppLaunchPermission() async {
await settingsRepository.clear(SettingsRepository.mailAppLaunchPermission);
}

// Map app launch permission
Future<void> storeMapAppLaunchPermission(bool permission) async {
await settingsRepository.store(
SettingsRepository.mapAppLaunchPermission, permission);
}

Future<bool?> readMapAppLaunchPermission() async {
return await settingsRepository
.read(SettingsRepository.mapAppLaunchPermission);
}

Future<void> clearMapAppLaunchPermission() async {
await settingsRepository.clear(SettingsRepository.mapAppLaunchPermission);
}
}

Funktioniert jetzt alles korrekt? Was kann ich jetzt damit tun?
Es soll jetzt ein Alert Dialog angezeigt werden wenn man in dem ContactInfo Widget auf ein icon clickt.
Dialog ist AlertDialog class - material library - Dart API (flutter.dev)
general_launchPermissionTitle | general_launchPermissionDescription | general_cancelButtonLabel
general_confirmButtonLabel
E-Mail App öffnen? | Bitte bestätigen Sie, dass Ihre Standard E-Mail App geöffnet wird.
Telefon App öffnen? | Bitte bestätigen Sie, dass Ihre Standard Telefon App geöffnet wird.
Karten App öffnen? | Bitte bestätigen Sie, dass Ihre Standard Karten App geöffnet wird.
Auf die Reinfolge der Buttons achten (Entweder erst Cancel dann Confirm, oder so wie es in anderen Dialogen ist)

import ‘package:flutter/material.dart’;
import ‘package:flutter_gen/gen_l10n/patient_app_localizations.dart’;
import ‘package:patient_app/models/location.dart’;
import ‘package:patient_app/settings.dart’ show AppSettingsProvider;
import ‘package:patient_app/theme/patient_app_colors.dart’;
import ‘package:patient_app/theme/patient_app_theme.dart’ as theme;
import ‘package:patient_app/tools/launcher_expert.dart’;
import ‘package:patient_app/widgets/decorative_image.dart’;
import ‘package:patient_app/widgets/patient_app_icon_button.dart’;
import ‘package:responsive_framework/responsive_framework.dart’;

class ContactInfo extends StatelessWidget {
const ContactInfo({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
final responsive = ResponsiveWrapper.of(context);

return ColoredBox(
color: responsive.isLargerThan(MOBILE)
? AppColors.grey
: AppColors.transparent,
child: ResponsiveRowColumn(
layout: responsive.isMobile
? ResponsiveRowColumnType.COLUMN
: ResponsiveRowColumnType.ROW,
children: [
const ResponsiveRowColumnItem(
rowFlex: 1,
child: _ResponsiveContactImage(),
),
ResponsiveRowColumnItem(
rowFlex: 1,
child: Center(
child: Padding(
padding: theme.commonEdgeInsetsFirstElement,
child: _buildContactActions(responsive, context),
),
),
),
],
),
);
}

Widget _buildContactActions(
ResponsiveWrapperData responsive, BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
AppLocalizations.of(context)!.homeHeadlineHospitalContact,
style: Theme.of(context).textTheme.headline2,
),
const SizedBox(height: theme.extraLargeSpacing),
ResponsiveRowColumn(
rowMainAxisAlignment: MainAxisAlignment.center,
rowCrossAxisAlignment: CrossAxisAlignment.start,
layout: responsive.isDesktop
? ResponsiveRowColumnType.ROW
: ResponsiveRowColumnType.COLUMN,
children: [
if (AppSettingsProvider().contact?.hasPhoneNumber == true)
ResponsiveRowColumnItem(
rowFlex: 1,
child: _buildTelephone(
AppSettingsProvider().contact!.phoneNumber!),
),
if (AppSettingsProvider().contact?.hasPhoneNumber == true)
const ResponsiveRowColumnItem(
child: SizedBox(
height: theme.mediumSpacing,
width: theme.mediumSpacing,
),
),
if (AppSettingsProvider().contact?.hasEmailAddress == true)
ResponsiveRowColumnItem(
rowFlex: 1,
child: _buildMail(AppSettingsProvider().contact!.eMailAddress!),
),
if (AppSettingsProvider().contact?.hasEmailAddress == true)
const ResponsiveRowColumnItem(
child: SizedBox(
height: theme.mediumSpacing,
width: theme.mediumSpacing,
),
),
if (AppSettingsProvider().contact?.hasAddress == true)
ResponsiveRowColumnItem(
rowFlex: 1,
child: _buildLocation(
AppSettingsProvider().contact!.streetName!,
AppSettingsProvider().contact!.zipCodeAndCity!,
AppSettingsProvider().contact?.geoLabel,
AppSettingsProvider().contact?.geoLocation),
),
],
),
],
);
}

Widget _buildTelephone(String phoneNumber) {
return Column(
children: [
_buildLauncherButton(
Icons.call_outlined,
LauncherExpert.createLaunchTelCallback(phoneNumber),
),
Text(phoneNumber),
],
);
}

Widget _buildMail(String emailAddress) {
return Column(
children: [
_buildLauncherButton(
Icons.email_outlined,
LauncherExpert.createLaunchEMailCallback(emailAddress),
),
Text(emailAddress),
],
);
}

Widget _buildLocation(String streetName, String zipCodeAndCity,
String? geoLabel, Position? geoLocation) {
return Column(
children: [
_buildLauncherButton(
Icons.place_outlined,
(geoLabel != null && geoLocation != null)
? LauncherExpert.createLaunchMapCallback(geoLabel, geoLocation)
: () {},
),
Text(
streetName,
textAlign: TextAlign.center,
),
Text(
zipCodeAndCity,
textAlign: TextAlign.center,
),
],
);
}

Widget _buildLauncherButton(
IconData iconData, VoidCallback? onPressedCallback) {
return PatientAppIconButton(
iconData: iconData,
onPressed: onPressedCallback,
);
}
}

class _ResponsiveContactImage extends StatelessWidget {
const _ResponsiveContactImage({
Key? key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
final responsive = ResponsiveWrapper.of(context);

if (responsive.isMobile) {
return AspectRatio(
aspectRatio: 19.0 / 9.0,
child: _buildImageContainer(),
);
} else {
return _buildImageContainer();
}
}

Widget _buildImageContainer() {
return DecorativeImage(
imagePath: AppSettingsProvider().assets.contactInfoImage,
maxHeight: theme.desktopLayoutImageMaxHeight);
}
}
○ Logged_in_user_service:
○ Zustimmung für E-Mail, Telefon, Map => Einzeln
○ Store-Methode: Konvertiert Boolean to String und speichert ihn
○ Ein Text mit Placeholder Variablen
○ Aktion statt Widget übergeben?

- Kein Context in Launchexpert => In BuildTelefon machen und dann in Launch
○ Das Speichern immer in Provider? BuisnessSchicht für Repository Zwischenschalten
○ launcherExpert.createLaunchTelCallBakc(phoonenumber)