import 'package:intl/locale.dart'; import 'package:pkpass/pkpass.dart'; import 'package:pkpass/pkpass/utils/mabe_decode.dart'; /// Information that is required for all passes. class PassMetadata { /// Brief description of the pass, used by accessibility technologies. /// /// Don’t try to include all of the data on the pass in its description, /// just include enough detail to distinguish passes of the same type. final String description; /// Version of the file format. The value must be 1. final int formatVersion; /// Display name of the organization that originated and signed the pass. final String organizationName; /// Pass type identifier, as issued by Apple. The value must correspond with /// your signing certificate. final String passTypeIdentifier; /// Serial number that uniquely identifies the pass. No two passes with the /// same pass type identifier may have the same serial number. final String serialNumber; /// Team identifier of the organization that originated and signed the pass, /// as issued by Apple. final String teamIdentifier; /// A URL to be passed to the associated app when launching it. final String? appLaunchURL; /// Date and time when the pass expires. final DateTime? expirationDate; /// Indicates that the pass is void—for example, a one time use coupon that /// has been redeemed. The default value is false. final bool voided; /// Beacons marking locations where the pass is relevant. final List beacons; /// Locations where the pass is relevant. For example, the location of your store. final List locations; /// Maximum distance in meters from a relevant latitude and longitude that /// the pass is relevant. This number is compared to the pass’s default /// distance and the smaller value is used. final int? maxDistance; /// Recommended for event tickets and boarding passes; otherwise optional. /// Date and time when the pass becomes relevant. For example, the start /// time of a movie. final DateTime? relevantDate; /// Information specific to a boarding pass. final PassStructureDictionary? boardingPass; /// Information specific to a coupon. final PassStructureDictionary? coupon; /// Information specific to an event ticket. final PassStructureDictionary? eventTicket; /// Information specific to a generic pass. final PassStructureDictionary? generic; /// Information specific to a store card. final PassStructureDictionary? storeCard; /// Information specific to the pass’s barcode. /// The system uses the first valid barcode dictionary in the array. /// Additional dictionaries can be added as fallbacks. final List barcodes; /// Background color of the pass. final int? backgroundColor; /// Foreground color of the pass. final int? foregroundColor; /// Optional for event tickets and boarding passes; otherwise not allowed. /// Identifier used to group related passes. If a grouping identifier is /// specified, passes with the same style, pass type identifier, and grouping /// identifier are displayed as a group. Otherwise, passes are grouped /// automatically. /// /// Use this to group passes that are tightly related, such as the boarding /// passes for different connections of the same trip. final String? groupingIdentifier; /// Color of the label text. final int? labelColor; /// Text displayed next to the logo on the pass. final String? logoText; /// Information used to update passes using the web service. final PassWebService? webService; const PassMetadata({ required this.description, required this.formatVersion, required this.organizationName, required this.passTypeIdentifier, required this.serialNumber, required this.teamIdentifier, this.appLaunchURL, this.expirationDate, this.voided = false, this.beacons = const [], this.locations = const [], this.maxDistance, this.relevantDate, this.boardingPass, this.coupon, this.eventTicket, this.generic, this.storeCard, this.barcodes = const [], this.backgroundColor, this.foregroundColor, this.groupingIdentifier, this.labelColor, this.logoText, this.webService, }); factory PassMetadata.fromJson(Map json) => PassMetadata( description: json['description'] as String, formatVersion: json['formatVersion'] as int, organizationName: json['organizationName'] as String, passTypeIdentifier: json['passTypeIdentifier'] as String, serialNumber: json['serialNumber'] as String, teamIdentifier: json['teamIdentifier'] as String, boardingPass: json['boardingPass'] == null ? null : PassStructureDictionary.fromJson( (json['boardingPass'] as Map).cast(), ), coupon: json['coupon'] == null ? null : PassStructureDictionary.fromJson( (json['coupon'] as Map).cast(), ), eventTicket: json['eventTicket'] == null ? null : PassStructureDictionary.fromJson( (json['eventTicket'] as Map).cast(), ), generic: json['generic'] == null ? null : PassStructureDictionary.fromJson( (json['generic'] as Map).cast(), ), storeCard: json['storeCard'] == null ? null : PassStructureDictionary.fromJson( (json['storeCard'] as Map).cast(), ), barcodes: (json['barcodes'] as List? ?? [if (json['barcode'] != null) json['barcode']]) .map((i) => PassBarcode.fromJson(i)) .toList(), locations: (json['locations'] as List? ?? []) .map((i) => Location.fromJson(i)) .toList(), appLaunchURL: json['appLaunchURL'] as String?, expirationDate: MaybeDecode.maybeDateTime(json['expirationDate'] as String?), voided: json['voided'] as bool? ?? false, beacons: (json['beacons'] as List? ?? []) .map((i) => Beacon.fromJson(i)) .toList(), maxDistance: json['maxDistance'] as int?, relevantDate: MaybeDecode.maybeDateTime(json['relevantDate'] as String?), backgroundColor: MaybeDecode.maybeColor(json['backgroundColor'] as String?), foregroundColor: MaybeDecode.maybeColor(json['foregroundColor'] as String?), groupingIdentifier: json['locoText'] as String?, labelColor: MaybeDecode.maybeColor(json['labelColor'] as String?), logoText: json['locoText'] as String?, webService: PassWebService.maybe( authenticationToken: json['authenticationToken'] as String?, webServiceURL: json['webServiceURL'] as String?, ), ); /// Localized version of [description] based on given [locale] and [pass]. String getLocalizedDescription(PassFile pass, Locale? locale) { final localizations = pass.getLocalizations(locale); return localizations?[description] ?? description; } /// Localized version of [organizationName] based on given [locale] and [pass]. String getLocalizedOrganizationName(PassFile pass, Locale? locale) { final localizations = pass.getLocalizations(locale); return localizations?[organizationName] ?? organizationName; } /// Localized version of [logoText] based on given [locale] and [pass]. String? getLocalizedLogoText(PassFile pass, Locale? locale) { final localizations = pass.getLocalizations(locale); return localizations?[logoText] ?? logoText; } }