funziona
This commit is contained in:
parent
1980353a20
commit
6e97813a01
5 changed files with 417 additions and 63 deletions
94
README.md
94
README.md
|
|
@ -21,7 +21,10 @@ run con
|
|||
```
|
||||
fvm flutter run -t lib/main_play.dart --flavor play
|
||||
```
|
||||
|
||||
se vuoi salvare tutto l'output in un file e cmq vederlo
|
||||
```
|
||||
fvm flutter run -t lib/main_play.dart --flavor play 2>&1 | tee output.log
|
||||
```
|
||||
i files nuovi sono
|
||||
|
||||
```
|
||||
|
|
@ -38,8 +41,97 @@ e questo modificato
|
|||
```
|
||||
lib/widgets/home/home_page.dart
|
||||
```
|
||||
salvare il DB
|
||||
```
|
||||
adb exec-out run-as deckers.thibault.aves.debug cat /data/data/deckers.thibault.aves.debug/databases/metadata.db > metadata.db
|
||||
```
|
||||
verifica che il db sia quello giusto
|
||||
|
||||
ci devono essere entry address metadata album
|
||||
|
||||
```
|
||||
sqlite3 metadata.db ".tables"
|
||||
address dateTaken favourites vaults
|
||||
android_metadata dynamicAlbums metadata videoPlayback
|
||||
covers entry trash
|
||||
```
|
||||
|
||||
verifica delke colonne, i campi
|
||||
```
|
||||
sqlite3 metadata.db "PRAGMA table_info(entry);"
|
||||
```
|
||||
risposta
|
||||
```
|
||||
0|id|INTEGER|0||1
|
||||
1|contentId|INTEGER|0||0
|
||||
2|uri|TEXT|0||0
|
||||
3|path|TEXT|0||0
|
||||
4|sourceMimeType|TEXT|0||0
|
||||
5|width|INTEGER|0||0
|
||||
6|height|INTEGER|0||0
|
||||
7|sourceRotationDegrees|INTEGER|0||0
|
||||
8|sizeBytes|INTEGER|0||0
|
||||
9|title|TEXT|0||0
|
||||
10|dateAddedSecs|INTEGER|0|strftime('%s','now')|0
|
||||
11|dateModifiedMillis|INTEGER|0||0
|
||||
12|sourceDateTakenMillis|INTEGER|0||0
|
||||
13|durationMillis|INTEGER|0||0
|
||||
14|trashed|INTEGER|0|0|0
|
||||
15|origin|INTEGER|0|0|0
|
||||
16|provider|TEXT|0||0
|
||||
17|remoteId|TEXT|0||0
|
||||
18|remotePath|TEXT|0||0
|
||||
19|remoteThumb1|TEXT|0||0
|
||||
20|remoteThumb2|TEXT|0||0
|
||||
21|latitude|REAL|0||0
|
||||
22|longitude|REAL|0||0
|
||||
23|altitude|REAL|0||0
|
||||
```
|
||||
Verifica 1 — Quante foto remote sono state salvate
|
||||
```
|
||||
sqlite3 metadata.db "SELECT COUNT(*) FROM entry WHERE origin=1;"
|
||||
99
|
||||
```
|
||||
|
||||
Verifica 2 — Controllare che le foto remote abbiano GPS e path corretti
|
||||
```
|
||||
sqlite3 metadata.db "
|
||||
SELECT id, title, remoteId, remotePath, latitude, longitude, altitude
|
||||
FROM entry
|
||||
WHERE origin=1
|
||||
LIMIT 20;
|
||||
"
|
||||
```
|
||||
risposta
|
||||
```
|
||||
6974|IMG_0123.JPG|d9fb0263ed0bc9945d2d6fde3822377d63ed7a62df20e2a1339d77a058b0e5a0|photos/Fabio/original/2017Irlanda19-29ago/IMG_0123.JPG|53.3419416666667|-6.28671666666667|23.6626344086022
|
||||
6975|IMG_0124.JPG|a48db6ef8efee410190ff59bcb223fece468837d0c39bb408cce911213e5e36c|photos/Fabio/original/2017Irlanda19-29ago/IMG_0124.JPG|53.341975|-6.28675277777778|23.8189509306261
|
||||
```
|
||||
cartelle possibili
|
||||
```
|
||||
sqlite3 metadata.db "SELECT remotePath FROM entry WHERE origin=1;" \
|
||||
| awk -F'/' '{$NF=""; sub(/\/$/,""); print}' \
|
||||
| sort -u
|
||||
```
|
||||
risposta
|
||||
```
|
||||
photos Fabio original 2017Irlanda19-29ago
|
||||
```
|
||||
controlla se ci sono tabelke album
|
||||
```
|
||||
sqlite3 metadata.db "
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name LIKE '%album%';
|
||||
"
|
||||
```
|
||||
risposta
|
||||
```
|
||||
dynamicAlbums
|
||||
```
|
||||
controlla negli albums
|
||||
```
|
||||
sqlite3 metadata.db "SELECT * FROM dynamicAlbums LIMIT 20;"
|
||||
```
|
||||
## Features
|
||||
|
||||
Aves can handle all sorts of images and videos, including your typical JPEGs and MP4s, but also more exotic things like **multi-page TIFFs, SVGs, old AVIs and more**!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// lib/remote/remote_repository.dart
|
||||
import 'package:flutter/foundation.dart' show debugPrint;
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'remote_models.dart';
|
||||
|
||||
|
|
@ -6,69 +6,143 @@ class RemoteRepository {
|
|||
final Database db;
|
||||
RemoteRepository(this.db);
|
||||
|
||||
Future<void> upsertAll(List<RemotePhotoItem> items) async {
|
||||
await db.transaction((txn) async {
|
||||
for (final it in items) {
|
||||
// cerca se esiste già una entry per quel remoteId
|
||||
final existing = await txn.query(
|
||||
'entry',
|
||||
columns: ['id'],
|
||||
where: 'remoteId = ?',
|
||||
whereArgs: [it.id],
|
||||
limit: 1,
|
||||
);
|
||||
|
||||
final int? existingId = existing.isNotEmpty ? (existing.first['id'] as int?) : null;
|
||||
|
||||
final row = <String, Object?>{
|
||||
'id': existingId, // se esiste sostituiamo, altrimenti INSERT nuovo
|
||||
'contentId': null,
|
||||
'uri': null,
|
||||
'path': null,
|
||||
'sourceMimeType': it.mimeType,
|
||||
'width': it.width,
|
||||
'height': it.height,
|
||||
'sourceRotationDegrees': null,
|
||||
'sizeBytes': it.sizeBytes,
|
||||
'title': it.name,
|
||||
'dateAddedSecs': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
'dateModifiedMillis': null,
|
||||
'sourceDateTakenMillis': it.takenAtUtc?.millisecondsSinceEpoch,
|
||||
'durationMillis': it.durationMillis, // <-- ora valorizzato anche per i video
|
||||
'trashed': 0,
|
||||
'origin': 1,
|
||||
'provider': 'json@patachina',
|
||||
'remoteId': it.id,
|
||||
'remotePath': it.path,
|
||||
'remoteThumb1': it.thub1,
|
||||
'remoteThumb2': it.thub2,
|
||||
};
|
||||
|
||||
// INSERT OR REPLACE (se 'id' è valorizzato, sostituisce; se null, crea nuovo)
|
||||
final newId = await txn.insert(
|
||||
'entry',
|
||||
row,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
|
||||
// opzionale: salva indirizzo (se il backend lo fornisce)
|
||||
if (it.location != null) {
|
||||
final addr = <String, Object?>{
|
||||
'id': newId,
|
||||
'addressLine': it.location!.address,
|
||||
'countryCode': null, // county_code != country code
|
||||
'countryName': it.location!.country,
|
||||
'adminArea': it.location!.region,
|
||||
'locality': it.location!.city,
|
||||
};
|
||||
await txn.insert(
|
||||
'address',
|
||||
addr,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
/// Assicura che le colonne GPS esistano nella tabella `entry`.
|
||||
/// Se mancano, prova ad aggiungerle con ALTER TABLE.
|
||||
Future<void> _ensureGpsColumns(DatabaseExecutor dbExec) async {
|
||||
try {
|
||||
final rows = await dbExec.rawQuery('PRAGMA table_info(entry);');
|
||||
final names = rows.map((r) => r['name'] as String).toSet();
|
||||
final stmts = <String>[];
|
||||
if (!names.contains('latitude')) stmts.add('ALTER TABLE entry ADD COLUMN latitude REAL;');
|
||||
if (!names.contains('longitude')) stmts.add('ALTER TABLE entry ADD COLUMN longitude REAL;');
|
||||
if (!names.contains('altitude')) stmts.add('ALTER TABLE entry ADD COLUMN altitude REAL;');
|
||||
for (final s in stmts) {
|
||||
try {
|
||||
await dbExec.execute(s);
|
||||
debugPrint('[RemoteRepository] executed: $s');
|
||||
} catch (e, st) {
|
||||
debugPrint('[RemoteRepository] failed to execute $s: $e\n$st');
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e, st) {
|
||||
debugPrint('[RemoteRepository] _ensureGpsColumns error: $e\n$st');
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserisce o aggiorna tutti gli elementi remoti.
|
||||
/// Difensivo: assicura colonne GPS, logga, e in caso di errore riprova senza i campi GPS.
|
||||
Future<void> upsertAll(List<RemotePhotoItem> items) async {
|
||||
debugPrint('RemoteRepository.upsertAll: items=${items.length}');
|
||||
try {
|
||||
await db.transaction((txn) async {
|
||||
// Assicuriamoci che le colonne GPS esistano prima di inserire
|
||||
await _ensureGpsColumns(txn);
|
||||
|
||||
for (final it in items) {
|
||||
debugPrint('RemoteRepository: processing remoteId=${it.id} lat=${it.lat} lng=${it.lng}');
|
||||
|
||||
final existing = await txn.query(
|
||||
'entry',
|
||||
columns: ['id'],
|
||||
where: 'remoteId = ?',
|
||||
whereArgs: [it.id],
|
||||
limit: 1,
|
||||
);
|
||||
|
||||
final int? existingId = existing.isNotEmpty ? (existing.first['id'] as int?) : null;
|
||||
|
||||
final row = <String, Object?>{
|
||||
'id': existingId,
|
||||
'contentId': null,
|
||||
'uri': null,
|
||||
'path': it.path,
|
||||
'sourceMimeType': it.mimeType,
|
||||
'width': it.width,
|
||||
'height': it.height,
|
||||
'sourceRotationDegrees': null,
|
||||
'sizeBytes': it.sizeBytes,
|
||||
'title': it.name,
|
||||
'dateAddedSecs': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
'dateModifiedMillis': null,
|
||||
'sourceDateTakenMillis': it.takenAtUtc?.millisecondsSinceEpoch,
|
||||
'durationMillis': it.durationMillis,
|
||||
'trashed': 0,
|
||||
'origin': 1,
|
||||
'provider': 'json@patachina',
|
||||
// campi GPS (possono essere null)
|
||||
'latitude': it.lat,
|
||||
'longitude': it.lng,
|
||||
'altitude': it.alt,
|
||||
// campi remoti
|
||||
'remoteId': it.id,
|
||||
'remotePath': it.path,
|
||||
'remoteThumb1': it.thub1,
|
||||
'remoteThumb2': it.thub2,
|
||||
};
|
||||
|
||||
try {
|
||||
final newId = await txn.insert(
|
||||
'entry',
|
||||
row,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
|
||||
if (it.location != null) {
|
||||
final addr = <String, Object?>{
|
||||
'id': newId,
|
||||
'addressLine': it.location!.address,
|
||||
'countryCode': null,
|
||||
'countryName': it.location!.country,
|
||||
'adminArea': it.location!.region,
|
||||
'locality': it.location!.city,
|
||||
};
|
||||
await txn.insert(
|
||||
'address',
|
||||
addr,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
} on DatabaseException catch (e, st) {
|
||||
debugPrint('[RemoteRepository] insert failed for remoteId=${it.id}: $e\n$st');
|
||||
// Fallback: riprova senza i campi GPS (utile se ALTER TABLE non è riuscito)
|
||||
final rowNoGps = Map<String, Object?>.from(row)
|
||||
..remove('latitude')
|
||||
..remove('longitude')
|
||||
..remove('altitude');
|
||||
try {
|
||||
final newId = await txn.insert(
|
||||
'entry',
|
||||
rowNoGps,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
|
||||
if (it.location != null) {
|
||||
final addr = <String, Object?>{
|
||||
'id': newId,
|
||||
'addressLine': it.location!.address,
|
||||
'countryCode': null,
|
||||
'countryName': it.location!.country,
|
||||
'adminArea': it.location!.region,
|
||||
'locality': it.location!.city,
|
||||
};
|
||||
await txn.insert(
|
||||
'address',
|
||||
addr,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
debugPrint('[RemoteRepository] insert succeeded without GPS for remoteId=${it.id}');
|
||||
} catch (e2, st2) {
|
||||
debugPrint('[RemoteRepository] retry without GPS failed for remoteId=${it.id}: $e2\n$st2');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e, st) {
|
||||
debugPrint('[RemoteRepository] upsertAll ERROR: $e\n$st');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> countRemote() async {
|
||||
|
|
|
|||
89
lib/remote/remote_repository.dart.old
Normal file
89
lib/remote/remote_repository.dart.old
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import 'package:sqflite/sqflite.dart';
|
||||
import 'remote_models.dart';
|
||||
|
||||
class RemoteRepository {
|
||||
final Database db;
|
||||
RemoteRepository(this.db);
|
||||
|
||||
Future<void> upsertAll(List<RemotePhotoItem> items) async {
|
||||
await db.transaction((txn) async {
|
||||
for (final it in items) {
|
||||
// cerca se esiste già una entry per quel remoteId
|
||||
final existing = await txn.query(
|
||||
'entry',
|
||||
columns: ['id'],
|
||||
where: 'remoteId = ?',
|
||||
whereArgs: [it.id],
|
||||
limit: 1,
|
||||
);
|
||||
|
||||
final int? existingId =
|
||||
existing.isNotEmpty ? (existing.first['id'] as int?) : null;
|
||||
|
||||
final row = <String, Object?>{
|
||||
// se esiste sostituiamo, altrimenti INSERT nuovo
|
||||
'id': existingId,
|
||||
'contentId': null,
|
||||
'uri': null,
|
||||
'path': null,
|
||||
'sourceMimeType': it.mimeType,
|
||||
'width': it.width,
|
||||
'height': it.height,
|
||||
'sourceRotationDegrees': null,
|
||||
'sizeBytes': it.sizeBytes,
|
||||
'title': it.name,
|
||||
'dateAddedSecs':
|
||||
DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
'dateModifiedMillis': null,
|
||||
'sourceDateTakenMillis':
|
||||
it.takenAtUtc?.millisecondsSinceEpoch,
|
||||
'durationMillis': it.durationMillis,
|
||||
'trashed': 0,
|
||||
'origin': 1,
|
||||
'provider': 'json@patachina',
|
||||
|
||||
// ⭐ AGGIUNTA: GPS direttamente nel DB di Aves
|
||||
'latitude': it.lat,
|
||||
'longitude': it.lng,
|
||||
'altitude': it.alt,
|
||||
|
||||
'remoteId': it.id,
|
||||
'remotePath': it.path,
|
||||
'remoteThumb1': it.thub1,
|
||||
'remoteThumb2': it.thub2,
|
||||
};
|
||||
|
||||
// INSERT OR REPLACE (se 'id' è valorizzato, sostituisce; se null, crea nuovo)
|
||||
final newId = await txn.insert(
|
||||
'entry',
|
||||
row,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
|
||||
// opzionale: salva indirizzo (se il backend lo fornisce)
|
||||
if (it.location != null) {
|
||||
final addr = <String, Object?>{
|
||||
'id': newId,
|
||||
'addressLine': it.location!.address,
|
||||
'countryCode': null, // county_code != country code
|
||||
'countryName': it.location!.country,
|
||||
'adminArea': it.location!.region,
|
||||
'locality': it.location!.city,
|
||||
};
|
||||
|
||||
await txn.insert(
|
||||
'address',
|
||||
addr,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<int> countRemote() async {
|
||||
final rows = await db
|
||||
.rawQuery('SELECT COUNT(1) AS c FROM entry WHERE origin=1');
|
||||
return (rows.first['c'] as int?) ?? 0;
|
||||
}
|
||||
}
|
||||
BIN
metadata.db
Normal file
BIN
metadata.db
Normal file
Binary file not shown.
99
remote_paths.txt
Normal file
99
remote_paths.txt
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0092.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0099.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0100.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0102.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0103.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0104.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0106.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0107.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0108.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0109.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0110.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0112.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0113.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0114.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0116.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0119.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0120.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0122.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0123.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0124.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0125.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0126.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0133.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0134.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0135.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0136.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0137.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0138.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0139.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0140.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0141.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0143.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0145.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0146.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0147.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0148.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0149.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0150.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0152.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0153.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0154.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0155.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0156.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0157.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0160.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0162.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0163.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0164.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0165.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0166.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0167.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0170.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0171.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0172.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0174.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0175.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0176.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0177.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0178.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0179.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0180.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0182.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0183.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0185.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0188.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0190.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0193.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0203.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0204.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0206.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0207.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0208.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0209.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0211.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0212.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0214.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0215.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0216.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0217.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0218.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0223.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0227.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0228.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0229.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0232.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0233.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0234.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0235.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0237.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0241.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0242.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0243.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0244.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0245.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0246.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0247.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0248.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/IMG_0249.JPG
|
||||
photos/Fabio/original/2017Irlanda19-29ago/VID_20260221_095917.mp4
|
||||
Loading…
Reference in a new issue