Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ When upgrading a toolkit, move all three platforms together where API surface ov
- **Bridge serialization**: Readium-owned objects (`Locator`, `Decoration`, …) → JSON strings via `json.encode`; plugin-owned flat structures (preferences, action configs) → Maps. Rationale + Web-TS `.serialize()` rules: `docs/architecture.md#bridge-serialization`.
- **Models**: hand-written `toJson`/`fromJson`. No `json_serializable`/`freezed`/build_runner codegen — don't reintroduce.
- **PDF locator**: position = 1-based page in `Locator.locations.position` (matches upstream); don't invent plugin-side parallels to upstream models. Detail: `docs/api-reference/locator.md#pdf-locators`.
- **copyWith sentinel**: use the shared `const unset` from `utils/constants.dart` for parameters that default to "not set" — never declare a new `_unset = Object()`. Merge additional-properties via `AdditionalProperties.copyAdditionalProperties()` instead of inline merge logic.

### Android

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import '../utils/constants.dart';

/// Configures the automatic audio-stream error recovery loop (retry attempts,
/// backoff, and stall detection) shared by the iOS/Android/web audio
Expand Down Expand Up @@ -59,15 +60,19 @@ class AudioRecoveryPolicy with Equatable {
};

AudioRecoveryPolicy copyWith({
int? maxAttempts,
double? backoffBaseSeconds,
double? stallTimeoutSeconds,
double? connectionTimeoutSeconds,
Object? maxAttempts = unset,
Object? backoffBaseSeconds = unset,
Object? stallTimeoutSeconds = unset,
Object? connectionTimeoutSeconds = unset,
}) => AudioRecoveryPolicy(
maxAttempts: maxAttempts ?? this.maxAttempts,
backoffBaseSeconds: backoffBaseSeconds ?? this.backoffBaseSeconds,
stallTimeoutSeconds: stallTimeoutSeconds ?? this.stallTimeoutSeconds,
connectionTimeoutSeconds: connectionTimeoutSeconds ?? this.connectionTimeoutSeconds,
maxAttempts: identical(maxAttempts, unset) ? this.maxAttempts : (maxAttempts as int),
backoffBaseSeconds: identical(backoffBaseSeconds, unset) ? this.backoffBaseSeconds : (backoffBaseSeconds as double),
stallTimeoutSeconds: identical(stallTimeoutSeconds, unset)
? this.stallTimeoutSeconds
: (stallTimeoutSeconds as double),
connectionTimeoutSeconds: identical(connectionTimeoutSeconds, unset)
? this.connectionTimeoutSeconds
: (connectionTimeoutSeconds as double),
);

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,25 +132,33 @@ class AudioPreferences with Equatable implements JSONable {
];

AudioPreferences copyWith({
double? volume,
double? speed,
double? pitch,
double? seekInterval,
bool? continuousSeeking,
bool? allowExternalSeeking,
double? updateIntervalSecs,
ControlPanelInfoType? controlPanelInfoType,
ControlPanelTimebase? controlPanelTimebase,
Object? volume = unset,
Object? speed = unset,
Object? pitch = unset,
Object? seekInterval = unset,
Object? continuousSeeking = unset,
Object? allowExternalSeeking = unset,
Object? updateIntervalSecs = unset,
Object? controlPanelInfoType = unset,
Object? controlPanelTimebase = unset,
}) => AudioPreferences(
volume: volume ?? this.volume,
speed: speed ?? this.speed,
pitch: pitch ?? this.pitch,
seekInterval: seekInterval ?? this.seekInterval,
continuousSeeking: continuousSeeking ?? this.continuousSeeking,
allowExternalSeeking: allowExternalSeeking ?? this.allowExternalSeeking,
updateIntervalSecs: updateIntervalSecs ?? this.updateIntervalSecs,
controlPanelInfoType: controlPanelInfoType ?? this.controlPanelInfoType,
controlPanelTimebase: controlPanelTimebase ?? this.controlPanelTimebase,
volume: identical(volume, unset) ? this.volume : (volume as double?)!,
speed: identical(speed, unset) ? this.speed : (speed as double?)!,
pitch: identical(pitch, unset) ? this.pitch : (pitch as double?)!,
seekInterval: identical(seekInterval, unset) ? this.seekInterval : (seekInterval as double?)!,
continuousSeeking: identical(continuousSeeking, unset) ? this.continuousSeeking : (continuousSeeking as bool?),
allowExternalSeeking: identical(allowExternalSeeking, unset)
? this.allowExternalSeeking
: (allowExternalSeeking as bool?),
updateIntervalSecs: identical(updateIntervalSecs, unset)
? this.updateIntervalSecs
: (updateIntervalSecs as double?)!,
controlPanelInfoType: identical(controlPanelInfoType, unset)
? this.controlPanelInfoType
: (controlPanelInfoType as ControlPanelInfoType?)!,
controlPanelTimebase: identical(controlPanelTimebase, unset)
? this.controlPanelTimebase
: (controlPanelTimebase as ControlPanelTimebase?)!,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ class ReaderDecoration implements JSONable {
@override
Map<String, dynamic> toJson() => {'id': id, 'locator': locator.toJson(), 'style': style.toJson()};

ReaderDecoration copyWith({String? id, Locator? locator, ReaderDecorationStyle? style}) =>
ReaderDecoration(id: id ?? this.id, locator: locator ?? this.locator, style: style ?? this.style);
ReaderDecoration copyWith({Object? id = unset, Object? locator = unset, Object? style = unset}) => ReaderDecoration(
id: identical(id, unset) ? this.id : (id as String?)!,
locator: identical(locator, unset) ? this.locator : (locator as Locator?)!,
style: identical(style, unset) ? this.style : (style as ReaderDecorationStyle?)!,
);
}

class ReaderDecorationStyle implements JSONable {
Expand Down Expand Up @@ -86,9 +89,10 @@ class ReaderDecorationStyle implements JSONable {
isActive: map['isActive'] as bool? ?? false,
);

ReaderDecorationStyle copyWith({DecorationStyle? style, Color? tint, bool? isActive}) => ReaderDecorationStyle(
style: style ?? this.style,
tint: tint ?? this.tint,
isActive: isActive ?? this.isActive,
);
ReaderDecorationStyle copyWith({Object? style = unset, Object? tint = unset, Object? isActive = unset}) =>
ReaderDecorationStyle(
style: identical(style, unset) ? this.style : (style as DecorationStyle?)!,
tint: identical(tint, unset) ? this.tint : tint as Color?,
isActive: identical(isActive, unset) ? this.isActive : (isActive as bool),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,23 @@ class PDFPreferences with Equatable implements JSONable {
..putOpt('visibleScrollbar', visibleScrollbar);

PDFPreferences copyWith({
PDFLayout? layout,
PDFReadingProgression? readingProgression,
double? pageSpacing,
PDFFit? fit,
bool? offsetFirstPage,
PDFSpread? spread,
bool? visibleScrollbar,
Object? layout = unset,
Object? readingProgression = unset,
Object? pageSpacing = unset,
Object? fit = unset,
Object? offsetFirstPage = unset,
Object? spread = unset,
Object? visibleScrollbar = unset,
}) => PDFPreferences(
layout: layout ?? this.layout,
readingProgression: readingProgression ?? this.readingProgression,
pageSpacing: pageSpacing ?? this.pageSpacing,
fit: fit ?? this.fit,
offsetFirstPage: offsetFirstPage ?? this.offsetFirstPage,
spread: spread ?? this.spread,
visibleScrollbar: visibleScrollbar ?? this.visibleScrollbar,
layout: identical(layout, unset) ? this.layout : (layout as PDFLayout?)!,
readingProgression: identical(readingProgression, unset)
? this.readingProgression
: (readingProgression as PDFReadingProgression?)!,
pageSpacing: identical(pageSpacing, unset) ? this.pageSpacing : (pageSpacing as double?)!,
fit: identical(fit, unset) ? this.fit : (fit as PDFFit?)!,
offsetFirstPage: identical(offsetFirstPage, unset) ? this.offsetFirstPage : (offsetFirstPage as bool?),
spread: identical(spread, unset) ? this.spread : (spread as PDFSpread?),
visibleScrollbar: identical(visibleScrollbar, unset) ? this.visibleScrollbar : (visibleScrollbar as bool?),
);

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

import '../enums.dart';
import '../utils/constants.dart';
import '../utils/jsonable.dart';
import '../utils/readium_log.dart';
import 'index.dart';
Expand Down Expand Up @@ -119,20 +120,20 @@ class ReaderTTSVoice with Equatable implements JSONable {
];

ReaderTTSVoice copyWith({
String? identifier,
String? name,
String? language,
bool? networkRequired,
TTSVoiceGender? gender,
TTSVoiceQuality? quality,
bool? active,
Object? identifier = unset,
Object? name = unset,
Object? language = unset,
Object? networkRequired = unset,
Object? gender = unset,
Object? quality = unset,
Object? active = unset,
}) => ReaderTTSVoice(
identifier: identifier ?? this.identifier,
name: name ?? this.name,
language: language ?? this.language,
networkRequired: networkRequired ?? this.networkRequired,
gender: gender ?? this.gender,
quality: quality ?? this.quality,
active: active ?? this.active,
identifier: identical(identifier, unset) ? this.identifier : (identifier as String?)!,
name: identical(name, unset) ? this.name : (name as String?)!,
language: identical(language, unset) ? this.language : (language as String?)!,
networkRequired: identical(networkRequired, unset) ? this.networkRequired : (networkRequired as bool),
gender: identical(gender, unset) ? this.gender : (gender as TTSVoiceGender),
quality: identical(quality, unset) ? this.quality : (quality as TTSVoiceQuality?),
active: identical(active, unset) ? this.active : (active as bool?),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:dartx/dartx.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

import '../../utils/constants.dart';
import '../../utils/jsonable.dart';
import '../opds.dart' show OpdsMetadata;
import '../publication/link.dart' show Link;
Expand All @@ -23,8 +24,13 @@ class Facet with Equatable implements JSONable {
@override
String toString() => 'Facet{metadata: $metadata, links: $links}';

Facet copyWith({OpdsMetadata? metadata, List<Link>? links}) =>
Facet(metadata: metadata ?? this.metadata, links: links ?? this.links);
Facet copyWith({
Object? metadata = unset,
Object? links = unset,
}) => Facet(
metadata: identical(metadata, unset) ? this.metadata : (metadata as OpdsMetadata),
links: identical(links, unset) ? this.links : (links as List<Link>),
);

@override
Map<String, dynamic> toJson() {
Expand Down
34 changes: 16 additions & 18 deletions flutter_readium_platform_interface/lib/src/shared/opds/feed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,25 @@ class Feed extends AdditionalProperties with Equatable implements JSONable {
'context: $context}';

Feed copyWith({
OpdsMetadata? metadata,
List<Link>? links,
List<Facet>? facets,
List<Group>? groups,
List<OpdsPublication>? publications,
List<Link>? navigation,
List<String>? context,
Map<String, dynamic>? additionalProperties,
Object? metadata = unset,
Object? links = unset,
Object? facets = unset,
Object? groups = unset,
Object? publications = unset,
Object? navigation = unset,
Object? context = unset,
Object? additionalProperties = unset,
}) {
final mergeProperties = Map<String, dynamic>.of(this.additionalProperties)
..addAll(additionalProperties ?? {})
..removeWhere((key, value) => value == null);
final mergeProperties = copyAdditionalProperties(additionalProperties: additionalProperties);

return Feed(
metadata: metadata ?? this.metadata,
links: links ?? this.links,
facets: facets ?? this.facets,
groups: groups ?? this.groups,
publications: publications ?? this.publications,
navigation: navigation ?? this.navigation,
context: context ?? this.context,
metadata: identical(metadata, unset) ? this.metadata : (metadata as OpdsMetadata?)!,
links: identical(links, unset) ? this.links : (links as List<Link>?)!,
facets: identical(facets, unset) ? this.facets : (facets as List<Facet>?)!,
groups: identical(groups, unset) ? this.groups : (groups as List<Group>?)!,
publications: identical(publications, unset) ? this.publications : (publications as List<OpdsPublication>?)!,
navigation: identical(navigation, unset) ? this.navigation : (navigation as List<Link>?)!,
context: identical(context, unset) ? this.context : (context as List<String>?)!,
additionalProperties: mergeProperties,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

import '../../utils/constants.dart';
import '../../utils/jsonable.dart';
import '../opds.dart';
import '../publication/link.dart';
Expand Down Expand Up @@ -34,15 +35,15 @@ class Group with Equatable implements JSONable {
'publications: $publications, navigation: $navigation}';

Group copyWith({
OpdsMetadata? metadata,
List<Link>? links,
List<OpdsPublication>? publications,
List<Link>? navigation,
Object? metadata = unset,
Object? links = unset,
Object? publications = unset,
Object? navigation = unset,
}) => Group(
metadata: metadata ?? this.metadata,
links: links ?? this.links,
publications: publications ?? this.publications,
navigation: navigation ?? this.navigation,
metadata: identical(metadata, unset) ? this.metadata : (metadata as OpdsMetadata?)!,
links: identical(links, unset) ? this.links : (links as List<Link>?)!,
publications: identical(publications, unset) ? this.publications : (publications as List<OpdsPublication>?)!,
navigation: identical(navigation, unset) ? this.navigation : (navigation as List<Link>?)!,
);

@override
Expand Down
Loading
Loading