pdf_signature/lib/data/model/model.dart

148 lines
4.4 KiB
Dart

import 'dart:typed_data';
import 'package:flutter/widgets.dart';
/// Represents a single signature placement on a page combining both the
/// geometric rectangle (UI coordinate space) and the identifier of the
/// image/signature asset assigned to that placement.
class SignaturePlacement {
final Rect rect;
/// Rotation in degrees to apply when rendering/exporting this placement.
final double rotationDeg;
/// Identifier of the image (e.g., filename / asset id) assigned to this placement.
/// Nullable to allow a placement reserved before an image is chosen.
final String? imageId;
const SignaturePlacement({
required this.rect,
this.imageId,
this.rotationDeg = 0.0,
});
SignaturePlacement copyWith({
Rect? rect,
String? imageId,
double? rotationDeg,
}) => SignaturePlacement(
rect: rect ?? this.rect,
imageId: imageId ?? this.imageId,
rotationDeg: rotationDeg ?? this.rotationDeg,
);
}
class PdfState {
final bool loaded;
final int pageCount;
final int currentPage;
final String? pickedPdfPath;
final Uint8List? pickedPdfBytes;
final int? signedPage;
// Multiple signature placements per page, each combines geometry and optional image id.
final Map<int, List<SignaturePlacement>> placementsByPage;
// UI state: selected placement index on the current page (if any)
final int? selectedPlacementIndex;
const PdfState({
required this.loaded,
required this.pageCount,
required this.currentPage,
this.pickedPdfPath,
this.pickedPdfBytes,
this.signedPage,
this.placementsByPage = const {},
this.selectedPlacementIndex,
});
factory PdfState.initial() => const PdfState(
loaded: false,
pageCount: 0,
currentPage: 1,
pickedPdfBytes: null,
signedPage: null,
placementsByPage: {},
selectedPlacementIndex: null,
);
PdfState copyWith({
bool? loaded,
int? pageCount,
int? currentPage,
String? pickedPdfPath,
Uint8List? pickedPdfBytes,
int? signedPage,
Map<int, List<SignaturePlacement>>? placementsByPage,
int? selectedPlacementIndex,
}) => PdfState(
loaded: loaded ?? this.loaded,
pageCount: pageCount ?? this.pageCount,
currentPage: currentPage ?? this.currentPage,
pickedPdfPath: pickedPdfPath ?? this.pickedPdfPath,
pickedPdfBytes: pickedPdfBytes ?? this.pickedPdfBytes,
signedPage: signedPage ?? this.signedPage,
placementsByPage: placementsByPage ?? this.placementsByPage,
selectedPlacementIndex:
selectedPlacementIndex ?? this.selectedPlacementIndex,
);
}
class SignatureState {
final Rect? rect;
final bool aspectLocked;
final bool bgRemoval;
final double contrast;
final double brightness;
// Rotation in degrees applied to the signature image when rendering/exporting
final double rotation;
final List<List<Offset>> strokes;
final Uint8List? imageBytes;
// The ID of the signature asset the current overlay is based on (from library)
final String? assetId;
// When true, the active signature overlay is movable/resizable and should not be exported.
// When false, the overlay is confirmed (unmovable) and eligible for export.
final bool editingEnabled;
const SignatureState({
required this.rect,
required this.aspectLocked,
required this.bgRemoval,
required this.contrast,
required this.brightness,
this.rotation = 0.0,
required this.strokes,
this.imageBytes,
this.assetId,
this.editingEnabled = false,
});
factory SignatureState.initial() => const SignatureState(
rect: null,
aspectLocked: false,
bgRemoval: false,
contrast: 1.0,
brightness: 0.0,
rotation: 0.0,
strokes: [],
imageBytes: null,
assetId: null,
editingEnabled: false,
);
SignatureState copyWith({
Rect? rect,
bool? aspectLocked,
bool? bgRemoval,
double? contrast,
double? brightness,
double? rotation,
List<List<Offset>>? strokes,
Uint8List? imageBytes,
String? assetId,
bool? editingEnabled,
}) => SignatureState(
rect: rect ?? this.rect,
aspectLocked: aspectLocked ?? this.aspectLocked,
bgRemoval: bgRemoval ?? this.bgRemoval,
contrast: contrast ?? this.contrast,
brightness: brightness ?? this.brightness,
rotation: rotation ?? this.rotation,
strokes: strokes ?? this.strokes,
imageBytes: imageBytes ?? this.imageBytes,
assetId: assetId ?? this.assetId,
editingEnabled: editingEnabled ?? this.editingEnabled,
);
}