81 lines
2.1 KiB
Dart
81 lines
2.1 KiB
Dart
|
|
import 'dart:convert';
|
||
|
|
import 'dart:io';
|
||
|
|
|
||
|
|
class HashEntry {
|
||
|
|
const HashEntry({
|
||
|
|
required this.cardId,
|
||
|
|
required this.hash,
|
||
|
|
this.filename,
|
||
|
|
});
|
||
|
|
|
||
|
|
final String cardId;
|
||
|
|
final String hash;
|
||
|
|
final String? filename;
|
||
|
|
|
||
|
|
/// Flutter asset path for the gallery image.
|
||
|
|
String? get assetPath =>
|
||
|
|
filename == null ? null : 'test_assets/$filename';
|
||
|
|
}
|
||
|
|
|
||
|
|
class HashLibrary {
|
||
|
|
const HashLibrary({
|
||
|
|
required this.version,
|
||
|
|
required this.algorithm,
|
||
|
|
required this.hashBits,
|
||
|
|
required this.items,
|
||
|
|
});
|
||
|
|
|
||
|
|
final String version;
|
||
|
|
final String algorithm;
|
||
|
|
final int hashBits;
|
||
|
|
final List<HashEntry> items;
|
||
|
|
|
||
|
|
static HashLibrary fromJson(Map<String, dynamic> json) {
|
||
|
|
final rawItems = (json['items'] as List<dynamic>? ?? const []);
|
||
|
|
return HashLibrary(
|
||
|
|
version: json['version'] as String? ?? 'assets-v1',
|
||
|
|
algorithm: json['algorithm'] as String? ?? 'rgb-phash-v1',
|
||
|
|
hashBits: json['hash_bits'] as int? ?? 105,
|
||
|
|
items: rawItems
|
||
|
|
.map((e) {
|
||
|
|
final m = e as Map<String, dynamic>;
|
||
|
|
return HashEntry(
|
||
|
|
cardId: m['card_id'] as String,
|
||
|
|
hash: m['hash'] as String,
|
||
|
|
filename: m['filename'] as String?,
|
||
|
|
);
|
||
|
|
})
|
||
|
|
.toList(growable: false),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
Map<String, dynamic> toJson() => {
|
||
|
|
'version': version,
|
||
|
|
'algorithm': algorithm,
|
||
|
|
'hash_bits': hashBits,
|
||
|
|
'card_count': items.length,
|
||
|
|
'items': items
|
||
|
|
.map(
|
||
|
|
(e) => {
|
||
|
|
'card_id': e.cardId,
|
||
|
|
'hash': e.hash,
|
||
|
|
if (e.filename != null) 'filename': e.filename,
|
||
|
|
},
|
||
|
|
)
|
||
|
|
.toList(growable: false),
|
||
|
|
};
|
||
|
|
|
||
|
|
/// Load from filesystem (CLI scripts / tests).
|
||
|
|
static Future<HashLibrary> loadFile(String path) async {
|
||
|
|
final text = await File(path).readAsString();
|
||
|
|
return fromJson(jsonDecode(text) as Map<String, dynamic>);
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<void> saveFile(String path) async {
|
||
|
|
final file = File(path);
|
||
|
|
await file.parent.create(recursive: true);
|
||
|
|
const encoder = JsonEncoder.withIndent(' ');
|
||
|
|
await file.writeAsString('${encoder.convert(toJson())}\n');
|
||
|
|
}
|
||
|
|
}
|