dart_pkpass/lib/src/models/pass_structure_dictionary.dart
The one with the braid e345763813 feat: add String localization support
Signed-off-by: The one with the braid <the-one@with-the-braid.cf>
2023-08-27 19:50:37 +02:00

236 lines
7.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:intl/locale.dart';
import 'package:pkpass/pkpass.dart';
import 'package:pkpass/src/utils/mabe_decode.dart';
/// Keys that define the structure of the pass.
///
/// These keys are used for all pass styles and partition the fields into the various parts of the pass.
class PassStructureDictionary {
/// Fields to be displayed in the header on the front of the pass.
///
/// Use header fields sparingly; unlike all other fields, they remain visible when a stack of passes are displayed.
final List<DictionaryField> headerFields;
/// Fields to be displayed prominently on the front of the pass.
final List<DictionaryField> primaryFields;
/// Fields to be displayed on the front of the pass.
final List<DictionaryField> secondaryFields;
/// Fields to be on the back of the pass.
final List<DictionaryField> backFields;
/// Additional fields to be displayed on the front of the pass.
final List<DictionaryField> auxiliaryFields;
/// Required for boarding passes; otherwise not allowed. Type of transit.
final TransitType? transitType;
const PassStructureDictionary({
this.headerFields = const [],
this.primaryFields = const [],
this.secondaryFields = const [],
this.backFields = const [],
this.auxiliaryFields = const [],
this.transitType,
});
factory PassStructureDictionary.fromJson(Map<String, Object?> json) =>
PassStructureDictionary(
headerFields: (json['headerFields'] as List?)
?.map((i) => DictionaryField.fromJson(i))
.toList() ??
[],
primaryFields: (json['primaryFields'] as List?)
?.map((i) => DictionaryField.fromJson(i))
.toList() ??
[],
secondaryFields: (json['secondaryFields'] as List?)
?.map((i) => DictionaryField.fromJson(i))
.toList() ??
[],
backFields: (json['backFields'] as List?)
?.map((i) => DictionaryField.fromJson(i))
.toList() ??
[],
auxiliaryFields: (json['auxiliaryFields'] as List?)
?.map((i) => DictionaryField.fromJson(i))
.toList() ??
[],
transitType: _TarnsitType.parse(json['transitType'] as String?),
);
}
/// Information about a field.
class DictionaryField {
/// The key must be unique within the scope of the entire pass. For example, “departure-gate.”
final String key;
/// Value of the field, for example, 42.
final DictionaryValue value;
/// Label text for the field.
final String? label;
/// Format string for the alert text that is displayed when the pass is updated. The format string must contain the escape %@, which is replaced with the fields new value. For example, “Gate changed to %@.”
///
/// If you dont specify a change message, the user isnt notified when the field changes.
final String? changeMessage;
/// Alignment for the fields contents.
final PassTextAlign? textAlignment;
/// Attributed value of the field.
///
/// The value may contain HTML markup for links. Only the <a> tag and its href attribute are supported. For example, the following is key-value pair specifies a link with the text “Edit my profile”:
///
/// "attributedValue": "<a href='http://example.com/customers/123'>Edit my profile</a>"
///
/// This keys value overrides the text specified by the value key.
final DictionaryValue? attributedValue;
const DictionaryField({
required this.key,
required this.value,
this.label,
this.changeMessage,
this.textAlignment,
this.attributedValue,
});
factory DictionaryField.fromJson(Map<String, Object?> json) =>
DictionaryField(
key: json['key'] as String,
value: DictionaryValue.parse(json['value'] as String),
label: json['label'] as String?,
changeMessage: json['changeMessage'] as String?,
textAlignment:
MaybeDecode.maybeTextAlign(json['textAlignment'] as String?),
attributedValue: json['attributedValue'] == null
? null
: DictionaryValue.parse(json['attributedValue'] as String),
);
/// Localized version of [label] based on given [locale] and [pass].
String? getLocalizedLabel(PassFile pass, Locale? locale) {
final localizations = pass.getLocalizations(locale);
print(localizations);
return localizations?[label] ?? label;
}
/// Localized version of [changeMessage] based on given [locale] and [pass].
String? getLocalizedChangeMessage(PassFile pass, Locale? locale) {
final localizations = pass.getLocalizations(locale);
return localizations?[changeMessage] ?? changeMessage;
}
}
/// represents the possible values of a [DictionaryField].
abstract class DictionaryValue {
const DictionaryValue();
/// parses the correct [DictionaryValue] implementor based on a given [value].
factory DictionaryValue.parse(String value) {
final number = int.tryParse(value);
if (number != null) return NumberDictionaryValue(number);
final dateTime = DateTime.tryParse(value);
if (dateTime != null) return DateTimeDictionaryValue(dateTime);
return StringDictionaryValue(value);
}
/// Localized value based on given [locale] and [pass].
DictionaryValue getLocalizedValue(PassFile pass, Locale? locale);
}
/// [String] content of a [DictionaryField].
class StringDictionaryValue extends DictionaryValue {
final String string;
const StringDictionaryValue(this.string);
@override
/// Localized value based on given [locale] and [pass].
DictionaryValue getLocalizedValue(PassFile pass, Locale? locale) {
final localizations = pass.getLocalizations(locale);
return StringDictionaryValue(localizations?[string] ?? string);
}
}
/// [DateTime] content of a [DictionaryField].
class DateTimeDictionaryValue extends DictionaryValue {
final DateTime dateTime;
const DateTimeDictionaryValue(this.dateTime);
@override
/// Localized value based on given [locale] and [pass]. Same as [dateTime].
DictionaryValue getLocalizedValue(PassFile pass, Locale? locale) => this;
}
/// [int] content of a [DictionaryField].
class NumberDictionaryValue extends DictionaryValue {
final int number;
const NumberDictionaryValue(this.number);
@override
/// Localized value based on given [locale] and [pass]. Same as [number].
DictionaryValue getLocalizedValue(PassFile pass, Locale? locale) => this;
}
/// Possible types of [PassStructureDictionary.transitType].
enum TransitType {
/// PKTransitTypeAir
air,
/// PKTransitTypeBoat
boat,
/// PKTransitTypeBus
bus,
/// PKTransitTypeGeneric
generic,
/// PKTransitTypeTrain
train,
}
/// Possible types of [DictionaryField.textAlignment].
enum PassTextAlign {
/// PKTextAlignmentLeft, corresponds `dart:ui` [TextAlign.left]
left,
/// PKTextAlignmentCenter, corresponds `dart:ui` [TextAlign.center]
center,
/// PKTextAlignmentRight, corresponds `dart:ui` [TextAlign.left]
right,
/// PKTextAlignmentNatural, corresponds `dart:ui` [TextAlign.start]
natural,
}
extension _TarnsitType on TransitType {
static TransitType? parse(String? type) {
if (type == null) return null;
switch (type) {
case 'PKTransitTypeAir':
return TransitType.air;
case 'PKTransitTypeBoat':
return TransitType.boat;
case 'PKTransitTypeBus':
return TransitType.bus;
case 'PKTransitTypeTrain':
return TransitType.train;
default:
return TransitType.generic;
}
}
}