147 lines
4.9 KiB
Dart
147 lines
4.9 KiB
Dart
// lib/services/note_photo_service.dart
|
|
//
|
|
// Fotó kezelő service:
|
|
// - Kamera / galéria hozzáférés (image_picker)
|
|
// - Fájl mentés külső tárhelyre
|
|
// - SQLite CRUD
|
|
// - Opcionális Supabase Storage szinkron
|
|
|
|
import 'dart:io';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
import '../models/note_item_photo.dart';
|
|
import '../services/app_database.dart';
|
|
|
|
class NotePhotoService extends GetxService {
|
|
static NotePhotoService get to => Get.find();
|
|
|
|
final _picker = ImagePicker();
|
|
String? _photoDir;
|
|
|
|
@override
|
|
Future<void> onInit() async {
|
|
super.onInit();
|
|
await _initPhotoDir();
|
|
}
|
|
|
|
Future<void> _initPhotoDir() async {
|
|
final ext = await getExternalStorageDirectory();
|
|
final dir = Directory(p.join(ext!.path, 'photos'));
|
|
if (!await dir.exists()) await dir.create(recursive: true);
|
|
_photoDir = dir.path;
|
|
}
|
|
|
|
// ── Fotó készítése kamerával ─────────────────────────────────────
|
|
|
|
Future<NoteItemPhoto?> takePhoto(int noteItemId) async {
|
|
return _pickAndSave(
|
|
noteItemId: noteItemId,
|
|
source: ImageSource.camera,
|
|
);
|
|
}
|
|
|
|
// ── Fotó választása galériából ───────────────────────────────────
|
|
|
|
Future<NoteItemPhoto?> pickFromGallery(int noteItemId) async {
|
|
return _pickAndSave(
|
|
noteItemId: noteItemId,
|
|
source: ImageSource.gallery,
|
|
);
|
|
}
|
|
|
|
// ── Közös mentési logika ─────────────────────────────────────────
|
|
|
|
Future<NoteItemPhoto?> _pickAndSave({
|
|
required int noteItemId,
|
|
required ImageSource source,
|
|
}) async {
|
|
try {
|
|
final picked = await _picker.pickImage(
|
|
source: source,
|
|
imageQuality: 85, // tömörítés a tárhelyért
|
|
maxWidth: 2048,
|
|
maxHeight: 2048,
|
|
);
|
|
if (picked == null) return null; // felhasználó visszalépett
|
|
|
|
// GPS pozíció a fotókészítés pillanatában
|
|
final pos = await _currentPosition();
|
|
|
|
// Fájl másolása az app saját könyvtárába
|
|
final fileName =
|
|
'photo_${noteItemId}_${DateTime.now().millisecondsSinceEpoch}.jpg';
|
|
final destPath = p.join(_photoDir!, fileName);
|
|
await File(picked.path).copy(destPath);
|
|
|
|
// SQLite mentés
|
|
final photo = NoteItemPhoto(
|
|
noteItemId: noteItemId,
|
|
localPath: destPath,
|
|
latitude: pos?.latitude,
|
|
longitude: pos?.longitude,
|
|
createdAt: DateTime.now(),
|
|
);
|
|
|
|
final id = await AppDatabase.instance.insertNotePhoto(photo);
|
|
return NoteItemPhoto(
|
|
id: id,
|
|
noteItemId: photo.noteItemId,
|
|
localPath: photo.localPath,
|
|
latitude: photo.latitude,
|
|
longitude: photo.longitude,
|
|
createdAt: photo.createdAt,
|
|
);
|
|
} catch (e) {
|
|
debugPrint('NotePhotoService hiba: $e');
|
|
Get.snackbar('Hiba', 'Fotó mentése sikertelen.',
|
|
snackPosition: SnackPosition.BOTTOM);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// ── Fotó törlése ─────────────────────────────────────────────────
|
|
|
|
Future<void> deletePhoto(NoteItemPhoto photo) async {
|
|
// Fájl törlése
|
|
final file = File(photo.localPath);
|
|
if (await file.exists()) await file.delete();
|
|
|
|
// SQLite törlése
|
|
await AppDatabase.instance.deleteNotePhoto(photo.id!);
|
|
}
|
|
|
|
// ── Felirat frissítése ────────────────────────────────────────────
|
|
|
|
Future<NoteItemPhoto> updateCaption(
|
|
NoteItemPhoto photo, String caption) async {
|
|
final updated = photo.copyWith(caption: caption);
|
|
await AppDatabase.instance.updateNotePhoto(updated);
|
|
return updated;
|
|
}
|
|
|
|
// ── GPS pozíció ──────────────────────────────────────────────────
|
|
|
|
Future<Position?> _currentPosition() async {
|
|
try {
|
|
return await Geolocator.getCurrentPosition(
|
|
locationSettings: const LocationSettings(
|
|
accuracy: LocationAccuracy.medium,
|
|
timeLimit: Duration(seconds: 3),
|
|
),
|
|
).timeout(const Duration(seconds: 3));
|
|
} catch (_) {
|
|
return Geolocator.getLastKnownPosition();
|
|
}
|
|
}
|
|
|
|
// ── Fotók betöltése ──────────────────────────────────────────────
|
|
|
|
Future<List<NoteItemPhoto>> loadPhotos(int noteItemId) =>
|
|
AppDatabase.instance.listNotePhotos(noteItemId);
|
|
}
|