// lib/models/scratch_link.dart // // A PDF-anchored scratch link: a sticky-note "tab" placed at a normalized // position (nx, ny in [0,1]) on a specific page of a document. Tapping the // anchor opens an on-page sticky card that BELONGS TO THIS ANCHOR (keyed by // [id]). Optional [nw]/[nh] size the expanded card as fractions of the page. import 'package:flutter/foundation.dart'; @immutable class ScratchLink { const ScratchLink({ required this.id, required this.documentId, required this.pageIndex, required this.nx, required this.ny, this.nw = 0.42, this.nh = 0.36, }); /// Stable anchor id (uuid). Doubles as the scratchpad storage key so each /// anchor gets its own private infinite scratchpad. final String id; /// The owning document (the editor's stable document-id for the PDF path). final String documentId; /// 0-based page the anchor sits on. final int pageIndex; /// Normalized horizontal position on the page, in [0, 1] (top-left of card). final double nx; /// Normalized vertical position on the page, in [0, 1] (top-left of card). final double ny; /// Expanded card width as a fraction of page width (clamped on write). final double nw; /// Expanded card height as a fraction of page height. final double nh; ScratchLink copyWith({ String? id, String? documentId, int? pageIndex, double? nx, double? ny, double? nw, double? nh, }) => ScratchLink( id: id ?? this.id, documentId: documentId ?? this.documentId, pageIndex: pageIndex ?? this.pageIndex, nx: nx ?? this.nx, ny: ny ?? this.ny, nw: nw ?? this.nw, nh: nh ?? this.nh, ); Map toJson() => { 'id': id, 'documentId': documentId, 'pageIndex': pageIndex, 'nx': nx, 'ny': ny, 'nw': nw, 'nh': nh, }; factory ScratchLink.fromJson(Map json) => ScratchLink( id: json['id'] as String, documentId: json['documentId'] as String, pageIndex: (json['pageIndex'] as num).toInt(), nx: (json['nx'] as num).toDouble(), ny: (json['ny'] as num).toDouble(), nw: (json['nw'] as num?)?.toDouble() ?? 0.42, nh: (json['nh'] as num?)?.toDouble() ?? 0.36, ); @override bool operator ==(Object other) => identical(this, other) || other is ScratchLink && runtimeType == other.runtimeType && id == other.id && documentId == other.documentId && pageIndex == other.pageIndex && nx == other.nx && ny == other.ny && nw == other.nw && nh == other.nh; @override int get hashCode => Object.hash(id, documentId, pageIndex, nx, ny, nw, nh); @override String toString() => 'ScratchLink(id: $id, documentId: $documentId, pageIndex: $pageIndex, ' 'nx: $nx, ny: $ny, nw: $nw, nh: $nh)'; }