···1+---
2+applyTo: "lib/api.dart"
3+---
4+5+# Copilot Instructions: Generate Typed Dart API Client for Grain Social Endpoints
6+7+## Goal
8+9+Generate a Dart API client for the Grain social endpoints, using the lexicon
10+JSON files in `lexicons/social/grain` and its subfolders. Each endpoint should
11+have:
12+13+- Typed request and response models
14+- API methods with correct parameters and return types
15+- Documentation from the lexicon descriptions
16+17+## Instructions for Copilot
18+19+1. **For each lexicon JSON file:**
20+ - Parse the endpoint definition (`id`, `type`, `description`,
21+ `parameters`/`input`, `output`).
22+ - Generate a Dart class for request parameters/input.
23+ - Generate a Dart class for response/output.
24+ - Use the [freezed](https://pub.dev/packages/freezed) package to generate an
25+ immutable model for each response type.
26+ - Each model class should be created in a separate file in
27+ `models/procedures`.
28+ - Create a Dart method for the endpoint, with correct types and
29+ documentation.
30+ - Each API method should:
31+ - Accept an `apiUrl` parameter as a prefix for requests (e.g.,
32+ `$apiUrl/xrpc/${id}`).
33+ - Pass the API token in the `Authorization` header for all requests.
34+ - Use the endpoint URL format `/xrpc/${id}` (e.g.,
35+ `/xrpc/social.grain.actor.getProfile`).
36+37+2. **Type Mapping:**
38+ - JSON `string` โ Dart `String`
39+ - JSON `object` โ Dart class
40+ - JSON `array` โ Dart `List<T>`
41+ - JSON `integer` โ Dart `int`
42+ - JSON `boolean` โ Dart `bool`
43+ - JSON `*/*` (binary) โ Dart `Uint8List` or `List<int>`
44+45+3. **API Method Example:**
46+ ```dart
47+ /// Get detailed profile view of an actor.
48+ Future<ProfileViewDetailed> getProfile(String actor);
49+50+ /// Create a comment.
51+ Future<CommentResponse> createComment(CreateCommentRequest request);
52+53+ /// Create a follow relationship.
54+ Future<FollowResponse> createFollow(String subject);
55+56+ /// Create a photo.
57+ Future<PhotoResponse> createPhoto(Uint8List photoData);
58+ ```
59+60+4. **Documentation:**
61+ - Use the `description` field from the lexicon for method/class docs.
62+63+5. **Error Handling:**
64+ - Generate error classes/types for API errors.
65+66+6. **Authentication:**
67+ - Mark endpoints that require auth.
68+69+## Reference
70+71+Use all JSON files in `lexicons/social/grain` and subfolders. For each endpoint,
72+use the schema references for response types if available.
73+74+## Example Endpoints
75+76+### Get Actor Profile
77+78+- **ID:** `social.grain.actor.getProfile`
79+- **Type:** Query
80+- **Description:** Get detailed profile view of an actor. Does not require auth,
81+ but contains relevant metadata with auth.
82+- **Parameters:** `actor` (string, at-identifier)
83+- **Response:** JSON, schema: `social.grain.actor.defs#profileViewDetailed`
···1+{
2+ "lexicon": 1,
3+ "id": "app.bsky.feed.postgate",
4+ "defs": {
5+ "main": {
6+ "key": "tid",
7+ "type": "record",
8+ "record": {
9+ "type": "object",
10+ "required": [
11+ "post",
12+ "createdAt"
13+ ],
14+ "properties": {
15+ "post": {
16+ "type": "string",
17+ "format": "at-uri",
18+ "description": "Reference (AT-URI) to the post record."
19+ },
20+ "createdAt": {
21+ "type": "string",
22+ "format": "datetime"
23+ },
24+ "embeddingRules": {
25+ "type": "array",
26+ "items": {
27+ "refs": [
28+ "#disableRule"
29+ ],
30+ "type": "union"
31+ },
32+ "maxLength": 5,
33+ "description": "List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed."
34+ },
35+ "detachedEmbeddingUris": {
36+ "type": "array",
37+ "items": {
38+ "type": "string",
39+ "format": "at-uri"
40+ },
41+ "maxLength": 50,
42+ "description": "List of AT-URIs embedding this post that the author has detached from."
43+ }
44+ }
45+ },
46+ "description": "Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository."
47+ },
48+ "disableRule": {
49+ "type": "object",
50+ "properties": {},
51+ "description": "Disables embedding of this post."
52+ }
53+ }
54+}
···1+{
2+ "lexicon": 1,
3+ "id": "com.atproto.label.defs",
4+ "defs": {
5+ "label": {
6+ "type": "object",
7+ "required": [
8+ "src",
9+ "uri",
10+ "val",
11+ "cts"
12+ ],
13+ "properties": {
14+ "cid": {
15+ "type": "string",
16+ "format": "cid",
17+ "description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to."
18+ },
19+ "cts": {
20+ "type": "string",
21+ "format": "datetime",
22+ "description": "Timestamp when this label was created."
23+ },
24+ "exp": {
25+ "type": "string",
26+ "format": "datetime",
27+ "description": "Timestamp at which this label expires (no longer applies)."
28+ },
29+ "neg": {
30+ "type": "boolean",
31+ "description": "If true, this is a negation label, overwriting a previous label."
32+ },
33+ "sig": {
34+ "type": "bytes",
35+ "description": "Signature of dag-cbor encoded label."
36+ },
37+ "src": {
38+ "type": "string",
39+ "format": "did",
40+ "description": "DID of the actor who created this label."
41+ },
42+ "uri": {
43+ "type": "string",
44+ "format": "uri",
45+ "description": "AT URI of the record, repository (account), or other resource that this label applies to."
46+ },
47+ "val": {
48+ "type": "string",
49+ "maxLength": 128,
50+ "description": "The short string name of the value or type of this label."
51+ },
52+ "ver": {
53+ "type": "integer",
54+ "description": "The AT Protocol version of the label object."
55+ }
56+ },
57+ "description": "Metadata tag on an atproto resource (eg, repo or record)."
58+ },
59+ "selfLabel": {
60+ "type": "object",
61+ "required": [
62+ "val"
63+ ],
64+ "properties": {
65+ "val": {
66+ "type": "string",
67+ "maxLength": 128,
68+ "description": "The short string name of the value or type of this label."
69+ }
70+ },
71+ "description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel."
72+ },
73+ "labelValue": {
74+ "type": "string",
75+ "knownValues": [
76+ "!hide",
77+ "!no-promote",
78+ "!warn",
79+ "!no-unauthenticated",
80+ "dmca-violation",
81+ "doxxing",
82+ "porn",
83+ "sexual",
84+ "nudity",
85+ "nsfl",
86+ "gore"
87+ ]
88+ },
89+ "selfLabels": {
90+ "type": "object",
91+ "required": [
92+ "values"
93+ ],
94+ "properties": {
95+ "values": {
96+ "type": "array",
97+ "items": {
98+ "ref": "#selfLabel",
99+ "type": "ref"
100+ },
101+ "maxLength": 10
102+ }
103+ },
104+ "description": "Metadata tags on an atproto record, published by the author within the record."
105+ },
106+ "labelValueDefinition": {
107+ "type": "object",
108+ "required": [
109+ "identifier",
110+ "severity",
111+ "blurs",
112+ "locales"
113+ ],
114+ "properties": {
115+ "blurs": {
116+ "type": "string",
117+ "description": "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.",
118+ "knownValues": [
119+ "content",
120+ "media",
121+ "none"
122+ ]
123+ },
124+ "locales": {
125+ "type": "array",
126+ "items": {
127+ "ref": "#labelValueDefinitionStrings",
128+ "type": "ref"
129+ }
130+ },
131+ "severity": {
132+ "type": "string",
133+ "description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.",
134+ "knownValues": [
135+ "inform",
136+ "alert",
137+ "none"
138+ ]
139+ },
140+ "adultOnly": {
141+ "type": "boolean",
142+ "description": "Does the user need to have adult content enabled in order to configure this label?"
143+ },
144+ "identifier": {
145+ "type": "string",
146+ "maxLength": 100,
147+ "description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).",
148+ "maxGraphemes": 100
149+ },
150+ "defaultSetting": {
151+ "type": "string",
152+ "default": "warn",
153+ "description": "The default setting for this label.",
154+ "knownValues": [
155+ "ignore",
156+ "warn",
157+ "hide"
158+ ]
159+ }
160+ },
161+ "description": "Declares a label value and its expected interpretations and behaviors."
162+ },
163+ "labelValueDefinitionStrings": {
164+ "type": "object",
165+ "required": [
166+ "lang",
167+ "name",
168+ "description"
169+ ],
170+ "properties": {
171+ "lang": {
172+ "type": "string",
173+ "format": "language",
174+ "description": "The code of the language these strings are written in."
175+ },
176+ "name": {
177+ "type": "string",
178+ "maxLength": 640,
179+ "description": "A short human-readable name for the label.",
180+ "maxGraphemes": 64
181+ },
182+ "description": {
183+ "type": "string",
184+ "maxLength": 100000,
185+ "description": "A longer description of what the label means and why it might be applied.",
186+ "maxGraphemes": 10000
187+ }
188+ },
189+ "description": "Strings which describe the label in the UI, localized into a specific language."
190+ }
191+ }
192+}
···1+{
2+ "lexicon": 1,
3+ "id": "social.grain.labeler.service",
4+ "defs": {
5+ "main": {
6+ "type": "record",
7+ "description": "A declaration of the existence of labeler service.",
8+ "key": "literal:self",
9+ "record": {
10+ "type": "object",
11+ "required": ["policies", "createdAt"],
12+ "properties": {
13+ "policies": {
14+ "type": "ref",
15+ "ref": "app.bsky.labeler.defs#labelerPolicies"
16+ },
17+ "labels": {
18+ "type": "union",
19+ "refs": ["com.atproto.label.defs#selfLabels"]
20+ },
21+ "createdAt": { "type": "string", "format": "datetime" },
22+ "reasonTypes": {
23+ "description": "The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.",
24+ "type": "array",
25+ "items": {
26+ "type": "ref",
27+ "ref": "com.atproto.moderation.defs#reasonType"
28+ }
29+ },
30+ "subjectTypes": {
31+ "description": "The set of subject types (account, record, etc) this service accepts reports on.",
32+ "type": "array",
33+ "items": {
34+ "type": "ref",
35+ "ref": "com.atproto.moderation.defs#subjectType"
36+ }
37+ },
38+ "subjectCollections": {
39+ "type": "array",
40+ "description": "Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type.",
41+ "items": { "type": "string", "format": "nsid" }
42+ }
43+ }
44+ }
45+ }
46+ }
47+}
···1+// coverage:ignore-file
2+// GENERATED CODE - DO NOT MODIFY BY HAND
3+// ignore_for_file: type=lint
4+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
5+6+part of 'apply_alts_response.dart';
7+8+// **************************************************************************
9+// FreezedGenerator
10+// **************************************************************************
11+12+T _$identity<T>(T value) => value;
13+14+final _privateConstructorUsedError = UnsupportedError(
15+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
16+);
17+18+ApplyAltsResponse _$ApplyAltsResponseFromJson(Map<String, dynamic> json) {
19+ return _ApplyAltsResponse.fromJson(json);
20+}
21+22+/// @nodoc
23+mixin _$ApplyAltsResponse {
24+ bool get success => throw _privateConstructorUsedError;
25+26+ /// Serializes this ApplyAltsResponse to a JSON map.
27+ Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28+29+ /// Create a copy of ApplyAltsResponse
30+ /// with the given fields replaced by the non-null parameter values.
31+ @JsonKey(includeFromJson: false, includeToJson: false)
32+ $ApplyAltsResponseCopyWith<ApplyAltsResponse> get copyWith =>
33+ throw _privateConstructorUsedError;
34+}
35+36+/// @nodoc
37+abstract class $ApplyAltsResponseCopyWith<$Res> {
38+ factory $ApplyAltsResponseCopyWith(
39+ ApplyAltsResponse value,
40+ $Res Function(ApplyAltsResponse) then,
41+ ) = _$ApplyAltsResponseCopyWithImpl<$Res, ApplyAltsResponse>;
42+ @useResult
43+ $Res call({bool success});
44+}
45+46+/// @nodoc
47+class _$ApplyAltsResponseCopyWithImpl<$Res, $Val extends ApplyAltsResponse>
48+ implements $ApplyAltsResponseCopyWith<$Res> {
49+ _$ApplyAltsResponseCopyWithImpl(this._value, this._then);
50+51+ // ignore: unused_field
52+ final $Val _value;
53+ // ignore: unused_field
54+ final $Res Function($Val) _then;
55+56+ /// Create a copy of ApplyAltsResponse
57+ /// with the given fields replaced by the non-null parameter values.
58+ @pragma('vm:prefer-inline')
59+ @override
60+ $Res call({Object? success = null}) {
61+ return _then(
62+ _value.copyWith(
63+ success: null == success
64+ ? _value.success
65+ : success // ignore: cast_nullable_to_non_nullable
66+ as bool,
67+ )
68+ as $Val,
69+ );
70+ }
71+}
72+73+/// @nodoc
74+abstract class _$$ApplyAltsResponseImplCopyWith<$Res>
75+ implements $ApplyAltsResponseCopyWith<$Res> {
76+ factory _$$ApplyAltsResponseImplCopyWith(
77+ _$ApplyAltsResponseImpl value,
78+ $Res Function(_$ApplyAltsResponseImpl) then,
79+ ) = __$$ApplyAltsResponseImplCopyWithImpl<$Res>;
80+ @override
81+ @useResult
82+ $Res call({bool success});
83+}
84+85+/// @nodoc
86+class __$$ApplyAltsResponseImplCopyWithImpl<$Res>
87+ extends _$ApplyAltsResponseCopyWithImpl<$Res, _$ApplyAltsResponseImpl>
88+ implements _$$ApplyAltsResponseImplCopyWith<$Res> {
89+ __$$ApplyAltsResponseImplCopyWithImpl(
90+ _$ApplyAltsResponseImpl _value,
91+ $Res Function(_$ApplyAltsResponseImpl) _then,
92+ ) : super(_value, _then);
93+94+ /// Create a copy of ApplyAltsResponse
95+ /// with the given fields replaced by the non-null parameter values.
96+ @pragma('vm:prefer-inline')
97+ @override
98+ $Res call({Object? success = null}) {
99+ return _then(
100+ _$ApplyAltsResponseImpl(
101+ success: null == success
102+ ? _value.success
103+ : success // ignore: cast_nullable_to_non_nullable
104+ as bool,
105+ ),
106+ );
107+ }
108+}
109+110+/// @nodoc
111+@JsonSerializable()
112+class _$ApplyAltsResponseImpl implements _ApplyAltsResponse {
113+ const _$ApplyAltsResponseImpl({required this.success});
114+115+ factory _$ApplyAltsResponseImpl.fromJson(Map<String, dynamic> json) =>
116+ _$$ApplyAltsResponseImplFromJson(json);
117+118+ @override
119+ final bool success;
120+121+ @override
122+ String toString() {
123+ return 'ApplyAltsResponse(success: $success)';
124+ }
125+126+ @override
127+ bool operator ==(Object other) {
128+ return identical(this, other) ||
129+ (other.runtimeType == runtimeType &&
130+ other is _$ApplyAltsResponseImpl &&
131+ (identical(other.success, success) || other.success == success));
132+ }
133+134+ @JsonKey(includeFromJson: false, includeToJson: false)
135+ @override
136+ int get hashCode => Object.hash(runtimeType, success);
137+138+ /// Create a copy of ApplyAltsResponse
139+ /// with the given fields replaced by the non-null parameter values.
140+ @JsonKey(includeFromJson: false, includeToJson: false)
141+ @override
142+ @pragma('vm:prefer-inline')
143+ _$$ApplyAltsResponseImplCopyWith<_$ApplyAltsResponseImpl> get copyWith =>
144+ __$$ApplyAltsResponseImplCopyWithImpl<_$ApplyAltsResponseImpl>(
145+ this,
146+ _$identity,
147+ );
148+149+ @override
150+ Map<String, dynamic> toJson() {
151+ return _$$ApplyAltsResponseImplToJson(this);
152+ }
153+}
154+155+abstract class _ApplyAltsResponse implements ApplyAltsResponse {
156+ const factory _ApplyAltsResponse({required final bool success}) =
157+ _$ApplyAltsResponseImpl;
158+159+ factory _ApplyAltsResponse.fromJson(Map<String, dynamic> json) =
160+ _$ApplyAltsResponseImpl.fromJson;
161+162+ @override
163+ bool get success;
164+165+ /// Create a copy of ApplyAltsResponse
166+ /// with the given fields replaced by the non-null parameter values.
167+ @override
168+ @JsonKey(includeFromJson: false, includeToJson: false)
169+ _$$ApplyAltsResponseImplCopyWith<_$ApplyAltsResponseImpl> get copyWith =>
170+ throw _privateConstructorUsedError;
171+}
+15
lib/models/procedures/apply_alts_response.g.dart
···000000000000000
···1+// GENERATED CODE - DO NOT MODIFY BY HAND
2+3+part of 'apply_alts_response.dart';
4+5+// **************************************************************************
6+// JsonSerializableGenerator
7+// **************************************************************************
8+9+_$ApplyAltsResponseImpl _$$ApplyAltsResponseImplFromJson(
10+ Map<String, dynamic> json,
11+) => _$ApplyAltsResponseImpl(success: json['success'] as bool);
12+13+Map<String, dynamic> _$$ApplyAltsResponseImplToJson(
14+ _$ApplyAltsResponseImpl instance,
15+) => <String, dynamic>{'success': instance.success};
+13
lib/models/procedures/apply_alts_update.dart
···0000000000000
···1+import 'package:freezed_annotation/freezed_annotation.dart';
2+3+part 'apply_alts_update.freezed.dart';
4+part 'apply_alts_update.g.dart';
5+6+/// Update alt text for a photo in a gallery.
7+/// AT URI of the item to update and the alt text to apply.
8+@freezed
9+class ApplyAltsUpdate with _$ApplyAltsUpdate {
10+ const factory ApplyAltsUpdate({required String photoUri, required String alt}) = _ApplyAltsUpdate;
11+12+ factory ApplyAltsUpdate.fromJson(Map<String, dynamic> json) => _$ApplyAltsUpdateFromJson(json);
13+}
···1+// coverage:ignore-file
2+// GENERATED CODE - DO NOT MODIFY BY HAND
3+// ignore_for_file: type=lint
4+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
5+6+part of 'create_exif_request.dart';
7+8+// **************************************************************************
9+// FreezedGenerator
10+// **************************************************************************
11+12+T _$identity<T>(T value) => value;
13+14+final _privateConstructorUsedError = UnsupportedError(
15+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
16+);
17+18+CreateExifRequest _$CreateExifRequestFromJson(Map<String, dynamic> json) {
19+ return _CreateExifRequest.fromJson(json);
20+}
21+22+/// @nodoc
23+mixin _$CreateExifRequest {
24+ String get photo => throw _privateConstructorUsedError;
25+ String? get dateTimeOriginal => throw _privateConstructorUsedError;
26+ int? get exposureTime => throw _privateConstructorUsedError;
27+ int? get fNumber => throw _privateConstructorUsedError;
28+ String? get flash => throw _privateConstructorUsedError;
29+ int? get focalLengthIn35mmFormat => throw _privateConstructorUsedError;
30+ int? get iSO => throw _privateConstructorUsedError;
31+ String? get lensMake => throw _privateConstructorUsedError;
32+ String? get lensModel => throw _privateConstructorUsedError;
33+ String? get make => throw _privateConstructorUsedError;
34+ String? get model => throw _privateConstructorUsedError;
35+36+ /// Serializes this CreateExifRequest to a JSON map.
37+ Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
38+39+ /// Create a copy of CreateExifRequest
40+ /// with the given fields replaced by the non-null parameter values.
41+ @JsonKey(includeFromJson: false, includeToJson: false)
42+ $CreateExifRequestCopyWith<CreateExifRequest> get copyWith =>
43+ throw _privateConstructorUsedError;
44+}
45+46+/// @nodoc
47+abstract class $CreateExifRequestCopyWith<$Res> {
48+ factory $CreateExifRequestCopyWith(
49+ CreateExifRequest value,
50+ $Res Function(CreateExifRequest) then,
51+ ) = _$CreateExifRequestCopyWithImpl<$Res, CreateExifRequest>;
52+ @useResult
53+ $Res call({
54+ String photo,
55+ String? dateTimeOriginal,
56+ int? exposureTime,
57+ int? fNumber,
58+ String? flash,
59+ int? focalLengthIn35mmFormat,
60+ int? iSO,
61+ String? lensMake,
62+ String? lensModel,
63+ String? make,
64+ String? model,
65+ });
66+}
67+68+/// @nodoc
69+class _$CreateExifRequestCopyWithImpl<$Res, $Val extends CreateExifRequest>
70+ implements $CreateExifRequestCopyWith<$Res> {
71+ _$CreateExifRequestCopyWithImpl(this._value, this._then);
72+73+ // ignore: unused_field
74+ final $Val _value;
75+ // ignore: unused_field
76+ final $Res Function($Val) _then;
77+78+ /// Create a copy of CreateExifRequest
79+ /// with the given fields replaced by the non-null parameter values.
80+ @pragma('vm:prefer-inline')
81+ @override
82+ $Res call({
83+ Object? photo = null,
84+ Object? dateTimeOriginal = freezed,
85+ Object? exposureTime = freezed,
86+ Object? fNumber = freezed,
87+ Object? flash = freezed,
88+ Object? focalLengthIn35mmFormat = freezed,
89+ Object? iSO = freezed,
90+ Object? lensMake = freezed,
91+ Object? lensModel = freezed,
92+ Object? make = freezed,
93+ Object? model = freezed,
94+ }) {
95+ return _then(
96+ _value.copyWith(
97+ photo: null == photo
98+ ? _value.photo
99+ : photo // ignore: cast_nullable_to_non_nullable
100+ as String,
101+ dateTimeOriginal: freezed == dateTimeOriginal
102+ ? _value.dateTimeOriginal
103+ : dateTimeOriginal // ignore: cast_nullable_to_non_nullable
104+ as String?,
105+ exposureTime: freezed == exposureTime
106+ ? _value.exposureTime
107+ : exposureTime // ignore: cast_nullable_to_non_nullable
108+ as int?,
109+ fNumber: freezed == fNumber
110+ ? _value.fNumber
111+ : fNumber // ignore: cast_nullable_to_non_nullable
112+ as int?,
113+ flash: freezed == flash
114+ ? _value.flash
115+ : flash // ignore: cast_nullable_to_non_nullable
116+ as String?,
117+ focalLengthIn35mmFormat: freezed == focalLengthIn35mmFormat
118+ ? _value.focalLengthIn35mmFormat
119+ : focalLengthIn35mmFormat // ignore: cast_nullable_to_non_nullable
120+ as int?,
121+ iSO: freezed == iSO
122+ ? _value.iSO
123+ : iSO // ignore: cast_nullable_to_non_nullable
124+ as int?,
125+ lensMake: freezed == lensMake
126+ ? _value.lensMake
127+ : lensMake // ignore: cast_nullable_to_non_nullable
128+ as String?,
129+ lensModel: freezed == lensModel
130+ ? _value.lensModel
131+ : lensModel // ignore: cast_nullable_to_non_nullable
132+ as String?,
133+ make: freezed == make
134+ ? _value.make
135+ : make // ignore: cast_nullable_to_non_nullable
136+ as String?,
137+ model: freezed == model
138+ ? _value.model
139+ : model // ignore: cast_nullable_to_non_nullable
140+ as String?,
141+ )
142+ as $Val,
143+ );
144+ }
145+}
146+147+/// @nodoc
148+abstract class _$$CreateExifRequestImplCopyWith<$Res>
149+ implements $CreateExifRequestCopyWith<$Res> {
150+ factory _$$CreateExifRequestImplCopyWith(
151+ _$CreateExifRequestImpl value,
152+ $Res Function(_$CreateExifRequestImpl) then,
153+ ) = __$$CreateExifRequestImplCopyWithImpl<$Res>;
154+ @override
155+ @useResult
156+ $Res call({
157+ String photo,
158+ String? dateTimeOriginal,
159+ int? exposureTime,
160+ int? fNumber,
161+ String? flash,
162+ int? focalLengthIn35mmFormat,
163+ int? iSO,
164+ String? lensMake,
165+ String? lensModel,
166+ String? make,
167+ String? model,
168+ });
169+}
170+171+/// @nodoc
172+class __$$CreateExifRequestImplCopyWithImpl<$Res>
173+ extends _$CreateExifRequestCopyWithImpl<$Res, _$CreateExifRequestImpl>
174+ implements _$$CreateExifRequestImplCopyWith<$Res> {
175+ __$$CreateExifRequestImplCopyWithImpl(
176+ _$CreateExifRequestImpl _value,
177+ $Res Function(_$CreateExifRequestImpl) _then,
178+ ) : super(_value, _then);
179+180+ /// Create a copy of CreateExifRequest
181+ /// with the given fields replaced by the non-null parameter values.
182+ @pragma('vm:prefer-inline')
183+ @override
184+ $Res call({
185+ Object? photo = null,
186+ Object? dateTimeOriginal = freezed,
187+ Object? exposureTime = freezed,
188+ Object? fNumber = freezed,
189+ Object? flash = freezed,
190+ Object? focalLengthIn35mmFormat = freezed,
191+ Object? iSO = freezed,
192+ Object? lensMake = freezed,
193+ Object? lensModel = freezed,
194+ Object? make = freezed,
195+ Object? model = freezed,
196+ }) {
197+ return _then(
198+ _$CreateExifRequestImpl(
199+ photo: null == photo
200+ ? _value.photo
201+ : photo // ignore: cast_nullable_to_non_nullable
202+ as String,
203+ dateTimeOriginal: freezed == dateTimeOriginal
204+ ? _value.dateTimeOriginal
205+ : dateTimeOriginal // ignore: cast_nullable_to_non_nullable
206+ as String?,
207+ exposureTime: freezed == exposureTime
208+ ? _value.exposureTime
209+ : exposureTime // ignore: cast_nullable_to_non_nullable
210+ as int?,
211+ fNumber: freezed == fNumber
212+ ? _value.fNumber
213+ : fNumber // ignore: cast_nullable_to_non_nullable
214+ as int?,
215+ flash: freezed == flash
216+ ? _value.flash
217+ : flash // ignore: cast_nullable_to_non_nullable
218+ as String?,
219+ focalLengthIn35mmFormat: freezed == focalLengthIn35mmFormat
220+ ? _value.focalLengthIn35mmFormat
221+ : focalLengthIn35mmFormat // ignore: cast_nullable_to_non_nullable
222+ as int?,
223+ iSO: freezed == iSO
224+ ? _value.iSO
225+ : iSO // ignore: cast_nullable_to_non_nullable
226+ as int?,
227+ lensMake: freezed == lensMake
228+ ? _value.lensMake
229+ : lensMake // ignore: cast_nullable_to_non_nullable
230+ as String?,
231+ lensModel: freezed == lensModel
232+ ? _value.lensModel
233+ : lensModel // ignore: cast_nullable_to_non_nullable
234+ as String?,
235+ make: freezed == make
236+ ? _value.make
237+ : make // ignore: cast_nullable_to_non_nullable
238+ as String?,
239+ model: freezed == model
240+ ? _value.model
241+ : model // ignore: cast_nullable_to_non_nullable
242+ as String?,
243+ ),
244+ );
245+ }
246+}
247+248+/// @nodoc
249+@JsonSerializable()
250+class _$CreateExifRequestImpl implements _CreateExifRequest {
251+ const _$CreateExifRequestImpl({
252+ required this.photo,
253+ this.dateTimeOriginal,
254+ this.exposureTime,
255+ this.fNumber,
256+ this.flash,
257+ this.focalLengthIn35mmFormat,
258+ this.iSO,
259+ this.lensMake,
260+ this.lensModel,
261+ this.make,
262+ this.model,
263+ });
264+265+ factory _$CreateExifRequestImpl.fromJson(Map<String, dynamic> json) =>
266+ _$$CreateExifRequestImplFromJson(json);
267+268+ @override
269+ final String photo;
270+ @override
271+ final String? dateTimeOriginal;
272+ @override
273+ final int? exposureTime;
274+ @override
275+ final int? fNumber;
276+ @override
277+ final String? flash;
278+ @override
279+ final int? focalLengthIn35mmFormat;
280+ @override
281+ final int? iSO;
282+ @override
283+ final String? lensMake;
284+ @override
285+ final String? lensModel;
286+ @override
287+ final String? make;
288+ @override
289+ final String? model;
290+291+ @override
292+ String toString() {
293+ return 'CreateExifRequest(photo: $photo, dateTimeOriginal: $dateTimeOriginal, exposureTime: $exposureTime, fNumber: $fNumber, flash: $flash, focalLengthIn35mmFormat: $focalLengthIn35mmFormat, iSO: $iSO, lensMake: $lensMake, lensModel: $lensModel, make: $make, model: $model)';
294+ }
295+296+ @override
297+ bool operator ==(Object other) {
298+ return identical(this, other) ||
299+ (other.runtimeType == runtimeType &&
300+ other is _$CreateExifRequestImpl &&
301+ (identical(other.photo, photo) || other.photo == photo) &&
302+ (identical(other.dateTimeOriginal, dateTimeOriginal) ||
303+ other.dateTimeOriginal == dateTimeOriginal) &&
304+ (identical(other.exposureTime, exposureTime) ||
305+ other.exposureTime == exposureTime) &&
306+ (identical(other.fNumber, fNumber) || other.fNumber == fNumber) &&
307+ (identical(other.flash, flash) || other.flash == flash) &&
308+ (identical(
309+ other.focalLengthIn35mmFormat,
310+ focalLengthIn35mmFormat,
311+ ) ||
312+ other.focalLengthIn35mmFormat == focalLengthIn35mmFormat) &&
313+ (identical(other.iSO, iSO) || other.iSO == iSO) &&
314+ (identical(other.lensMake, lensMake) ||
315+ other.lensMake == lensMake) &&
316+ (identical(other.lensModel, lensModel) ||
317+ other.lensModel == lensModel) &&
318+ (identical(other.make, make) || other.make == make) &&
319+ (identical(other.model, model) || other.model == model));
320+ }
321+322+ @JsonKey(includeFromJson: false, includeToJson: false)
323+ @override
324+ int get hashCode => Object.hash(
325+ runtimeType,
326+ photo,
327+ dateTimeOriginal,
328+ exposureTime,
329+ fNumber,
330+ flash,
331+ focalLengthIn35mmFormat,
332+ iSO,
333+ lensMake,
334+ lensModel,
335+ make,
336+ model,
337+ );
338+339+ /// Create a copy of CreateExifRequest
340+ /// with the given fields replaced by the non-null parameter values.
341+ @JsonKey(includeFromJson: false, includeToJson: false)
342+ @override
343+ @pragma('vm:prefer-inline')
344+ _$$CreateExifRequestImplCopyWith<_$CreateExifRequestImpl> get copyWith =>
345+ __$$CreateExifRequestImplCopyWithImpl<_$CreateExifRequestImpl>(
346+ this,
347+ _$identity,
348+ );
349+350+ @override
351+ Map<String, dynamic> toJson() {
352+ return _$$CreateExifRequestImplToJson(this);
353+ }
354+}
355+356+abstract class _CreateExifRequest implements CreateExifRequest {
357+ const factory _CreateExifRequest({
358+ required final String photo,
359+ final String? dateTimeOriginal,
360+ final int? exposureTime,
361+ final int? fNumber,
362+ final String? flash,
363+ final int? focalLengthIn35mmFormat,
364+ final int? iSO,
365+ final String? lensMake,
366+ final String? lensModel,
367+ final String? make,
368+ final String? model,
369+ }) = _$CreateExifRequestImpl;
370+371+ factory _CreateExifRequest.fromJson(Map<String, dynamic> json) =
372+ _$CreateExifRequestImpl.fromJson;
373+374+ @override
375+ String get photo;
376+ @override
377+ String? get dateTimeOriginal;
378+ @override
379+ int? get exposureTime;
380+ @override
381+ int? get fNumber;
382+ @override
383+ String? get flash;
384+ @override
385+ int? get focalLengthIn35mmFormat;
386+ @override
387+ int? get iSO;
388+ @override
389+ String? get lensMake;
390+ @override
391+ String? get lensModel;
392+ @override
393+ String? get make;
394+ @override
395+ String? get model;
396+397+ /// Create a copy of CreateExifRequest
398+ /// with the given fields replaced by the non-null parameter values.
399+ @override
400+ @JsonKey(includeFromJson: false, includeToJson: false)
401+ _$$CreateExifRequestImplCopyWith<_$CreateExifRequestImpl> get copyWith =>
402+ throw _privateConstructorUsedError;
403+}
+39
lib/models/procedures/create_exif_request.g.dart
···000000000000000000000000000000000000000
···1+// GENERATED CODE - DO NOT MODIFY BY HAND
2+3+part of 'create_exif_request.dart';
4+5+// **************************************************************************
6+// JsonSerializableGenerator
7+// **************************************************************************
8+9+_$CreateExifRequestImpl _$$CreateExifRequestImplFromJson(
10+ Map<String, dynamic> json,
11+) => _$CreateExifRequestImpl(
12+ photo: json['photo'] as String,
13+ dateTimeOriginal: json['dateTimeOriginal'] as String?,
14+ exposureTime: (json['exposureTime'] as num?)?.toInt(),
15+ fNumber: (json['fNumber'] as num?)?.toInt(),
16+ flash: json['flash'] as String?,
17+ focalLengthIn35mmFormat: (json['focalLengthIn35mmFormat'] as num?)?.toInt(),
18+ iSO: (json['iSO'] as num?)?.toInt(),
19+ lensMake: json['lensMake'] as String?,
20+ lensModel: json['lensModel'] as String?,
21+ make: json['make'] as String?,
22+ model: json['model'] as String?,
23+);
24+25+Map<String, dynamic> _$$CreateExifRequestImplToJson(
26+ _$CreateExifRequestImpl instance,
27+) => <String, dynamic>{
28+ 'photo': instance.photo,
29+ 'dateTimeOriginal': instance.dateTimeOriginal,
30+ 'exposureTime': instance.exposureTime,
31+ 'fNumber': instance.fNumber,
32+ 'flash': instance.flash,
33+ 'focalLengthIn35mmFormat': instance.focalLengthIn35mmFormat,
34+ 'iSO': instance.iSO,
35+ 'lensMake': instance.lensMake,
36+ 'lensModel': instance.lensModel,
37+ 'make': instance.make,
38+ 'model': instance.model,
39+};
+15
lib/models/procedures/create_exif_response.dart
···000000000000000
···1+import 'package:freezed_annotation/freezed_annotation.dart';
2+3+part 'create_exif_response.freezed.dart';
4+part 'create_exif_response.g.dart';
5+6+/// Response model for creating a new Exif record for a photo.
7+///
8+/// [exifUri] - The URI of the created Exif record.
9+@freezed
10+class CreateExifResponse with _$CreateExifResponse {
11+ const factory CreateExifResponse({required String exifUri}) = _CreateExifResponse;
12+13+ factory CreateExifResponse.fromJson(Map<String, dynamic> json) =>
14+ _$CreateExifResponseFromJson(json);
15+}
···1name: grain
2-description: "A new Flutter project."
3# The following line prevents the package from being accidentally published to
4# pub.dev using `flutter pub publish`. This is preferred for private packages.
5publish_to: "none" # Remove this line if you wish to publish to pub.dev
···16# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17# In Windows, build-name is used as the major, minor, and patch parts
18# of the product and file versions while build-number is used as the build suffix.
19-version: 1.0.0+17
2021environment:
22 sdk: ^3.8.1
···1name: grain
2+description: "Grain Social Mobile App"
3# The following line prevents the package from being accidentally published to
4# pub.dev using `flutter pub publish`. This is preferred for private packages.
5publish_to: "none" # Remove this line if you wish to publish to pub.dev
···16# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17# In Windows, build-name is used as the major, minor, and patch parts
18# of the product and file versions while build-number is used as the build suffix.
19+version: 1.0.0+20
2021environment:
22 sdk: ^3.8.1