Compare commits
No commits in common. "43e65ec1454f9ddb06fd0acc32ba32b74c52a9a9" and "1980353a20ef44b2245ebb1c4725194526bbe993" have entirely different histories.
43e65ec145
...
1980353a20
4 changed files with 63 additions and 417 deletions
94
README.md
94
README.md
|
|
@ -21,10 +21,7 @@ run con
|
||||||
```
|
```
|
||||||
fvm flutter run -t lib/main_play.dart --flavor play
|
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
|
i files nuovi sono
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -41,97 +38,8 @@ e questo modificato
|
||||||
```
|
```
|
||||||
lib/widgets/home/home_page.dart
|
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
|
## 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**!
|
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 @@
|
||||||
import 'package:flutter/foundation.dart' show debugPrint;
|
// lib/remote/remote_repository.dart
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite/sqflite.dart';
|
||||||
import 'remote_models.dart';
|
import 'remote_models.dart';
|
||||||
|
|
||||||
|
|
@ -6,41 +6,10 @@ class RemoteRepository {
|
||||||
final Database db;
|
final Database db;
|
||||||
RemoteRepository(this.db);
|
RemoteRepository(this.db);
|
||||||
|
|
||||||
/// 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 {
|
Future<void> upsertAll(List<RemotePhotoItem> items) async {
|
||||||
debugPrint('RemoteRepository.upsertAll: items=${items.length}');
|
|
||||||
try {
|
|
||||||
await db.transaction((txn) async {
|
await db.transaction((txn) async {
|
||||||
// Assicuriamoci che le colonne GPS esistano prima di inserire
|
|
||||||
await _ensureGpsColumns(txn);
|
|
||||||
|
|
||||||
for (final it in items) {
|
for (final it in items) {
|
||||||
debugPrint('RemoteRepository: processing remoteId=${it.id} lat=${it.lat} lng=${it.lng}');
|
// cerca se esiste già una entry per quel remoteId
|
||||||
|
|
||||||
final existing = await txn.query(
|
final existing = await txn.query(
|
||||||
'entry',
|
'entry',
|
||||||
columns: ['id'],
|
columns: ['id'],
|
||||||
|
|
@ -52,10 +21,10 @@ class RemoteRepository {
|
||||||
final int? existingId = existing.isNotEmpty ? (existing.first['id'] as int?) : null;
|
final int? existingId = existing.isNotEmpty ? (existing.first['id'] as int?) : null;
|
||||||
|
|
||||||
final row = <String, Object?>{
|
final row = <String, Object?>{
|
||||||
'id': existingId,
|
'id': existingId, // se esiste sostituiamo, altrimenti INSERT nuovo
|
||||||
'contentId': null,
|
'contentId': null,
|
||||||
'uri': null,
|
'uri': null,
|
||||||
'path': it.path,
|
'path': null,
|
||||||
'sourceMimeType': it.mimeType,
|
'sourceMimeType': it.mimeType,
|
||||||
'width': it.width,
|
'width': it.width,
|
||||||
'height': it.height,
|
'height': it.height,
|
||||||
|
|
@ -65,33 +34,29 @@ class RemoteRepository {
|
||||||
'dateAddedSecs': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
'dateAddedSecs': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||||
'dateModifiedMillis': null,
|
'dateModifiedMillis': null,
|
||||||
'sourceDateTakenMillis': it.takenAtUtc?.millisecondsSinceEpoch,
|
'sourceDateTakenMillis': it.takenAtUtc?.millisecondsSinceEpoch,
|
||||||
'durationMillis': it.durationMillis,
|
'durationMillis': it.durationMillis, // <-- ora valorizzato anche per i video
|
||||||
'trashed': 0,
|
'trashed': 0,
|
||||||
'origin': 1,
|
'origin': 1,
|
||||||
'provider': 'json@patachina',
|
'provider': 'json@patachina',
|
||||||
// campi GPS (possono essere null)
|
|
||||||
'latitude': it.lat,
|
|
||||||
'longitude': it.lng,
|
|
||||||
'altitude': it.alt,
|
|
||||||
// campi remoti
|
|
||||||
'remoteId': it.id,
|
'remoteId': it.id,
|
||||||
'remotePath': it.path,
|
'remotePath': it.path,
|
||||||
'remoteThumb1': it.thub1,
|
'remoteThumb1': it.thub1,
|
||||||
'remoteThumb2': it.thub2,
|
'remoteThumb2': it.thub2,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// INSERT OR REPLACE (se 'id' è valorizzato, sostituisce; se null, crea nuovo)
|
||||||
final newId = await txn.insert(
|
final newId = await txn.insert(
|
||||||
'entry',
|
'entry',
|
||||||
row,
|
row,
|
||||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// opzionale: salva indirizzo (se il backend lo fornisce)
|
||||||
if (it.location != null) {
|
if (it.location != null) {
|
||||||
final addr = <String, Object?>{
|
final addr = <String, Object?>{
|
||||||
'id': newId,
|
'id': newId,
|
||||||
'addressLine': it.location!.address,
|
'addressLine': it.location!.address,
|
||||||
'countryCode': null,
|
'countryCode': null, // county_code != country code
|
||||||
'countryName': it.location!.country,
|
'countryName': it.location!.country,
|
||||||
'adminArea': it.location!.region,
|
'adminArea': it.location!.region,
|
||||||
'locality': it.location!.city,
|
'locality': it.location!.city,
|
||||||
|
|
@ -102,47 +67,8 @@ class RemoteRepository {
|
||||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
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 {
|
Future<int> countRemote() async {
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
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