+83
.github/instructions/api.instructions.md
+83
.github/instructions/api.instructions.md
···
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`
+2
-1
.vscode/settings.json
+2
-1
.vscode/settings.json
+695
lexicons/app/bsky/actor/defs.json
+695
lexicons/app/bsky/actor/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.actor.defs",
4
+
"defs": {
5
+
"nux": {
6
+
"type": "object",
7
+
"required": [
8
+
"id",
9
+
"completed"
10
+
],
11
+
"properties": {
12
+
"id": {
13
+
"type": "string",
14
+
"maxLength": 100
15
+
},
16
+
"data": {
17
+
"type": "string",
18
+
"maxLength": 3000,
19
+
"description": "Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters.",
20
+
"maxGraphemes": 300
21
+
},
22
+
"completed": {
23
+
"type": "boolean",
24
+
"default": false
25
+
},
26
+
"expiresAt": {
27
+
"type": "string",
28
+
"format": "datetime",
29
+
"description": "The date and time at which the NUX will expire and should be considered completed."
30
+
}
31
+
},
32
+
"description": "A new user experiences (NUX) storage object"
33
+
},
34
+
"mutedWord": {
35
+
"type": "object",
36
+
"required": [
37
+
"value",
38
+
"targets"
39
+
],
40
+
"properties": {
41
+
"id": {
42
+
"type": "string"
43
+
},
44
+
"value": {
45
+
"type": "string",
46
+
"maxLength": 10000,
47
+
"description": "The muted word itself.",
48
+
"maxGraphemes": 1000
49
+
},
50
+
"targets": {
51
+
"type": "array",
52
+
"items": {
53
+
"ref": "app.bsky.actor.defs#mutedWordTarget",
54
+
"type": "ref"
55
+
},
56
+
"description": "The intended targets of the muted word."
57
+
},
58
+
"expiresAt": {
59
+
"type": "string",
60
+
"format": "datetime",
61
+
"description": "The date and time at which the muted word will expire and no longer be applied."
62
+
},
63
+
"actorTarget": {
64
+
"type": "string",
65
+
"default": "all",
66
+
"description": "Groups of users to apply the muted word to. If undefined, applies to all users.",
67
+
"knownValues": [
68
+
"all",
69
+
"exclude-following"
70
+
]
71
+
}
72
+
},
73
+
"description": "A word that the account owner has muted."
74
+
},
75
+
"savedFeed": {
76
+
"type": "object",
77
+
"required": [
78
+
"id",
79
+
"type",
80
+
"value",
81
+
"pinned"
82
+
],
83
+
"properties": {
84
+
"id": {
85
+
"type": "string"
86
+
},
87
+
"type": {
88
+
"type": "string",
89
+
"knownValues": [
90
+
"feed",
91
+
"list",
92
+
"timeline"
93
+
]
94
+
},
95
+
"value": {
96
+
"type": "string"
97
+
},
98
+
"pinned": {
99
+
"type": "boolean"
100
+
}
101
+
}
102
+
},
103
+
"preferences": {
104
+
"type": "array",
105
+
"items": {
106
+
"refs": [
107
+
"#adultContentPref",
108
+
"#contentLabelPref",
109
+
"#savedFeedsPref",
110
+
"#savedFeedsPrefV2",
111
+
"#personalDetailsPref",
112
+
"#feedViewPref",
113
+
"#threadViewPref",
114
+
"#interestsPref",
115
+
"#mutedWordsPref",
116
+
"#hiddenPostsPref",
117
+
"#bskyAppStatePref",
118
+
"#labelersPref",
119
+
"#postInteractionSettingsPref"
120
+
],
121
+
"type": "union"
122
+
}
123
+
},
124
+
"profileView": {
125
+
"type": "object",
126
+
"required": [
127
+
"did",
128
+
"handle"
129
+
],
130
+
"properties": {
131
+
"did": {
132
+
"type": "string",
133
+
"format": "did"
134
+
},
135
+
"avatar": {
136
+
"type": "string",
137
+
"format": "uri"
138
+
},
139
+
"handle": {
140
+
"type": "string",
141
+
"format": "handle"
142
+
},
143
+
"labels": {
144
+
"type": "array",
145
+
"items": {
146
+
"ref": "com.atproto.label.defs#label",
147
+
"type": "ref"
148
+
}
149
+
},
150
+
"viewer": {
151
+
"ref": "#viewerState",
152
+
"type": "ref"
153
+
},
154
+
"createdAt": {
155
+
"type": "string",
156
+
"format": "datetime"
157
+
},
158
+
"indexedAt": {
159
+
"type": "string",
160
+
"format": "datetime"
161
+
},
162
+
"associated": {
163
+
"ref": "#profileAssociated",
164
+
"type": "ref"
165
+
},
166
+
"description": {
167
+
"type": "string",
168
+
"maxLength": 2560,
169
+
"maxGraphemes": 256
170
+
},
171
+
"displayName": {
172
+
"type": "string",
173
+
"maxLength": 640,
174
+
"maxGraphemes": 64
175
+
}
176
+
}
177
+
},
178
+
"viewerState": {
179
+
"type": "object",
180
+
"properties": {
181
+
"muted": {
182
+
"type": "boolean"
183
+
},
184
+
"blocking": {
185
+
"type": "string",
186
+
"format": "at-uri"
187
+
},
188
+
"blockedBy": {
189
+
"type": "boolean"
190
+
},
191
+
"following": {
192
+
"type": "string",
193
+
"format": "at-uri"
194
+
},
195
+
"followedBy": {
196
+
"type": "string",
197
+
"format": "at-uri"
198
+
},
199
+
"mutedByList": {
200
+
"ref": "app.bsky.graph.defs#listViewBasic",
201
+
"type": "ref"
202
+
},
203
+
"blockingByList": {
204
+
"ref": "app.bsky.graph.defs#listViewBasic",
205
+
"type": "ref"
206
+
},
207
+
"knownFollowers": {
208
+
"ref": "#knownFollowers",
209
+
"type": "ref"
210
+
}
211
+
},
212
+
"description": "Metadata about the requesting account's relationship with the subject account. Only has meaningful content for authed requests."
213
+
},
214
+
"feedViewPref": {
215
+
"type": "object",
216
+
"required": [
217
+
"feed"
218
+
],
219
+
"properties": {
220
+
"feed": {
221
+
"type": "string",
222
+
"description": "The URI of the feed, or an identifier which describes the feed."
223
+
},
224
+
"hideReplies": {
225
+
"type": "boolean",
226
+
"description": "Hide replies in the feed."
227
+
},
228
+
"hideReposts": {
229
+
"type": "boolean",
230
+
"description": "Hide reposts in the feed."
231
+
},
232
+
"hideQuotePosts": {
233
+
"type": "boolean",
234
+
"description": "Hide quote posts in the feed."
235
+
},
236
+
"hideRepliesByLikeCount": {
237
+
"type": "integer",
238
+
"description": "Hide replies in the feed if they do not have this number of likes."
239
+
},
240
+
"hideRepliesByUnfollowed": {
241
+
"type": "boolean",
242
+
"default": true,
243
+
"description": "Hide replies in the feed if they are not by followed users."
244
+
}
245
+
}
246
+
},
247
+
"labelersPref": {
248
+
"type": "object",
249
+
"required": [
250
+
"labelers"
251
+
],
252
+
"properties": {
253
+
"labelers": {
254
+
"type": "array",
255
+
"items": {
256
+
"ref": "#labelerPrefItem",
257
+
"type": "ref"
258
+
}
259
+
}
260
+
}
261
+
},
262
+
"interestsPref": {
263
+
"type": "object",
264
+
"required": [
265
+
"tags"
266
+
],
267
+
"properties": {
268
+
"tags": {
269
+
"type": "array",
270
+
"items": {
271
+
"type": "string",
272
+
"maxLength": 640,
273
+
"maxGraphemes": 64
274
+
},
275
+
"maxLength": 100,
276
+
"description": "A list of tags which describe the account owner's interests gathered during onboarding."
277
+
}
278
+
}
279
+
},
280
+
"knownFollowers": {
281
+
"type": "object",
282
+
"required": [
283
+
"count",
284
+
"followers"
285
+
],
286
+
"properties": {
287
+
"count": {
288
+
"type": "integer"
289
+
},
290
+
"followers": {
291
+
"type": "array",
292
+
"items": {
293
+
"ref": "#profileViewBasic",
294
+
"type": "ref"
295
+
},
296
+
"maxLength": 5,
297
+
"minLength": 0
298
+
}
299
+
},
300
+
"description": "The subject's followers whom you also follow"
301
+
},
302
+
"mutedWordsPref": {
303
+
"type": "object",
304
+
"required": [
305
+
"items"
306
+
],
307
+
"properties": {
308
+
"items": {
309
+
"type": "array",
310
+
"items": {
311
+
"ref": "app.bsky.actor.defs#mutedWord",
312
+
"type": "ref"
313
+
},
314
+
"description": "A list of words the account owner has muted."
315
+
}
316
+
}
317
+
},
318
+
"savedFeedsPref": {
319
+
"type": "object",
320
+
"required": [
321
+
"pinned",
322
+
"saved"
323
+
],
324
+
"properties": {
325
+
"saved": {
326
+
"type": "array",
327
+
"items": {
328
+
"type": "string",
329
+
"format": "at-uri"
330
+
}
331
+
},
332
+
"pinned": {
333
+
"type": "array",
334
+
"items": {
335
+
"type": "string",
336
+
"format": "at-uri"
337
+
}
338
+
},
339
+
"timelineIndex": {
340
+
"type": "integer"
341
+
}
342
+
}
343
+
},
344
+
"threadViewPref": {
345
+
"type": "object",
346
+
"properties": {
347
+
"sort": {
348
+
"type": "string",
349
+
"description": "Sorting mode for threads.",
350
+
"knownValues": [
351
+
"oldest",
352
+
"newest",
353
+
"most-likes",
354
+
"random",
355
+
"hotness"
356
+
]
357
+
},
358
+
"prioritizeFollowedUsers": {
359
+
"type": "boolean",
360
+
"description": "Show followed users at the top of all replies."
361
+
}
362
+
}
363
+
},
364
+
"hiddenPostsPref": {
365
+
"type": "object",
366
+
"required": [
367
+
"items"
368
+
],
369
+
"properties": {
370
+
"items": {
371
+
"type": "array",
372
+
"items": {
373
+
"type": "string",
374
+
"format": "at-uri"
375
+
},
376
+
"description": "A list of URIs of posts the account owner has hidden."
377
+
}
378
+
}
379
+
},
380
+
"labelerPrefItem": {
381
+
"type": "object",
382
+
"required": [
383
+
"did"
384
+
],
385
+
"properties": {
386
+
"did": {
387
+
"type": "string",
388
+
"format": "did"
389
+
}
390
+
}
391
+
},
392
+
"mutedWordTarget": {
393
+
"type": "string",
394
+
"maxLength": 640,
395
+
"knownValues": [
396
+
"content",
397
+
"tag"
398
+
],
399
+
"maxGraphemes": 64
400
+
},
401
+
"adultContentPref": {
402
+
"type": "object",
403
+
"required": [
404
+
"enabled"
405
+
],
406
+
"properties": {
407
+
"enabled": {
408
+
"type": "boolean",
409
+
"default": false
410
+
}
411
+
}
412
+
},
413
+
"bskyAppStatePref": {
414
+
"type": "object",
415
+
"properties": {
416
+
"nuxs": {
417
+
"type": "array",
418
+
"items": {
419
+
"ref": "app.bsky.actor.defs#nux",
420
+
"type": "ref"
421
+
},
422
+
"maxLength": 100,
423
+
"description": "Storage for NUXs the user has encountered."
424
+
},
425
+
"queuedNudges": {
426
+
"type": "array",
427
+
"items": {
428
+
"type": "string",
429
+
"maxLength": 100
430
+
},
431
+
"maxLength": 1000,
432
+
"description": "An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user."
433
+
},
434
+
"activeProgressGuide": {
435
+
"ref": "#bskyAppProgressGuide",
436
+
"type": "ref"
437
+
}
438
+
},
439
+
"description": "A grab bag of state that's specific to the bsky.app program. Third-party apps shouldn't use this."
440
+
},
441
+
"contentLabelPref": {
442
+
"type": "object",
443
+
"required": [
444
+
"label",
445
+
"visibility"
446
+
],
447
+
"properties": {
448
+
"label": {
449
+
"type": "string"
450
+
},
451
+
"labelerDid": {
452
+
"type": "string",
453
+
"format": "did",
454
+
"description": "Which labeler does this preference apply to? If undefined, applies globally."
455
+
},
456
+
"visibility": {
457
+
"type": "string",
458
+
"knownValues": [
459
+
"ignore",
460
+
"show",
461
+
"warn",
462
+
"hide"
463
+
]
464
+
}
465
+
}
466
+
},
467
+
"profileViewBasic": {
468
+
"type": "object",
469
+
"required": [
470
+
"did",
471
+
"handle"
472
+
],
473
+
"properties": {
474
+
"did": {
475
+
"type": "string",
476
+
"format": "did"
477
+
},
478
+
"avatar": {
479
+
"type": "string",
480
+
"format": "uri"
481
+
},
482
+
"handle": {
483
+
"type": "string",
484
+
"format": "handle"
485
+
},
486
+
"labels": {
487
+
"type": "array",
488
+
"items": {
489
+
"ref": "com.atproto.label.defs#label",
490
+
"type": "ref"
491
+
}
492
+
},
493
+
"viewer": {
494
+
"ref": "#viewerState",
495
+
"type": "ref"
496
+
},
497
+
"createdAt": {
498
+
"type": "string",
499
+
"format": "datetime"
500
+
},
501
+
"associated": {
502
+
"ref": "#profileAssociated",
503
+
"type": "ref"
504
+
},
505
+
"displayName": {
506
+
"type": "string",
507
+
"maxLength": 640,
508
+
"maxGraphemes": 64
509
+
}
510
+
}
511
+
},
512
+
"savedFeedsPrefV2": {
513
+
"type": "object",
514
+
"required": [
515
+
"items"
516
+
],
517
+
"properties": {
518
+
"items": {
519
+
"type": "array",
520
+
"items": {
521
+
"ref": "app.bsky.actor.defs#savedFeed",
522
+
"type": "ref"
523
+
}
524
+
}
525
+
}
526
+
},
527
+
"profileAssociated": {
528
+
"type": "object",
529
+
"properties": {
530
+
"chat": {
531
+
"ref": "#profileAssociatedChat",
532
+
"type": "ref"
533
+
},
534
+
"lists": {
535
+
"type": "integer"
536
+
},
537
+
"labeler": {
538
+
"type": "boolean"
539
+
},
540
+
"feedgens": {
541
+
"type": "integer"
542
+
},
543
+
"starterPacks": {
544
+
"type": "integer"
545
+
}
546
+
}
547
+
},
548
+
"personalDetailsPref": {
549
+
"type": "object",
550
+
"properties": {
551
+
"birthDate": {
552
+
"type": "string",
553
+
"format": "datetime",
554
+
"description": "The birth date of account owner."
555
+
}
556
+
}
557
+
},
558
+
"profileViewDetailed": {
559
+
"type": "object",
560
+
"required": [
561
+
"did",
562
+
"handle"
563
+
],
564
+
"properties": {
565
+
"did": {
566
+
"type": "string",
567
+
"format": "did"
568
+
},
569
+
"avatar": {
570
+
"type": "string",
571
+
"format": "uri"
572
+
},
573
+
"banner": {
574
+
"type": "string",
575
+
"format": "uri"
576
+
},
577
+
"handle": {
578
+
"type": "string",
579
+
"format": "handle"
580
+
},
581
+
"labels": {
582
+
"type": "array",
583
+
"items": {
584
+
"ref": "com.atproto.label.defs#label",
585
+
"type": "ref"
586
+
}
587
+
},
588
+
"viewer": {
589
+
"ref": "#viewerState",
590
+
"type": "ref"
591
+
},
592
+
"createdAt": {
593
+
"type": "string",
594
+
"format": "datetime"
595
+
},
596
+
"indexedAt": {
597
+
"type": "string",
598
+
"format": "datetime"
599
+
},
600
+
"associated": {
601
+
"ref": "#profileAssociated",
602
+
"type": "ref"
603
+
},
604
+
"pinnedPost": {
605
+
"ref": "com.atproto.repo.strongRef",
606
+
"type": "ref"
607
+
},
608
+
"postsCount": {
609
+
"type": "integer"
610
+
},
611
+
"description": {
612
+
"type": "string",
613
+
"maxLength": 2560,
614
+
"maxGraphemes": 256
615
+
},
616
+
"displayName": {
617
+
"type": "string",
618
+
"maxLength": 640,
619
+
"maxGraphemes": 64
620
+
},
621
+
"followsCount": {
622
+
"type": "integer"
623
+
},
624
+
"followersCount": {
625
+
"type": "integer"
626
+
},
627
+
"joinedViaStarterPack": {
628
+
"ref": "app.bsky.graph.defs#starterPackViewBasic",
629
+
"type": "ref"
630
+
}
631
+
}
632
+
},
633
+
"bskyAppProgressGuide": {
634
+
"type": "object",
635
+
"required": [
636
+
"guide"
637
+
],
638
+
"properties": {
639
+
"guide": {
640
+
"type": "string",
641
+
"maxLength": 100
642
+
}
643
+
},
644
+
"description": "If set, an active progress guide. Once completed, can be set to undefined. Should have unspecced fields tracking progress."
645
+
},
646
+
"profileAssociatedChat": {
647
+
"type": "object",
648
+
"required": [
649
+
"allowIncoming"
650
+
],
651
+
"properties": {
652
+
"allowIncoming": {
653
+
"type": "string",
654
+
"knownValues": [
655
+
"all",
656
+
"none",
657
+
"following"
658
+
]
659
+
}
660
+
}
661
+
},
662
+
"postInteractionSettingsPref": {
663
+
"type": "object",
664
+
"required": [],
665
+
"properties": {
666
+
"threadgateAllowRules": {
667
+
"type": "array",
668
+
"items": {
669
+
"refs": [
670
+
"app.bsky.feed.threadgate#mentionRule",
671
+
"app.bsky.feed.threadgate#followerRule",
672
+
"app.bsky.feed.threadgate#followingRule",
673
+
"app.bsky.feed.threadgate#listRule"
674
+
],
675
+
"type": "union"
676
+
},
677
+
"maxLength": 5,
678
+
"description": "Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply."
679
+
},
680
+
"postgateEmbeddingRules": {
681
+
"type": "array",
682
+
"items": {
683
+
"refs": [
684
+
"app.bsky.feed.postgate#disableRule"
685
+
],
686
+
"type": "union"
687
+
},
688
+
"maxLength": 5,
689
+
"description": "Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed."
690
+
}
691
+
},
692
+
"description": "Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly."
693
+
}
694
+
}
695
+
}
+64
lexicons/app/bsky/actor/profile.json
+64
lexicons/app/bsky/actor/profile.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.actor.profile",
4
+
"defs": {
5
+
"main": {
6
+
"key": "literal:self",
7
+
"type": "record",
8
+
"record": {
9
+
"type": "object",
10
+
"properties": {
11
+
"avatar": {
12
+
"type": "blob",
13
+
"accept": [
14
+
"image/png",
15
+
"image/jpeg"
16
+
],
17
+
"maxSize": 1000000,
18
+
"description": "Small image to be displayed next to posts from account. AKA, 'profile picture'"
19
+
},
20
+
"banner": {
21
+
"type": "blob",
22
+
"accept": [
23
+
"image/png",
24
+
"image/jpeg"
25
+
],
26
+
"maxSize": 1000000,
27
+
"description": "Larger horizontal image to display behind profile view."
28
+
},
29
+
"labels": {
30
+
"refs": [
31
+
"com.atproto.label.defs#selfLabels"
32
+
],
33
+
"type": "union",
34
+
"description": "Self-label values, specific to the Bluesky application, on the overall account."
35
+
},
36
+
"createdAt": {
37
+
"type": "string",
38
+
"format": "datetime"
39
+
},
40
+
"pinnedPost": {
41
+
"ref": "com.atproto.repo.strongRef",
42
+
"type": "ref"
43
+
},
44
+
"description": {
45
+
"type": "string",
46
+
"maxLength": 2560,
47
+
"description": "Free-form profile description text.",
48
+
"maxGraphemes": 256
49
+
},
50
+
"displayName": {
51
+
"type": "string",
52
+
"maxLength": 640,
53
+
"maxGraphemes": 64
54
+
},
55
+
"joinedViaStarterPack": {
56
+
"ref": "com.atproto.repo.strongRef",
57
+
"type": "ref"
58
+
}
59
+
}
60
+
},
61
+
"description": "A declaration of a Bluesky account profile."
62
+
}
63
+
}
64
+
}
+24
lexicons/app/bsky/embed/defs.json
+24
lexicons/app/bsky/embed/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.defs",
4
+
"defs": {
5
+
"aspectRatio": {
6
+
"type": "object",
7
+
"required": [
8
+
"width",
9
+
"height"
10
+
],
11
+
"properties": {
12
+
"width": {
13
+
"type": "integer",
14
+
"minimum": 1
15
+
},
16
+
"height": {
17
+
"type": "integer",
18
+
"minimum": 1
19
+
}
20
+
},
21
+
"description": "width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit."
22
+
}
23
+
}
24
+
}
+82
lexicons/app/bsky/embed/external.json
+82
lexicons/app/bsky/embed/external.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.external",
4
+
"defs": {
5
+
"main": {
6
+
"type": "object",
7
+
"required": [
8
+
"external"
9
+
],
10
+
"properties": {
11
+
"external": {
12
+
"ref": "#external",
13
+
"type": "ref"
14
+
}
15
+
},
16
+
"description": "A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post)."
17
+
},
18
+
"view": {
19
+
"type": "object",
20
+
"required": [
21
+
"external"
22
+
],
23
+
"properties": {
24
+
"external": {
25
+
"ref": "#viewExternal",
26
+
"type": "ref"
27
+
}
28
+
}
29
+
},
30
+
"external": {
31
+
"type": "object",
32
+
"required": [
33
+
"uri",
34
+
"title",
35
+
"description"
36
+
],
37
+
"properties": {
38
+
"uri": {
39
+
"type": "string",
40
+
"format": "uri"
41
+
},
42
+
"thumb": {
43
+
"type": "blob",
44
+
"accept": [
45
+
"image/*"
46
+
],
47
+
"maxSize": 1000000
48
+
},
49
+
"title": {
50
+
"type": "string"
51
+
},
52
+
"description": {
53
+
"type": "string"
54
+
}
55
+
}
56
+
},
57
+
"viewExternal": {
58
+
"type": "object",
59
+
"required": [
60
+
"uri",
61
+
"title",
62
+
"description"
63
+
],
64
+
"properties": {
65
+
"uri": {
66
+
"type": "string",
67
+
"format": "uri"
68
+
},
69
+
"thumb": {
70
+
"type": "string",
71
+
"format": "uri"
72
+
},
73
+
"title": {
74
+
"type": "string"
75
+
},
76
+
"description": {
77
+
"type": "string"
78
+
}
79
+
}
80
+
}
81
+
}
82
+
}
+91
lexicons/app/bsky/embed/images.json
+91
lexicons/app/bsky/embed/images.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.images",
4
+
"description": "A set of images embedded in a Bluesky record (eg, a post).",
5
+
"defs": {
6
+
"main": {
7
+
"type": "object",
8
+
"required": [
9
+
"images"
10
+
],
11
+
"properties": {
12
+
"images": {
13
+
"type": "array",
14
+
"items": {
15
+
"ref": "#image",
16
+
"type": "ref"
17
+
},
18
+
"maxLength": 4
19
+
}
20
+
}
21
+
},
22
+
"view": {
23
+
"type": "object",
24
+
"required": [
25
+
"images"
26
+
],
27
+
"properties": {
28
+
"images": {
29
+
"type": "array",
30
+
"items": {
31
+
"ref": "#viewImage",
32
+
"type": "ref"
33
+
},
34
+
"maxLength": 4
35
+
}
36
+
}
37
+
},
38
+
"image": {
39
+
"type": "object",
40
+
"required": [
41
+
"image",
42
+
"alt"
43
+
],
44
+
"properties": {
45
+
"alt": {
46
+
"type": "string",
47
+
"description": "Alt text description of the image, for accessibility."
48
+
},
49
+
"image": {
50
+
"type": "blob",
51
+
"accept": [
52
+
"image/*"
53
+
],
54
+
"maxSize": 1000000
55
+
},
56
+
"aspectRatio": {
57
+
"ref": "app.bsky.embed.defs#aspectRatio",
58
+
"type": "ref"
59
+
}
60
+
}
61
+
},
62
+
"viewImage": {
63
+
"type": "object",
64
+
"required": [
65
+
"thumb",
66
+
"fullsize",
67
+
"alt"
68
+
],
69
+
"properties": {
70
+
"alt": {
71
+
"type": "string",
72
+
"description": "Alt text description of the image, for accessibility."
73
+
},
74
+
"thumb": {
75
+
"type": "string",
76
+
"format": "uri",
77
+
"description": "Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View."
78
+
},
79
+
"fullsize": {
80
+
"type": "string",
81
+
"format": "uri",
82
+
"description": "Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View."
83
+
},
84
+
"aspectRatio": {
85
+
"ref": "app.bsky.embed.defs#aspectRatio",
86
+
"type": "ref"
87
+
}
88
+
}
89
+
}
90
+
}
91
+
}
+160
lexicons/app/bsky/embed/record.json
+160
lexicons/app/bsky/embed/record.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.record",
4
+
"description": "A representation of a record embedded in a Bluesky record (eg, a post). For example, a quote-post, or sharing a feed generator record.",
5
+
"defs": {
6
+
"main": {
7
+
"type": "object",
8
+
"required": [
9
+
"record"
10
+
],
11
+
"properties": {
12
+
"record": {
13
+
"ref": "com.atproto.repo.strongRef",
14
+
"type": "ref"
15
+
}
16
+
}
17
+
},
18
+
"view": {
19
+
"type": "object",
20
+
"required": [
21
+
"record"
22
+
],
23
+
"properties": {
24
+
"record": {
25
+
"refs": [
26
+
"#viewRecord",
27
+
"#viewNotFound",
28
+
"#viewBlocked",
29
+
"#viewDetached",
30
+
"app.bsky.feed.defs#generatorView",
31
+
"app.bsky.graph.defs#listView",
32
+
"app.bsky.labeler.defs#labelerView",
33
+
"app.bsky.graph.defs#starterPackViewBasic"
34
+
],
35
+
"type": "union"
36
+
}
37
+
}
38
+
},
39
+
"viewRecord": {
40
+
"type": "object",
41
+
"required": [
42
+
"uri",
43
+
"cid",
44
+
"author",
45
+
"value",
46
+
"indexedAt"
47
+
],
48
+
"properties": {
49
+
"cid": {
50
+
"type": "string",
51
+
"format": "cid"
52
+
},
53
+
"uri": {
54
+
"type": "string",
55
+
"format": "at-uri"
56
+
},
57
+
"value": {
58
+
"type": "unknown",
59
+
"description": "The record data itself."
60
+
},
61
+
"author": {
62
+
"ref": "app.bsky.actor.defs#profileViewBasic",
63
+
"type": "ref"
64
+
},
65
+
"embeds": {
66
+
"type": "array",
67
+
"items": {
68
+
"refs": [
69
+
"app.bsky.embed.images#view",
70
+
"app.bsky.embed.video#view",
71
+
"app.bsky.embed.external#view",
72
+
"app.bsky.embed.record#view",
73
+
"app.bsky.embed.recordWithMedia#view"
74
+
],
75
+
"type": "union"
76
+
}
77
+
},
78
+
"labels": {
79
+
"type": "array",
80
+
"items": {
81
+
"ref": "com.atproto.label.defs#label",
82
+
"type": "ref"
83
+
}
84
+
},
85
+
"indexedAt": {
86
+
"type": "string",
87
+
"format": "datetime"
88
+
},
89
+
"likeCount": {
90
+
"type": "integer"
91
+
},
92
+
"quoteCount": {
93
+
"type": "integer"
94
+
},
95
+
"replyCount": {
96
+
"type": "integer"
97
+
},
98
+
"repostCount": {
99
+
"type": "integer"
100
+
}
101
+
}
102
+
},
103
+
"viewBlocked": {
104
+
"type": "object",
105
+
"required": [
106
+
"uri",
107
+
"blocked",
108
+
"author"
109
+
],
110
+
"properties": {
111
+
"uri": {
112
+
"type": "string",
113
+
"format": "at-uri"
114
+
},
115
+
"author": {
116
+
"ref": "app.bsky.feed.defs#blockedAuthor",
117
+
"type": "ref"
118
+
},
119
+
"blocked": {
120
+
"type": "boolean",
121
+
"const": true
122
+
}
123
+
}
124
+
},
125
+
"viewDetached": {
126
+
"type": "object",
127
+
"required": [
128
+
"uri",
129
+
"detached"
130
+
],
131
+
"properties": {
132
+
"uri": {
133
+
"type": "string",
134
+
"format": "at-uri"
135
+
},
136
+
"detached": {
137
+
"type": "boolean",
138
+
"const": true
139
+
}
140
+
}
141
+
},
142
+
"viewNotFound": {
143
+
"type": "object",
144
+
"required": [
145
+
"uri",
146
+
"notFound"
147
+
],
148
+
"properties": {
149
+
"uri": {
150
+
"type": "string",
151
+
"format": "at-uri"
152
+
},
153
+
"notFound": {
154
+
"type": "boolean",
155
+
"const": true
156
+
}
157
+
}
158
+
}
159
+
}
160
+
}
+49
lexicons/app/bsky/embed/recordWithMedia.json
+49
lexicons/app/bsky/embed/recordWithMedia.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.recordWithMedia",
4
+
"description": "A representation of a record embedded in a Bluesky record (eg, a post), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card.",
5
+
"defs": {
6
+
"main": {
7
+
"type": "object",
8
+
"required": [
9
+
"record",
10
+
"media"
11
+
],
12
+
"properties": {
13
+
"media": {
14
+
"refs": [
15
+
"app.bsky.embed.images",
16
+
"app.bsky.embed.video",
17
+
"app.bsky.embed.external"
18
+
],
19
+
"type": "union"
20
+
},
21
+
"record": {
22
+
"ref": "app.bsky.embed.record",
23
+
"type": "ref"
24
+
}
25
+
}
26
+
},
27
+
"view": {
28
+
"type": "object",
29
+
"required": [
30
+
"record",
31
+
"media"
32
+
],
33
+
"properties": {
34
+
"media": {
35
+
"refs": [
36
+
"app.bsky.embed.images#view",
37
+
"app.bsky.embed.video#view",
38
+
"app.bsky.embed.external#view"
39
+
],
40
+
"type": "union"
41
+
},
42
+
"record": {
43
+
"ref": "app.bsky.embed.record#view",
44
+
"type": "ref"
45
+
}
46
+
}
47
+
}
48
+
}
49
+
}
+90
lexicons/app/bsky/embed/video.json
+90
lexicons/app/bsky/embed/video.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.embed.video",
4
+
"description": "A video embedded in a Bluesky record (eg, a post).",
5
+
"defs": {
6
+
"main": {
7
+
"type": "object",
8
+
"required": [
9
+
"video"
10
+
],
11
+
"properties": {
12
+
"alt": {
13
+
"type": "string",
14
+
"maxLength": 10000,
15
+
"description": "Alt text description of the video, for accessibility.",
16
+
"maxGraphemes": 1000
17
+
},
18
+
"video": {
19
+
"type": "blob",
20
+
"accept": [
21
+
"video/mp4"
22
+
],
23
+
"maxSize": 50000000
24
+
},
25
+
"captions": {
26
+
"type": "array",
27
+
"items": {
28
+
"ref": "#caption",
29
+
"type": "ref"
30
+
},
31
+
"maxLength": 20
32
+
},
33
+
"aspectRatio": {
34
+
"ref": "app.bsky.embed.defs#aspectRatio",
35
+
"type": "ref"
36
+
}
37
+
}
38
+
},
39
+
"view": {
40
+
"type": "object",
41
+
"required": [
42
+
"cid",
43
+
"playlist"
44
+
],
45
+
"properties": {
46
+
"alt": {
47
+
"type": "string",
48
+
"maxLength": 10000,
49
+
"maxGraphemes": 1000
50
+
},
51
+
"cid": {
52
+
"type": "string",
53
+
"format": "cid"
54
+
},
55
+
"playlist": {
56
+
"type": "string",
57
+
"format": "uri"
58
+
},
59
+
"thumbnail": {
60
+
"type": "string",
61
+
"format": "uri"
62
+
},
63
+
"aspectRatio": {
64
+
"ref": "app.bsky.embed.defs#aspectRatio",
65
+
"type": "ref"
66
+
}
67
+
}
68
+
},
69
+
"caption": {
70
+
"type": "object",
71
+
"required": [
72
+
"lang",
73
+
"file"
74
+
],
75
+
"properties": {
76
+
"file": {
77
+
"type": "blob",
78
+
"accept": [
79
+
"text/vtt"
80
+
],
81
+
"maxSize": 20000
82
+
},
83
+
"lang": {
84
+
"type": "string",
85
+
"format": "language"
86
+
}
87
+
}
88
+
}
89
+
}
90
+
}
+515
lexicons/app/bsky/feed/defs.json
+515
lexicons/app/bsky/feed/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.feed.defs",
4
+
"defs": {
5
+
"postView": {
6
+
"type": "object",
7
+
"required": [
8
+
"uri",
9
+
"cid",
10
+
"author",
11
+
"record",
12
+
"indexedAt"
13
+
],
14
+
"properties": {
15
+
"cid": {
16
+
"type": "string",
17
+
"format": "cid"
18
+
},
19
+
"uri": {
20
+
"type": "string",
21
+
"format": "at-uri"
22
+
},
23
+
"embed": {
24
+
"refs": [
25
+
"app.bsky.embed.images#view",
26
+
"app.bsky.embed.video#view",
27
+
"app.bsky.embed.external#view",
28
+
"app.bsky.embed.record#view",
29
+
"app.bsky.embed.recordWithMedia#view"
30
+
],
31
+
"type": "union"
32
+
},
33
+
"author": {
34
+
"ref": "app.bsky.actor.defs#profileViewBasic",
35
+
"type": "ref"
36
+
},
37
+
"labels": {
38
+
"type": "array",
39
+
"items": {
40
+
"ref": "com.atproto.label.defs#label",
41
+
"type": "ref"
42
+
}
43
+
},
44
+
"record": {
45
+
"type": "unknown"
46
+
},
47
+
"viewer": {
48
+
"ref": "#viewerState",
49
+
"type": "ref"
50
+
},
51
+
"indexedAt": {
52
+
"type": "string",
53
+
"format": "datetime"
54
+
},
55
+
"likeCount": {
56
+
"type": "integer"
57
+
},
58
+
"quoteCount": {
59
+
"type": "integer"
60
+
},
61
+
"replyCount": {
62
+
"type": "integer"
63
+
},
64
+
"threadgate": {
65
+
"ref": "#threadgateView",
66
+
"type": "ref"
67
+
},
68
+
"repostCount": {
69
+
"type": "integer"
70
+
}
71
+
}
72
+
},
73
+
"replyRef": {
74
+
"type": "object",
75
+
"required": [
76
+
"root",
77
+
"parent"
78
+
],
79
+
"properties": {
80
+
"root": {
81
+
"refs": [
82
+
"#postView",
83
+
"#notFoundPost",
84
+
"#blockedPost"
85
+
],
86
+
"type": "union"
87
+
},
88
+
"parent": {
89
+
"refs": [
90
+
"#postView",
91
+
"#notFoundPost",
92
+
"#blockedPost"
93
+
],
94
+
"type": "union"
95
+
},
96
+
"grandparentAuthor": {
97
+
"ref": "app.bsky.actor.defs#profileViewBasic",
98
+
"type": "ref",
99
+
"description": "When parent is a reply to another post, this is the author of that post."
100
+
}
101
+
}
102
+
},
103
+
"reasonPin": {
104
+
"type": "object",
105
+
"properties": {}
106
+
},
107
+
"blockedPost": {
108
+
"type": "object",
109
+
"required": [
110
+
"uri",
111
+
"blocked",
112
+
"author"
113
+
],
114
+
"properties": {
115
+
"uri": {
116
+
"type": "string",
117
+
"format": "at-uri"
118
+
},
119
+
"author": {
120
+
"ref": "#blockedAuthor",
121
+
"type": "ref"
122
+
},
123
+
"blocked": {
124
+
"type": "boolean",
125
+
"const": true
126
+
}
127
+
}
128
+
},
129
+
"interaction": {
130
+
"type": "object",
131
+
"properties": {
132
+
"item": {
133
+
"type": "string",
134
+
"format": "at-uri"
135
+
},
136
+
"event": {
137
+
"type": "string",
138
+
"knownValues": [
139
+
"app.bsky.feed.defs#requestLess",
140
+
"app.bsky.feed.defs#requestMore",
141
+
"app.bsky.feed.defs#clickthroughItem",
142
+
"app.bsky.feed.defs#clickthroughAuthor",
143
+
"app.bsky.feed.defs#clickthroughReposter",
144
+
"app.bsky.feed.defs#clickthroughEmbed",
145
+
"app.bsky.feed.defs#interactionSeen",
146
+
"app.bsky.feed.defs#interactionLike",
147
+
"app.bsky.feed.defs#interactionRepost",
148
+
"app.bsky.feed.defs#interactionReply",
149
+
"app.bsky.feed.defs#interactionQuote",
150
+
"app.bsky.feed.defs#interactionShare"
151
+
]
152
+
},
153
+
"feedContext": {
154
+
"type": "string",
155
+
"maxLength": 2000,
156
+
"description": "Context on a feed item that was originally supplied by the feed generator on getFeedSkeleton."
157
+
}
158
+
}
159
+
},
160
+
"requestLess": {
161
+
"type": "token",
162
+
"description": "Request that less content like the given feed item be shown in the feed"
163
+
},
164
+
"requestMore": {
165
+
"type": "token",
166
+
"description": "Request that more content like the given feed item be shown in the feed"
167
+
},
168
+
"viewerState": {
169
+
"type": "object",
170
+
"properties": {
171
+
"like": {
172
+
"type": "string",
173
+
"format": "at-uri"
174
+
},
175
+
"pinned": {
176
+
"type": "boolean"
177
+
},
178
+
"repost": {
179
+
"type": "string",
180
+
"format": "at-uri"
181
+
},
182
+
"threadMuted": {
183
+
"type": "boolean"
184
+
},
185
+
"replyDisabled": {
186
+
"type": "boolean"
187
+
},
188
+
"embeddingDisabled": {
189
+
"type": "boolean"
190
+
}
191
+
},
192
+
"description": "Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests."
193
+
},
194
+
"feedViewPost": {
195
+
"type": "object",
196
+
"required": [
197
+
"post"
198
+
],
199
+
"properties": {
200
+
"post": {
201
+
"ref": "#postView",
202
+
"type": "ref"
203
+
},
204
+
"reply": {
205
+
"ref": "#replyRef",
206
+
"type": "ref"
207
+
},
208
+
"reason": {
209
+
"refs": [
210
+
"#reasonRepost",
211
+
"#reasonPin"
212
+
],
213
+
"type": "union"
214
+
},
215
+
"feedContext": {
216
+
"type": "string",
217
+
"maxLength": 2000,
218
+
"description": "Context provided by feed generator that may be passed back alongside interactions."
219
+
}
220
+
}
221
+
},
222
+
"notFoundPost": {
223
+
"type": "object",
224
+
"required": [
225
+
"uri",
226
+
"notFound"
227
+
],
228
+
"properties": {
229
+
"uri": {
230
+
"type": "string",
231
+
"format": "at-uri"
232
+
},
233
+
"notFound": {
234
+
"type": "boolean",
235
+
"const": true
236
+
}
237
+
}
238
+
},
239
+
"reasonRepost": {
240
+
"type": "object",
241
+
"required": [
242
+
"by",
243
+
"indexedAt"
244
+
],
245
+
"properties": {
246
+
"by": {
247
+
"ref": "app.bsky.actor.defs#profileViewBasic",
248
+
"type": "ref"
249
+
},
250
+
"indexedAt": {
251
+
"type": "string",
252
+
"format": "datetime"
253
+
}
254
+
}
255
+
},
256
+
"blockedAuthor": {
257
+
"type": "object",
258
+
"required": [
259
+
"did"
260
+
],
261
+
"properties": {
262
+
"did": {
263
+
"type": "string",
264
+
"format": "did"
265
+
},
266
+
"viewer": {
267
+
"ref": "app.bsky.actor.defs#viewerState",
268
+
"type": "ref"
269
+
}
270
+
}
271
+
},
272
+
"generatorView": {
273
+
"type": "object",
274
+
"required": [
275
+
"uri",
276
+
"cid",
277
+
"did",
278
+
"creator",
279
+
"displayName",
280
+
"indexedAt"
281
+
],
282
+
"properties": {
283
+
"cid": {
284
+
"type": "string",
285
+
"format": "cid"
286
+
},
287
+
"did": {
288
+
"type": "string",
289
+
"format": "did"
290
+
},
291
+
"uri": {
292
+
"type": "string",
293
+
"format": "at-uri"
294
+
},
295
+
"avatar": {
296
+
"type": "string",
297
+
"format": "uri"
298
+
},
299
+
"labels": {
300
+
"type": "array",
301
+
"items": {
302
+
"ref": "com.atproto.label.defs#label",
303
+
"type": "ref"
304
+
}
305
+
},
306
+
"viewer": {
307
+
"ref": "#generatorViewerState",
308
+
"type": "ref"
309
+
},
310
+
"creator": {
311
+
"ref": "app.bsky.actor.defs#profileView",
312
+
"type": "ref"
313
+
},
314
+
"indexedAt": {
315
+
"type": "string",
316
+
"format": "datetime"
317
+
},
318
+
"likeCount": {
319
+
"type": "integer",
320
+
"minimum": 0
321
+
},
322
+
"contentMode": {
323
+
"type": "string",
324
+
"knownValues": [
325
+
"app.bsky.feed.defs#contentModeUnspecified",
326
+
"app.bsky.feed.defs#contentModeVideo"
327
+
]
328
+
},
329
+
"description": {
330
+
"type": "string",
331
+
"maxLength": 3000,
332
+
"maxGraphemes": 300
333
+
},
334
+
"displayName": {
335
+
"type": "string"
336
+
},
337
+
"descriptionFacets": {
338
+
"type": "array",
339
+
"items": {
340
+
"ref": "app.bsky.richtext.facet",
341
+
"type": "ref"
342
+
}
343
+
},
344
+
"acceptsInteractions": {
345
+
"type": "boolean"
346
+
}
347
+
}
348
+
},
349
+
"threadContext": {
350
+
"type": "object",
351
+
"properties": {
352
+
"rootAuthorLike": {
353
+
"type": "string",
354
+
"format": "at-uri"
355
+
}
356
+
},
357
+
"description": "Metadata about this post within the context of the thread it is in."
358
+
},
359
+
"threadViewPost": {
360
+
"type": "object",
361
+
"required": [
362
+
"post"
363
+
],
364
+
"properties": {
365
+
"post": {
366
+
"ref": "#postView",
367
+
"type": "ref"
368
+
},
369
+
"parent": {
370
+
"refs": [
371
+
"#threadViewPost",
372
+
"#notFoundPost",
373
+
"#blockedPost"
374
+
],
375
+
"type": "union"
376
+
},
377
+
"replies": {
378
+
"type": "array",
379
+
"items": {
380
+
"refs": [
381
+
"#threadViewPost",
382
+
"#notFoundPost",
383
+
"#blockedPost"
384
+
],
385
+
"type": "union"
386
+
}
387
+
},
388
+
"threadContext": {
389
+
"ref": "#threadContext",
390
+
"type": "ref"
391
+
}
392
+
}
393
+
},
394
+
"threadgateView": {
395
+
"type": "object",
396
+
"properties": {
397
+
"cid": {
398
+
"type": "string",
399
+
"format": "cid"
400
+
},
401
+
"uri": {
402
+
"type": "string",
403
+
"format": "at-uri"
404
+
},
405
+
"lists": {
406
+
"type": "array",
407
+
"items": {
408
+
"ref": "app.bsky.graph.defs#listViewBasic",
409
+
"type": "ref"
410
+
}
411
+
},
412
+
"record": {
413
+
"type": "unknown"
414
+
}
415
+
}
416
+
},
417
+
"interactionLike": {
418
+
"type": "token",
419
+
"description": "User liked the feed item"
420
+
},
421
+
"interactionSeen": {
422
+
"type": "token",
423
+
"description": "Feed item was seen by user"
424
+
},
425
+
"clickthroughItem": {
426
+
"type": "token",
427
+
"description": "User clicked through to the feed item"
428
+
},
429
+
"contentModeVideo": {
430
+
"type": "token",
431
+
"description": "Declares the feed generator returns posts containing app.bsky.embed.video embeds."
432
+
},
433
+
"interactionQuote": {
434
+
"type": "token",
435
+
"description": "User quoted the feed item"
436
+
},
437
+
"interactionReply": {
438
+
"type": "token",
439
+
"description": "User replied to the feed item"
440
+
},
441
+
"interactionShare": {
442
+
"type": "token",
443
+
"description": "User shared the feed item"
444
+
},
445
+
"skeletonFeedPost": {
446
+
"type": "object",
447
+
"required": [
448
+
"post"
449
+
],
450
+
"properties": {
451
+
"post": {
452
+
"type": "string",
453
+
"format": "at-uri"
454
+
},
455
+
"reason": {
456
+
"refs": [
457
+
"#skeletonReasonRepost",
458
+
"#skeletonReasonPin"
459
+
],
460
+
"type": "union"
461
+
},
462
+
"feedContext": {
463
+
"type": "string",
464
+
"maxLength": 2000,
465
+
"description": "Context that will be passed through to client and may be passed to feed generator back alongside interactions."
466
+
}
467
+
}
468
+
},
469
+
"clickthroughEmbed": {
470
+
"type": "token",
471
+
"description": "User clicked through to the embedded content of the feed item"
472
+
},
473
+
"interactionRepost": {
474
+
"type": "token",
475
+
"description": "User reposted the feed item"
476
+
},
477
+
"skeletonReasonPin": {
478
+
"type": "object",
479
+
"properties": {}
480
+
},
481
+
"clickthroughAuthor": {
482
+
"type": "token",
483
+
"description": "User clicked through to the author of the feed item"
484
+
},
485
+
"clickthroughReposter": {
486
+
"type": "token",
487
+
"description": "User clicked through to the reposter of the feed item"
488
+
},
489
+
"generatorViewerState": {
490
+
"type": "object",
491
+
"properties": {
492
+
"like": {
493
+
"type": "string",
494
+
"format": "at-uri"
495
+
}
496
+
}
497
+
},
498
+
"skeletonReasonRepost": {
499
+
"type": "object",
500
+
"required": [
501
+
"repost"
502
+
],
503
+
"properties": {
504
+
"repost": {
505
+
"type": "string",
506
+
"format": "at-uri"
507
+
}
508
+
}
509
+
},
510
+
"contentModeUnspecified": {
511
+
"type": "token",
512
+
"description": "Declares the feed generator returns any types of posts."
513
+
}
514
+
}
515
+
}
+54
lexicons/app/bsky/feed/postgate.json
+54
lexicons/app/bsky/feed/postgate.json
···
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
+
}
+80
lexicons/app/bsky/feed/threadgate.json
+80
lexicons/app/bsky/feed/threadgate.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.feed.threadgate",
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
+
"allow": {
21
+
"type": "array",
22
+
"items": {
23
+
"refs": [
24
+
"#mentionRule",
25
+
"#followerRule",
26
+
"#followingRule",
27
+
"#listRule"
28
+
],
29
+
"type": "union"
30
+
},
31
+
"maxLength": 5,
32
+
"description": "List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply."
33
+
},
34
+
"createdAt": {
35
+
"type": "string",
36
+
"format": "datetime"
37
+
},
38
+
"hiddenReplies": {
39
+
"type": "array",
40
+
"items": {
41
+
"type": "string",
42
+
"format": "at-uri"
43
+
},
44
+
"maxLength": 50,
45
+
"description": "List of hidden reply URIs."
46
+
}
47
+
}
48
+
},
49
+
"description": "Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository."
50
+
},
51
+
"listRule": {
52
+
"type": "object",
53
+
"required": [
54
+
"list"
55
+
],
56
+
"properties": {
57
+
"list": {
58
+
"type": "string",
59
+
"format": "at-uri"
60
+
}
61
+
},
62
+
"description": "Allow replies from actors on a list."
63
+
},
64
+
"mentionRule": {
65
+
"type": "object",
66
+
"properties": {},
67
+
"description": "Allow replies from actors mentioned in your post."
68
+
},
69
+
"followerRule": {
70
+
"type": "object",
71
+
"properties": {},
72
+
"description": "Allow replies from actors who follow you."
73
+
},
74
+
"followingRule": {
75
+
"type": "object",
76
+
"properties": {},
77
+
"description": "Allow replies from actors you follow."
78
+
}
79
+
}
80
+
}
+332
lexicons/app/bsky/graph/defs.json
+332
lexicons/app/bsky/graph/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.graph.defs",
4
+
"defs": {
5
+
"modlist": {
6
+
"type": "token",
7
+
"description": "A list of actors to apply an aggregate moderation action (mute/block) on."
8
+
},
9
+
"listView": {
10
+
"type": "object",
11
+
"required": [
12
+
"uri",
13
+
"cid",
14
+
"creator",
15
+
"name",
16
+
"purpose",
17
+
"indexedAt"
18
+
],
19
+
"properties": {
20
+
"cid": {
21
+
"type": "string",
22
+
"format": "cid"
23
+
},
24
+
"uri": {
25
+
"type": "string",
26
+
"format": "at-uri"
27
+
},
28
+
"name": {
29
+
"type": "string",
30
+
"maxLength": 64,
31
+
"minLength": 1
32
+
},
33
+
"avatar": {
34
+
"type": "string",
35
+
"format": "uri"
36
+
},
37
+
"labels": {
38
+
"type": "array",
39
+
"items": {
40
+
"ref": "com.atproto.label.defs#label",
41
+
"type": "ref"
42
+
}
43
+
},
44
+
"viewer": {
45
+
"ref": "#listViewerState",
46
+
"type": "ref"
47
+
},
48
+
"creator": {
49
+
"ref": "app.bsky.actor.defs#profileView",
50
+
"type": "ref"
51
+
},
52
+
"purpose": {
53
+
"ref": "#listPurpose",
54
+
"type": "ref"
55
+
},
56
+
"indexedAt": {
57
+
"type": "string",
58
+
"format": "datetime"
59
+
},
60
+
"description": {
61
+
"type": "string",
62
+
"maxLength": 3000,
63
+
"maxGraphemes": 300
64
+
},
65
+
"listItemCount": {
66
+
"type": "integer",
67
+
"minimum": 0
68
+
},
69
+
"descriptionFacets": {
70
+
"type": "array",
71
+
"items": {
72
+
"ref": "app.bsky.richtext.facet",
73
+
"type": "ref"
74
+
}
75
+
}
76
+
}
77
+
},
78
+
"curatelist": {
79
+
"type": "token",
80
+
"description": "A list of actors used for curation purposes such as list feeds or interaction gating."
81
+
},
82
+
"listPurpose": {
83
+
"type": "string",
84
+
"knownValues": [
85
+
"app.bsky.graph.defs#modlist",
86
+
"app.bsky.graph.defs#curatelist",
87
+
"app.bsky.graph.defs#referencelist"
88
+
]
89
+
},
90
+
"listItemView": {
91
+
"type": "object",
92
+
"required": [
93
+
"uri",
94
+
"subject"
95
+
],
96
+
"properties": {
97
+
"uri": {
98
+
"type": "string",
99
+
"format": "at-uri"
100
+
},
101
+
"subject": {
102
+
"ref": "app.bsky.actor.defs#profileView",
103
+
"type": "ref"
104
+
}
105
+
}
106
+
},
107
+
"relationship": {
108
+
"type": "object",
109
+
"required": [
110
+
"did"
111
+
],
112
+
"properties": {
113
+
"did": {
114
+
"type": "string",
115
+
"format": "did"
116
+
},
117
+
"following": {
118
+
"type": "string",
119
+
"format": "at-uri",
120
+
"description": "if the actor follows this DID, this is the AT-URI of the follow record"
121
+
},
122
+
"followedBy": {
123
+
"type": "string",
124
+
"format": "at-uri",
125
+
"description": "if the actor is followed by this DID, contains the AT-URI of the follow record"
126
+
}
127
+
},
128
+
"description": "lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object)"
129
+
},
130
+
"listViewBasic": {
131
+
"type": "object",
132
+
"required": [
133
+
"uri",
134
+
"cid",
135
+
"name",
136
+
"purpose"
137
+
],
138
+
"properties": {
139
+
"cid": {
140
+
"type": "string",
141
+
"format": "cid"
142
+
},
143
+
"uri": {
144
+
"type": "string",
145
+
"format": "at-uri"
146
+
},
147
+
"name": {
148
+
"type": "string",
149
+
"maxLength": 64,
150
+
"minLength": 1
151
+
},
152
+
"avatar": {
153
+
"type": "string",
154
+
"format": "uri"
155
+
},
156
+
"labels": {
157
+
"type": "array",
158
+
"items": {
159
+
"ref": "com.atproto.label.defs#label",
160
+
"type": "ref"
161
+
}
162
+
},
163
+
"viewer": {
164
+
"ref": "#listViewerState",
165
+
"type": "ref"
166
+
},
167
+
"purpose": {
168
+
"ref": "#listPurpose",
169
+
"type": "ref"
170
+
},
171
+
"indexedAt": {
172
+
"type": "string",
173
+
"format": "datetime"
174
+
},
175
+
"listItemCount": {
176
+
"type": "integer",
177
+
"minimum": 0
178
+
}
179
+
}
180
+
},
181
+
"notFoundActor": {
182
+
"type": "object",
183
+
"required": [
184
+
"actor",
185
+
"notFound"
186
+
],
187
+
"properties": {
188
+
"actor": {
189
+
"type": "string",
190
+
"format": "at-identifier"
191
+
},
192
+
"notFound": {
193
+
"type": "boolean",
194
+
"const": true
195
+
}
196
+
},
197
+
"description": "indicates that a handle or DID could not be resolved"
198
+
},
199
+
"referencelist": {
200
+
"type": "token",
201
+
"description": "A list of actors used for only for reference purposes such as within a starter pack."
202
+
},
203
+
"listViewerState": {
204
+
"type": "object",
205
+
"properties": {
206
+
"muted": {
207
+
"type": "boolean"
208
+
},
209
+
"blocked": {
210
+
"type": "string",
211
+
"format": "at-uri"
212
+
}
213
+
}
214
+
},
215
+
"starterPackView": {
216
+
"type": "object",
217
+
"required": [
218
+
"uri",
219
+
"cid",
220
+
"record",
221
+
"creator",
222
+
"indexedAt"
223
+
],
224
+
"properties": {
225
+
"cid": {
226
+
"type": "string",
227
+
"format": "cid"
228
+
},
229
+
"uri": {
230
+
"type": "string",
231
+
"format": "at-uri"
232
+
},
233
+
"list": {
234
+
"ref": "#listViewBasic",
235
+
"type": "ref"
236
+
},
237
+
"feeds": {
238
+
"type": "array",
239
+
"items": {
240
+
"ref": "app.bsky.feed.defs#generatorView",
241
+
"type": "ref"
242
+
},
243
+
"maxLength": 3
244
+
},
245
+
"labels": {
246
+
"type": "array",
247
+
"items": {
248
+
"ref": "com.atproto.label.defs#label",
249
+
"type": "ref"
250
+
}
251
+
},
252
+
"record": {
253
+
"type": "unknown"
254
+
},
255
+
"creator": {
256
+
"ref": "app.bsky.actor.defs#profileViewBasic",
257
+
"type": "ref"
258
+
},
259
+
"indexedAt": {
260
+
"type": "string",
261
+
"format": "datetime"
262
+
},
263
+
"joinedWeekCount": {
264
+
"type": "integer",
265
+
"minimum": 0
266
+
},
267
+
"listItemsSample": {
268
+
"type": "array",
269
+
"items": {
270
+
"ref": "#listItemView",
271
+
"type": "ref"
272
+
},
273
+
"maxLength": 12
274
+
},
275
+
"joinedAllTimeCount": {
276
+
"type": "integer",
277
+
"minimum": 0
278
+
}
279
+
}
280
+
},
281
+
"starterPackViewBasic": {
282
+
"type": "object",
283
+
"required": [
284
+
"uri",
285
+
"cid",
286
+
"record",
287
+
"creator",
288
+
"indexedAt"
289
+
],
290
+
"properties": {
291
+
"cid": {
292
+
"type": "string",
293
+
"format": "cid"
294
+
},
295
+
"uri": {
296
+
"type": "string",
297
+
"format": "at-uri"
298
+
},
299
+
"labels": {
300
+
"type": "array",
301
+
"items": {
302
+
"ref": "com.atproto.label.defs#label",
303
+
"type": "ref"
304
+
}
305
+
},
306
+
"record": {
307
+
"type": "unknown"
308
+
},
309
+
"creator": {
310
+
"ref": "app.bsky.actor.defs#profileViewBasic",
311
+
"type": "ref"
312
+
},
313
+
"indexedAt": {
314
+
"type": "string",
315
+
"format": "datetime"
316
+
},
317
+
"listItemCount": {
318
+
"type": "integer",
319
+
"minimum": 0
320
+
},
321
+
"joinedWeekCount": {
322
+
"type": "integer",
323
+
"minimum": 0
324
+
},
325
+
"joinedAllTimeCount": {
326
+
"type": "integer",
327
+
"minimum": 0
328
+
}
329
+
}
330
+
}
331
+
}
332
+
}
+28
lexicons/app/bsky/graph/follow.json
+28
lexicons/app/bsky/graph/follow.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.graph.follow",
4
+
"defs": {
5
+
"main": {
6
+
"key": "tid",
7
+
"type": "record",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"subject",
12
+
"createdAt"
13
+
],
14
+
"properties": {
15
+
"subject": {
16
+
"type": "string",
17
+
"format": "did"
18
+
},
19
+
"createdAt": {
20
+
"type": "string",
21
+
"format": "datetime"
22
+
}
23
+
}
24
+
},
25
+
"description": "Record declaring a social 'follow' relationship of another account. Duplicate follows will be ignored by the AppView."
26
+
}
27
+
}
28
+
}
+128
lexicons/app/bsky/labeler/defs.json
+128
lexicons/app/bsky/labeler/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.labeler.defs",
4
+
"defs": {
5
+
"labelerView": {
6
+
"type": "object",
7
+
"required": [
8
+
"uri",
9
+
"cid",
10
+
"creator",
11
+
"indexedAt"
12
+
],
13
+
"properties": {
14
+
"cid": {
15
+
"type": "string",
16
+
"format": "cid"
17
+
},
18
+
"uri": {
19
+
"type": "string",
20
+
"format": "at-uri"
21
+
},
22
+
"labels": {
23
+
"type": "array",
24
+
"items": {
25
+
"ref": "com.atproto.label.defs#label",
26
+
"type": "ref"
27
+
}
28
+
},
29
+
"viewer": {
30
+
"ref": "#labelerViewerState",
31
+
"type": "ref"
32
+
},
33
+
"creator": {
34
+
"ref": "app.bsky.actor.defs#profileView",
35
+
"type": "ref"
36
+
},
37
+
"indexedAt": {
38
+
"type": "string",
39
+
"format": "datetime"
40
+
},
41
+
"likeCount": {
42
+
"type": "integer",
43
+
"minimum": 0
44
+
}
45
+
}
46
+
},
47
+
"labelerPolicies": {
48
+
"type": "object",
49
+
"required": [
50
+
"labelValues"
51
+
],
52
+
"properties": {
53
+
"labelValues": {
54
+
"type": "array",
55
+
"items": {
56
+
"ref": "com.atproto.label.defs#labelValue",
57
+
"type": "ref"
58
+
},
59
+
"description": "The label values which this labeler publishes. May include global or custom labels."
60
+
},
61
+
"labelValueDefinitions": {
62
+
"type": "array",
63
+
"items": {
64
+
"ref": "com.atproto.label.defs#labelValueDefinition",
65
+
"type": "ref"
66
+
},
67
+
"description": "Label values created by this labeler and scoped exclusively to it. Labels defined here will override global label definitions for this labeler."
68
+
}
69
+
}
70
+
},
71
+
"labelerViewerState": {
72
+
"type": "object",
73
+
"properties": {
74
+
"like": {
75
+
"type": "string",
76
+
"format": "at-uri"
77
+
}
78
+
}
79
+
},
80
+
"labelerViewDetailed": {
81
+
"type": "object",
82
+
"required": [
83
+
"uri",
84
+
"cid",
85
+
"creator",
86
+
"policies",
87
+
"indexedAt"
88
+
],
89
+
"properties": {
90
+
"cid": {
91
+
"type": "string",
92
+
"format": "cid"
93
+
},
94
+
"uri": {
95
+
"type": "string",
96
+
"format": "at-uri"
97
+
},
98
+
"labels": {
99
+
"type": "array",
100
+
"items": {
101
+
"ref": "com.atproto.label.defs#label",
102
+
"type": "ref"
103
+
}
104
+
},
105
+
"viewer": {
106
+
"ref": "#labelerViewerState",
107
+
"type": "ref"
108
+
},
109
+
"creator": {
110
+
"ref": "app.bsky.actor.defs#profileView",
111
+
"type": "ref"
112
+
},
113
+
"policies": {
114
+
"ref": "app.bsky.labeler.defs#labelerPolicies",
115
+
"type": "ref"
116
+
},
117
+
"indexedAt": {
118
+
"type": "string",
119
+
"format": "datetime"
120
+
},
121
+
"likeCount": {
122
+
"type": "integer",
123
+
"minimum": 0
124
+
}
125
+
}
126
+
}
127
+
}
128
+
}
+89
lexicons/app/bsky/richtext/facet.json
+89
lexicons/app/bsky/richtext/facet.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "app.bsky.richtext.facet",
4
+
"defs": {
5
+
"tag": {
6
+
"type": "object",
7
+
"required": [
8
+
"tag"
9
+
],
10
+
"properties": {
11
+
"tag": {
12
+
"type": "string",
13
+
"maxLength": 640,
14
+
"maxGraphemes": 64
15
+
}
16
+
},
17
+
"description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags')."
18
+
},
19
+
"link": {
20
+
"type": "object",
21
+
"required": [
22
+
"uri"
23
+
],
24
+
"properties": {
25
+
"uri": {
26
+
"type": "string",
27
+
"format": "uri"
28
+
}
29
+
},
30
+
"description": "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL."
31
+
},
32
+
"main": {
33
+
"type": "object",
34
+
"required": [
35
+
"index",
36
+
"features"
37
+
],
38
+
"properties": {
39
+
"index": {
40
+
"ref": "#byteSlice",
41
+
"type": "ref"
42
+
},
43
+
"features": {
44
+
"type": "array",
45
+
"items": {
46
+
"refs": [
47
+
"#mention",
48
+
"#link",
49
+
"#tag"
50
+
],
51
+
"type": "union"
52
+
}
53
+
}
54
+
},
55
+
"description": "Annotation of a sub-string within rich text."
56
+
},
57
+
"mention": {
58
+
"type": "object",
59
+
"required": [
60
+
"did"
61
+
],
62
+
"properties": {
63
+
"did": {
64
+
"type": "string",
65
+
"format": "did"
66
+
}
67
+
},
68
+
"description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID."
69
+
},
70
+
"byteSlice": {
71
+
"type": "object",
72
+
"required": [
73
+
"byteStart",
74
+
"byteEnd"
75
+
],
76
+
"properties": {
77
+
"byteEnd": {
78
+
"type": "integer",
79
+
"minimum": 0
80
+
},
81
+
"byteStart": {
82
+
"type": "integer",
83
+
"minimum": 0
84
+
}
85
+
},
86
+
"description": "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets."
87
+
}
88
+
}
89
+
}
+192
lexicons/com/atproto/label/defs.json
+192
lexicons/com/atproto/label/defs.json
···
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
+
}
+55
lexicons/com/atproto/moderation/defs.json
+55
lexicons/com/atproto/moderation/defs.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "com.atproto.moderation.defs",
4
+
"defs": {
5
+
"reasonRude": {
6
+
"type": "token",
7
+
"description": "Rude, harassing, explicit, or otherwise unwelcoming behavior"
8
+
},
9
+
"reasonSpam": {
10
+
"type": "token",
11
+
"description": "Spam: frequent unwanted promotion, replies, mentions"
12
+
},
13
+
"reasonType": {
14
+
"type": "string",
15
+
"knownValues": [
16
+
"com.atproto.moderation.defs#reasonSpam",
17
+
"com.atproto.moderation.defs#reasonViolation",
18
+
"com.atproto.moderation.defs#reasonMisleading",
19
+
"com.atproto.moderation.defs#reasonSexual",
20
+
"com.atproto.moderation.defs#reasonRude",
21
+
"com.atproto.moderation.defs#reasonOther",
22
+
"com.atproto.moderation.defs#reasonAppeal"
23
+
]
24
+
},
25
+
"reasonOther": {
26
+
"type": "token",
27
+
"description": "Other: reports not falling under another report category"
28
+
},
29
+
"subjectType": {
30
+
"type": "string",
31
+
"description": "Tag describing a type of subject that might be reported.",
32
+
"knownValues": [
33
+
"account",
34
+
"record",
35
+
"chat"
36
+
]
37
+
},
38
+
"reasonAppeal": {
39
+
"type": "token",
40
+
"description": "Appeal: appeal a previously taken moderation action"
41
+
},
42
+
"reasonSexual": {
43
+
"type": "token",
44
+
"description": "Unwanted or mislabeled sexual content"
45
+
},
46
+
"reasonViolation": {
47
+
"type": "token",
48
+
"description": "Direct violation of server rules, laws, terms of service"
49
+
},
50
+
"reasonMisleading": {
51
+
"type": "token",
52
+
"description": "Misleading identity, affiliation, or content"
53
+
}
54
+
}
55
+
}
+24
lexicons/com/atproto/repo/strongRef.json
+24
lexicons/com/atproto/repo/strongRef.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "com.atproto.repo.strongRef",
4
+
"description": "A URI with a content-hash fingerprint.",
5
+
"defs": {
6
+
"main": {
7
+
"type": "object",
8
+
"required": [
9
+
"uri",
10
+
"cid"
11
+
],
12
+
"properties": {
13
+
"cid": {
14
+
"type": "string",
15
+
"format": "cid"
16
+
},
17
+
"uri": {
18
+
"type": "string",
19
+
"format": "at-uri"
20
+
}
21
+
}
22
+
}
23
+
}
24
+
}
+71
lexicons/sh/tangled/actor/profile.json
+71
lexicons/sh/tangled/actor/profile.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.actor.profile",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"description": "A declaration of a Tangled account profile.",
8
+
"key": "literal:self",
9
+
"record": {
10
+
"type": "object",
11
+
"required": [
12
+
"bluesky"
13
+
],
14
+
"properties": {
15
+
"description": {
16
+
"type": "string",
17
+
"description": "Free-form profile description text.",
18
+
"maxGraphemes": 256,
19
+
"maxLength": 2560
20
+
},
21
+
"links": {
22
+
"type": "array",
23
+
"minLength": 0,
24
+
"maxLength": 5,
25
+
"items": {
26
+
"type": "string",
27
+
"description": "Any URI, intended for social profiles or websites, can be used to link DIDs/AT-URIs too."
28
+
}
29
+
},
30
+
"stats": {
31
+
"type": "array",
32
+
"minLength": 0,
33
+
"maxLength": 2,
34
+
"items": {
35
+
"type": "string",
36
+
"description": "Vanity stats.",
37
+
"enum": [
38
+
"merged-pull-request-count",
39
+
"closed-pull-request-count",
40
+
"open-pull-request-count",
41
+
"open-issue-count",
42
+
"closed-issue-count",
43
+
"repository-count"
44
+
]
45
+
}
46
+
},
47
+
"bluesky": {
48
+
"type": "boolean",
49
+
"description": "Include link to this account on Bluesky."
50
+
},
51
+
"location": {
52
+
"type": "string",
53
+
"description": "Free-form location text.",
54
+
"maxGraphemes": 40,
55
+
"maxLength": 400
56
+
},
57
+
"pinnedRepositories": {
58
+
"type": "array",
59
+
"description": "Any ATURI, it is up to appviews to validate these fields.",
60
+
"minLength": 0,
61
+
"maxLength": 6,
62
+
"items": {
63
+
"type": "string",
64
+
"format": "at-uri"
65
+
}
66
+
}
67
+
}
68
+
}
69
+
}
70
+
}
71
+
}
+27
lexicons/sh/tangled/graph/follow.json
+27
lexicons/sh/tangled/graph/follow.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.graph.follow",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"subject",
12
+
"createdAt"
13
+
],
14
+
"properties": {
15
+
"subject": {
16
+
"type": "string",
17
+
"format": "did"
18
+
},
19
+
"createdAt": {
20
+
"type": "string",
21
+
"format": "datetime"
22
+
}
23
+
}
24
+
}
25
+
}
26
+
}
27
+
}
+317
-696
lib/api.dart
+317
-696
lib/api.dart
···
1
1
import 'dart:convert';
2
2
import 'dart:io';
3
3
4
-
import 'package:at_uri/at_uri.dart';
5
4
import 'package:grain/app_logger.dart';
6
-
import 'package:grain/dpop_client.dart';
7
5
import 'package:grain/main.dart';
8
6
import 'package:grain/models/session.dart';
9
-
import 'package:grain/photo_manip.dart';
10
7
import 'package:http/http.dart' as http;
11
8
import 'package:mime/mime.dart';
12
9
···
14
11
import 'models/followers_result.dart';
15
12
import 'models/follows_result.dart';
16
13
import 'models/gallery.dart';
17
-
import 'models/gallery_item.dart';
18
14
import 'models/gallery_photo.dart';
19
15
import 'models/gallery_thread.dart';
20
16
import 'models/notification.dart' as grain;
17
+
import 'models/procedures/procedures.dart';
21
18
import 'models/profile.dart';
22
19
23
20
class ApiService {
···
27
24
28
25
String get _apiUrl => AppConfig.apiUrl;
29
26
30
-
Future<Session?> fetchSession([String? initialToken]) async {
31
-
String? token = initialToken;
32
-
if (token == null) {
33
-
final session = await auth.getValidSession();
34
-
token = session?.token;
35
-
if (token == null) return null;
27
+
Future<Session?> refreshSession(Session session) async {
28
+
final url = Uri.parse('$_apiUrl/api/token/refresh');
29
+
final headers = {'Content-Type': 'application/json'};
30
+
try {
31
+
final response = await http.post(
32
+
url,
33
+
headers: headers,
34
+
body: jsonEncode({'refreshToken': session.refreshToken}),
35
+
);
36
+
if (response.statusCode == 200) {
37
+
appLogger.i('Session refreshed successfully');
38
+
return Session.fromJson(jsonDecode(response.body));
39
+
} else {
40
+
appLogger.w('Failed to refresh session: ${response.statusCode} ${response.body}');
41
+
return null;
42
+
}
43
+
} catch (e) {
44
+
appLogger.e('Error refreshing session: $e');
45
+
return null;
36
46
}
37
-
38
-
final response = await http.get(
39
-
Uri.parse('$_apiUrl/oauth/session'),
40
-
headers: {'Authorization': 'Bearer $token', 'Content-Type': 'application/json'},
41
-
);
42
-
43
-
if (response.statusCode != 200) {
44
-
throw Exception('Failed to fetch session');
45
-
}
46
-
47
-
return Session.fromJson(jsonDecode(response.body));
48
47
}
49
48
50
-
Future<bool> revokeSession() async {
51
-
final session = await auth.getValidSession();
52
-
final token = session?.token;
53
-
if (token == null) {
54
-
appLogger.w('No access token for revokeSession');
55
-
return false;
56
-
}
57
-
final url = Uri.parse('$_apiUrl/oauth/revoke');
58
-
final headers = {'Authorization': 'Bearer $token', 'Content-Type': 'application/json'};
49
+
Future<bool> revokeSession(Session session) async {
50
+
final url = Uri.parse('$_apiUrl/api/token/revoke');
51
+
final headers = {'Content-Type': 'application/json'};
59
52
try {
60
-
final response = await http.post(url, headers: headers);
53
+
final response = await http.post(
54
+
url,
55
+
headers: headers,
56
+
body: jsonEncode({'refreshToken': session.refreshToken}),
57
+
);
61
58
if (response.statusCode == 200) {
62
59
appLogger.i('Session revoked successfully');
63
60
return true;
···
74
71
Future<Profile?> fetchCurrentUser() async {
75
72
final session = await auth.getValidSession();
76
73
77
-
if (session == null || session.session.subject.isEmpty) {
74
+
if (session == null || session.did.isEmpty) {
78
75
return null;
79
76
}
80
77
81
-
final user = await fetchProfile(did: session.session.subject);
78
+
final user = await fetchProfile(did: session.did);
82
79
83
80
currentUser = user;
84
81
···
289
286
return (json['items'] as List<dynamic>?)?.map((item) => Gallery.fromJson(item)).toList() ?? [];
290
287
}
291
288
292
-
Future<String?> createGallery({
293
-
required String title,
294
-
required String description,
295
-
List<Map<String, dynamic>>? facets,
289
+
/// Fetch followers for a given actor DID
290
+
Future<FollowersResult> getFollowers({
291
+
required String actor,
292
+
String? cursor,
293
+
int limit = 50,
296
294
}) async {
297
-
final session = await auth.getValidSession();
298
-
if (session == null) {
299
-
appLogger.w('No valid session for createGallery');
300
-
return null;
301
-
}
302
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
303
-
final issuer = session.session.issuer;
304
-
final did = session.session.subject;
305
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
306
-
final record = {
307
-
'collection': 'social.grain.gallery',
308
-
'repo': did,
309
-
'record': {
310
-
'title': title,
311
-
'description': description,
312
-
if (facets != null) 'facets': facets,
313
-
'updatedAt': DateTime.now().toUtc().toIso8601String(),
314
-
'createdAt': DateTime.now().toUtc().toIso8601String(),
315
-
},
316
-
};
317
-
appLogger.i('Creating gallery: $record');
318
-
final response = await dpopClient.send(
319
-
method: 'POST',
320
-
url: url,
321
-
accessToken: session.session.accessToken,
322
-
headers: {'Content-Type': 'application/json'},
323
-
body: jsonEncode(record),
295
+
final uri = Uri.parse(
296
+
'$_apiUrl/xrpc/social.grain.graph.getFollowers?actor=$actor&limit=$limit${cursor != null ? '&cursor=$cursor' : ''}',
324
297
);
325
-
if (response.statusCode != 200 && response.statusCode != 201) {
326
-
appLogger.w('Failed to create gallery: \\${response.statusCode} \\${response.body}');
327
-
throw Exception('Failed to create gallery: \\${response.statusCode}');
298
+
final response = await http.get(uri, headers: {'Content-Type': 'application/json'});
299
+
if (response.statusCode != 200) {
300
+
throw Exception('Failed to fetch followers: \\${response.statusCode} \\${response.body}');
328
301
}
329
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
330
-
appLogger.i('Created gallery result: $result');
331
-
final uri = result['uri'] as String?;
332
-
return uri;
302
+
final json = jsonDecode(response.body);
303
+
return FollowersResult.fromJson(json);
333
304
}
334
305
335
-
/// Polls the gallery until the number of items matches [expectedCount] or timeout.
336
-
/// Returns the Gallery if successful, or null if timeout.
337
-
Future<Gallery?> pollGalleryItems({
338
-
required String galleryUri,
339
-
required int expectedCount,
340
-
Duration pollDelay = const Duration(seconds: 2),
341
-
int maxAttempts = 20,
342
-
}) async {
343
-
int attempts = 0;
344
-
Gallery? gallery;
345
-
while (attempts < maxAttempts) {
346
-
gallery = await getGallery(uri: galleryUri);
347
-
if (gallery != null && gallery.items.length == expectedCount) {
348
-
appLogger.i('Gallery $galleryUri has expected number of items: $expectedCount');
349
-
return gallery;
350
-
}
351
-
await Future.delayed(pollDelay);
352
-
attempts++;
353
-
}
354
-
appLogger.w(
355
-
'Gallery $galleryUri did not reach expected items count ($expectedCount) after polling.',
306
+
/// Fetch follows for a given actor DID
307
+
Future<FollowsResult> getFollows({required String actor, String? cursor, int limit = 50}) async {
308
+
final uri = Uri.parse(
309
+
'$_apiUrl/xrpc/social.grain.graph.getFollows?actor=$actor&limit=$limit${cursor != null ? '&cursor=$cursor' : ''}',
356
310
);
357
-
return null;
311
+
final response = await http.get(uri, headers: {'Content-Type': 'application/json'});
312
+
if (response.statusCode != 200) {
313
+
throw Exception('Failed to fetch follows: \\${response.statusCode} \\${response.body}');
314
+
}
315
+
final json = jsonDecode(response.body);
316
+
return FollowsResult.fromJson(json);
358
317
}
359
318
360
-
/// Polls the gallery thread until the number of comments matches [expectedCount] or timeout.
361
-
/// Returns the thread map if successful, or null if timeout.
362
-
Future<GalleryThread?> pollGalleryThreadComments({
363
-
required String galleryUri,
364
-
required int expectedCount,
365
-
Duration pollDelay = const Duration(seconds: 2),
366
-
int maxAttempts = 20,
367
-
}) async {
368
-
int attempts = 0;
369
-
GalleryThread? thread;
370
-
while (attempts < maxAttempts) {
371
-
thread = await getGalleryThread(uri: galleryUri);
372
-
if (thread != null && thread.comments.length == expectedCount) {
373
-
appLogger.i('Gallery thread $galleryUri has expected number of comments: $expectedCount');
374
-
return thread;
375
-
}
376
-
await Future.delayed(pollDelay);
377
-
attempts++;
319
+
// Procedures
320
+
321
+
Future<UpdateProfileResponse> updateProfile({required UpdateProfileRequest request}) async {
322
+
final session = await auth.getValidSession();
323
+
final token = session?.token;
324
+
if (token == null) {
325
+
throw Exception('No access token for updateProfile');
378
326
}
379
-
appLogger.w(
380
-
'Gallery thread $galleryUri did not reach expected comments count ($expectedCount) after polling.',
327
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.actor.updateProfile');
328
+
final response = await http.post(
329
+
uri,
330
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
331
+
body: jsonEncode(request.toJson()),
381
332
);
382
-
return null;
333
+
if (response.statusCode != 200) {
334
+
throw Exception('Failed to update profile: ${response.statusCode} ${response.body}');
335
+
}
336
+
final json = jsonDecode(response.body);
337
+
return UpdateProfileResponse.fromJson(json);
383
338
}
384
339
385
-
/// Uploads a blob (file) to the atproto uploadBlob endpoint using DPoP authentication.
386
-
/// Returns the blob reference map on success, or null on failure.
387
-
Future<Map<String, dynamic>?> uploadBlob(File file) async {
340
+
Future<UpdateAvatarResponse> updateAvatar({required File avatarFile}) async {
388
341
final session = await auth.getValidSession();
389
-
if (session == null) {
390
-
appLogger.w('No valid session for uploadBlob');
391
-
return null;
342
+
final token = session?.token;
343
+
if (token == null) {
344
+
throw Exception('No access token for updateAvatar');
392
345
}
393
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
394
-
final issuer = session.session.issuer;
395
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.uploadBlob');
396
-
397
-
// Detect MIME type, fallback to application/octet-stream if unknown
398
-
String? mimeType = lookupMimeType(file.path);
346
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.actor.updateAvatar');
347
+
String? mimeType = lookupMimeType(avatarFile.path);
399
348
final contentType = mimeType ?? 'application/octet-stream';
400
-
401
-
appLogger.i('Uploading blob: ${file.path} (MIME: $mimeType)');
402
-
403
-
final bytes = await file.readAsBytes();
404
-
405
-
final response = await dpopClient.send(
406
-
method: 'POST',
407
-
url: url,
408
-
accessToken: session.session.accessToken,
409
-
headers: {'Content-Type': contentType},
349
+
final bytes = await avatarFile.readAsBytes();
350
+
final response = await http.post(
351
+
uri,
352
+
headers: {'Authorization': "Bearer $token", 'Content-Type': contentType},
410
353
body: bytes,
411
354
);
412
-
413
-
if (response.statusCode != 200 && response.statusCode != 201) {
414
-
appLogger.w(
415
-
'Failed to upload blob: \\${response.statusCode} \\${response.body} (File: \\${file.path}, MIME: \\${mimeType})',
416
-
);
417
-
return null;
355
+
if (response.statusCode != 200) {
356
+
throw Exception('Failed to update avatar: ${response.statusCode} ${response.body}');
418
357
}
419
-
420
-
try {
421
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
422
-
appLogger.i('Uploaded blob result: $result');
423
-
return result;
424
-
} catch (e, st) {
425
-
appLogger.e('Failed to parse uploadBlob response: $e', stackTrace: st);
426
-
return null;
427
-
}
358
+
final json = jsonDecode(response.body);
359
+
return UpdateAvatarResponse.fromJson(json);
428
360
}
429
361
430
-
Future<String?> createPhoto({
431
-
required Map<String, dynamic> blob,
432
-
required int width,
433
-
required int height,
434
-
String alt = '',
435
-
}) async {
362
+
Future<ApplySortResponse> applySort({required ApplySortRequest request}) async {
436
363
final session = await auth.getValidSession();
437
-
if (session == null) {
438
-
appLogger.w('No valid session for createPhotoRecord');
439
-
return null;
364
+
final token = session?.token;
365
+
if (token == null) {
366
+
throw Exception('No access token for applySort');
440
367
}
441
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
442
-
final issuer = session.session.issuer;
443
-
final did = session.session.subject;
444
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
445
-
final record = {
446
-
'collection': 'social.grain.photo',
447
-
'repo': did,
448
-
'record': {
449
-
'photo': blob['blob'],
450
-
'aspectRatio': {'width': width, 'height': height},
451
-
'alt': "",
452
-
'createdAt': DateTime.now().toUtc().toIso8601String(),
453
-
},
454
-
};
455
-
appLogger.i('Creating photo record: $record');
456
-
final response = await dpopClient.send(
457
-
method: 'POST',
458
-
url: url,
459
-
accessToken: session.session.accessToken,
460
-
headers: {'Content-Type': 'application/json'},
461
-
body: jsonEncode(record),
368
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.applySort');
369
+
final response = await http.post(
370
+
uri,
371
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
372
+
body: jsonEncode(request.toJson()),
462
373
);
463
-
if (response.statusCode != 200 && response.statusCode != 201) {
464
-
appLogger.w('Failed to create photo record: \\${response.statusCode} \\${response.body}');
465
-
return null;
374
+
if (response.statusCode != 200) {
375
+
throw Exception('Failed to apply sort: ${response.statusCode} ${response.body}');
466
376
}
467
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
468
-
appLogger.i('Created photo record result: $result');
469
-
return result['uri'] as String?;
377
+
final json = jsonDecode(response.body);
378
+
return ApplySortResponse.fromJson(json);
470
379
}
471
380
472
-
Future<String?> createGalleryItem({
473
-
required String galleryUri,
474
-
required String photoUri,
475
-
required int position,
476
-
}) async {
381
+
Future<ApplyAltsResponse> applyAlts({required ApplyAltsRequest request}) async {
477
382
final session = await auth.getValidSession();
478
-
if (session == null) {
479
-
appLogger.w('No valid session for createGalleryItem');
480
-
return null;
383
+
final token = session?.token;
384
+
if (token == null) {
385
+
throw Exception('No access token for applyAlts');
481
386
}
482
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
483
-
final issuer = session.session.issuer;
484
-
final did = session.session.subject;
485
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
486
-
final record = {
487
-
'collection': 'social.grain.gallery.item',
488
-
'repo': did,
489
-
'record': {
490
-
'gallery': galleryUri,
491
-
'item': photoUri,
492
-
'position': position,
493
-
'createdAt': DateTime.now().toUtc().toIso8601String(),
494
-
},
495
-
};
496
-
appLogger.i('Creating gallery item: $record');
497
-
final response = await dpopClient.send(
498
-
method: 'POST',
499
-
url: url,
500
-
accessToken: session.session.accessToken,
501
-
headers: {'Content-Type': 'application/json'},
502
-
body: jsonEncode(record),
387
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.photo.applyAlts');
388
+
final response = await http.post(
389
+
uri,
390
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
391
+
body: jsonEncode(request.toJson()),
503
392
);
504
-
if (response.statusCode != 200 && response.statusCode != 201) {
505
-
appLogger.w('Failed to create gallery item: \\${response.statusCode} \\${response.body}');
506
-
return null;
393
+
if (response.statusCode != 200) {
394
+
throw Exception('Failed to apply alts: ${response.statusCode} ${response.body}');
507
395
}
508
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
509
-
appLogger.i('Created gallery item result: $result');
510
-
return result['uri'] as String?;
396
+
final json = jsonDecode(response.body);
397
+
return ApplyAltsResponse.fromJson(json);
511
398
}
512
399
513
-
Future<String?> createComment({
514
-
required String text,
515
-
List<Map<String, dynamic>>? facets,
516
-
required String subject,
517
-
String? focus, // Now a String (photo URI)
518
-
String? replyTo,
519
-
}) async {
400
+
Future<CreateExifResponse> createExif({required CreateExifRequest request}) async {
520
401
final session = await auth.getValidSession();
521
-
if (session == null) {
522
-
appLogger.w('No valid session for createComment');
523
-
return null;
402
+
final token = session?.token;
403
+
if (token == null) {
404
+
throw Exception('No access token for createExif');
524
405
}
525
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
526
-
final issuer = session.session.issuer;
527
-
final did = session.session.subject;
528
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
529
-
final record = {
530
-
'collection': 'social.grain.comment',
531
-
'repo': did,
532
-
'record': {
533
-
'text': text,
534
-
if (facets != null) 'facets': facets,
535
-
'subject': subject,
536
-
if (focus != null) 'focus': focus, // focus is now a String
537
-
if (replyTo != null) 'replyTo': replyTo,
538
-
'createdAt': DateTime.now().toUtc().toIso8601String(),
539
-
},
540
-
};
541
-
appLogger.i('Creating comment: $record');
542
-
final response = await dpopClient.send(
543
-
method: 'POST',
544
-
url: url,
545
-
accessToken: session.session.accessToken,
546
-
headers: {'Content-Type': 'application/json'},
547
-
body: jsonEncode(record),
406
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.photo.createExif');
407
+
final response = await http.post(
408
+
uri,
409
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
410
+
body: jsonEncode(request.toJson()),
548
411
);
549
-
if (response.statusCode != 200 && response.statusCode != 201) {
550
-
appLogger.w('Failed to create comment: \\${response.statusCode} \\${response.body}');
551
-
return null;
412
+
if (response.statusCode != 200) {
413
+
throw Exception('Failed to create exif: ${response.statusCode} ${response.body}');
552
414
}
553
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
554
-
appLogger.i('Created comment result: $result');
555
-
return result['uri'] as String?;
415
+
final json = jsonDecode(response.body);
416
+
return CreateExifResponse.fromJson(json);
556
417
}
557
418
558
-
Future<String?> createFavorite({required String galleryUri}) async {
419
+
Future<CreateFollowResponse> createFollow({required CreateFollowRequest request}) async {
559
420
final session = await auth.getValidSession();
560
-
if (session == null) {
561
-
appLogger.w('No valid session for createFavorite');
562
-
return null;
421
+
final token = session?.token;
422
+
if (token == null) {
423
+
throw Exception('No access token for createFollow');
563
424
}
564
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
565
-
final issuer = session.session.issuer;
566
-
final did = session.session.subject;
567
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
568
-
final record = {
569
-
'collection': 'social.grain.favorite',
570
-
'repo': did,
571
-
'record': {'subject': galleryUri, 'createdAt': DateTime.now().toUtc().toIso8601String()},
572
-
};
573
-
appLogger.i('Creating favorite: $record');
574
-
final response = await dpopClient.send(
575
-
method: 'POST',
576
-
url: url,
577
-
accessToken: session.session.accessToken,
578
-
headers: {'Content-Type': 'application/json'},
579
-
body: jsonEncode(record),
425
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.graph.createFollow');
426
+
final response = await http.post(
427
+
uri,
428
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
429
+
body: jsonEncode(request.toJson()),
580
430
);
581
-
if (response.statusCode != 200 && response.statusCode != 201) {
582
-
appLogger.w('Failed to create favorite: \\${response.statusCode} \\${response.body}');
583
-
return null;
431
+
if (response.statusCode != 200) {
432
+
throw Exception('Failed to create follow: ${response.statusCode} ${response.body}');
584
433
}
585
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
586
-
appLogger.i('Created favorite result: $result');
587
-
return result['uri'] as String?;
434
+
final json = jsonDecode(response.body);
435
+
return CreateFollowResponse.fromJson(json);
588
436
}
589
437
590
-
Future<String?> createFollow({required String followeeDid}) async {
438
+
Future<DeleteFollowResponse> deleteFollow({required DeleteFollowRequest request}) async {
591
439
final session = await auth.getValidSession();
592
-
if (session == null) {
593
-
appLogger.w('No valid session for createFollow');
594
-
return null;
440
+
final token = session?.token;
441
+
if (token == null) {
442
+
throw Exception('No access token for deleteFollow');
595
443
}
596
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
597
-
final issuer = session.session.issuer;
598
-
final did = session.session.subject;
599
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
600
-
final record = {
601
-
'collection': 'social.grain.graph.follow',
602
-
'repo': did,
603
-
'record': {'subject': followeeDid, 'createdAt': DateTime.now().toUtc().toIso8601String()},
604
-
};
605
-
appLogger.i('Creating follow: $record');
606
-
final response = await dpopClient.send(
607
-
method: 'POST',
608
-
url: url,
609
-
accessToken: session.session.accessToken,
610
-
headers: {'Content-Type': 'application/json'},
611
-
body: jsonEncode(record),
444
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.graph.deleteFollow');
445
+
final response = await http.post(
446
+
uri,
447
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
448
+
body: jsonEncode(request.toJson()),
612
449
);
613
-
if (response.statusCode != 200 && response.statusCode != 201) {
614
-
appLogger.w('Failed to create follow: \\${response.statusCode} \\${response.body}');
615
-
return null;
450
+
if (response.statusCode != 200) {
451
+
throw Exception('Failed to delete follow: {response.statusCode} {response.body}');
616
452
}
617
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
618
-
appLogger.i('Created follow result: $result');
619
-
return result['uri'] as String?;
453
+
final json = jsonDecode(response.body);
454
+
return DeleteFollowResponse.fromJson(json);
620
455
}
621
456
622
-
/// Deletes a record by its URI using DPoP authentication.
623
-
/// Returns true on success, false on failure.
624
-
Future<bool> deleteRecord(String uri) async {
457
+
Future<DeletePhotoResponse> deletePhoto({required DeletePhotoRequest request}) async {
625
458
final session = await auth.getValidSession();
626
-
if (session == null) {
627
-
appLogger.w('No valid session for deleteRecord');
628
-
return false;
459
+
final token = session?.token;
460
+
if (token == null) {
461
+
throw Exception('No access token for deletePhoto');
629
462
}
630
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
631
-
final issuer = session.session.issuer;
632
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.deleteRecord');
633
-
final repo = session.session.subject;
634
-
if (repo.isEmpty) {
635
-
appLogger.w('No repo (DID) available from session for deleteRecord');
636
-
return false;
637
-
}
638
-
String? collection;
639
-
String? rkey;
640
-
try {
641
-
final atUri = AtUri.parse(uri);
642
-
collection = atUri.collection.toString();
643
-
rkey = atUri.rkey;
644
-
} catch (e) {
645
-
appLogger.w('Failed to parse collection from uri: $uri');
646
-
}
647
-
if (collection == null || collection.isEmpty) {
648
-
appLogger.w('No collection found in uri: $uri');
649
-
return false;
650
-
}
651
-
final payload = {'uri': uri, 'repo': repo, 'collection': collection, 'rkey': rkey};
652
-
appLogger.i('Deleting record: $payload');
653
-
final response = await dpopClient.send(
654
-
method: 'POST',
655
-
url: url,
656
-
accessToken: session.session.accessToken,
657
-
headers: {'Content-Type': 'application/json'},
658
-
body: jsonEncode(payload),
463
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.photo.deletePhoto');
464
+
final response = await http.post(
465
+
uri,
466
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
467
+
body: jsonEncode(request.toJson()),
659
468
);
660
-
if (response.statusCode != 200 && response.statusCode != 204) {
661
-
appLogger.w('Failed to delete record: \\${response.statusCode} \\${response.body}');
662
-
return false;
469
+
if (response.statusCode != 200) {
470
+
throw Exception('Failed to delete photo: ${response.statusCode} ${response.body}');
663
471
}
664
-
appLogger.i('Deleted record $uri');
665
-
return true;
472
+
final json = jsonDecode(response.body);
473
+
return DeletePhotoResponse.fromJson(json);
666
474
}
667
475
668
-
/// Updates the current user's profile (displayName, description, avatar).
669
-
/// If avatarFile is provided, uploads it as a blob and sets avatar.
670
-
/// Returns true on success, false on failure.
671
-
Future<bool> updateProfile({
672
-
required String displayName,
673
-
required String description,
674
-
File? avatarFile,
675
-
}) async {
476
+
Future<UploadPhotoResponse> uploadPhoto(File file) async {
676
477
final session = await auth.getValidSession();
677
478
if (session == null) {
678
-
appLogger.w('No valid session for updateProfile');
679
-
return false;
479
+
appLogger.w('No valid session for uploadPhoto');
480
+
throw Exception('No valid session for uploadPhoto');
680
481
}
681
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
682
-
final issuer = session.session.issuer;
683
-
final did = session.session.subject;
684
-
// Fetch the raw profile record from atproto getRecord endpoint
685
-
final getUrl = Uri.parse(
686
-
'$issuer/xrpc/com.atproto.repo.getRecord?repo=$did&collection=social.grain.actor.profile&rkey=self',
687
-
);
688
-
final getResp = await dpopClient.send(
689
-
method: 'GET',
690
-
url: getUrl,
691
-
accessToken: session.session.accessToken,
692
-
headers: {'Content-Type': 'application/json'},
482
+
final token = session.token;
483
+
final uri = Uri.parse('${AppConfig.apiUrl}/xrpc/social.grain.photo.uploadPhoto');
484
+
485
+
// Detect MIME type, fallback to application/octet-stream if unknown
486
+
String? mimeType = lookupMimeType(file.path);
487
+
final contentType = mimeType ?? 'application/octet-stream';
488
+
489
+
appLogger.i('Uploading photo: ${file.path} (MIME: $mimeType)');
490
+
final bytes = await file.readAsBytes();
491
+
492
+
final response = await http.post(
493
+
uri,
494
+
headers: {'Authorization': 'Bearer $token', 'Content-Type': contentType},
495
+
body: bytes,
693
496
);
694
-
if (getResp.statusCode != 200) {
497
+
498
+
if (response.statusCode != 200 && response.statusCode != 201) {
695
499
appLogger.w(
696
-
'Failed to fetch raw profile record for update: \\${getResp.statusCode} \\${getResp.body}',
500
+
'Failed to upload photo: ${response.statusCode} ${response.body} (File: ${file.path}, MIME: $mimeType)',
697
501
);
698
-
return false;
502
+
throw Exception('Failed to upload photo: ${response.statusCode} ${response.body}');
699
503
}
700
-
final recordJson = jsonDecode(getResp.body) as Map<String, dynamic>;
701
-
var avatar = recordJson['value']?['avatar'];
702
-
// If avatarFile is provided, upload it and set avatar
703
-
if (avatarFile != null) {
704
-
try {
705
-
// Resize avatar before upload using photo_manip
706
-
final resizeResult = await resizeImage(file: avatarFile);
707
-
final blobResult = await uploadBlob(resizeResult.file);
708
-
if (blobResult != null && blobResult['blob'] != null) {
709
-
avatar = blobResult['blob'];
710
-
}
711
-
} catch (e) {
712
-
appLogger.w('Failed to upload avatar: $e');
713
-
}
504
+
505
+
try {
506
+
final json = jsonDecode(response.body);
507
+
appLogger.i('Uploaded photo result: $json');
508
+
return UploadPhotoResponse.fromJson(json);
509
+
} catch (e, st) {
510
+
appLogger.e('Failed to parse createPhoto response: $e', stackTrace: st);
511
+
throw Exception('Failed to parse createPhoto response: $e');
714
512
}
715
-
// Update the profile record
716
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.putRecord');
717
-
final record = {
718
-
'collection': 'social.grain.actor.profile',
719
-
'repo': did,
720
-
'rkey': 'self',
721
-
'record': {'displayName': displayName, 'description': description, 'avatar': avatar},
722
-
};
723
-
appLogger.i('Updating profile: $record');
724
-
final response = await dpopClient.send(
725
-
method: 'POST',
726
-
url: url,
727
-
accessToken: session.session.accessToken,
728
-
headers: {'Content-Type': 'application/json'},
729
-
body: jsonEncode(record),
730
-
);
731
-
if (response.statusCode != 200 && response.statusCode != 201) {
732
-
appLogger.w('Failed to update profile: \\${response.statusCode} \\${response.body}');
733
-
return false;
734
-
}
735
-
appLogger.i('Profile updated successfully');
736
-
return true;
737
513
}
738
514
739
-
/// Fetch followers for a given actor DID
740
-
Future<FollowersResult> getFollowers({
741
-
required String actor,
742
-
String? cursor,
743
-
int limit = 50,
515
+
Future<DeleteGalleryItemResponse> deleteGalleryItem({
516
+
required DeleteGalleryItemRequest request,
744
517
}) async {
745
-
final uri = Uri.parse(
746
-
'$_apiUrl/xrpc/social.grain.graph.getFollowers?actor=$actor&limit=$limit${cursor != null ? '&cursor=$cursor' : ''}',
518
+
final session = await auth.getValidSession();
519
+
final token = session?.token;
520
+
if (token == null) {
521
+
throw Exception('No access token for deleteGalleryItem');
522
+
}
523
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.deleteItem');
524
+
final response = await http.post(
525
+
uri,
526
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
527
+
body: jsonEncode(request.toJson()),
747
528
);
748
-
final response = await http.get(uri, headers: {'Content-Type': 'application/json'});
749
529
if (response.statusCode != 200) {
750
-
throw Exception('Failed to fetch followers: \\${response.statusCode} \\${response.body}');
530
+
throw Exception('Failed to delete gallery item: ${response.statusCode} ${response.body}');
751
531
}
752
532
final json = jsonDecode(response.body);
753
-
return FollowersResult.fromJson(json);
533
+
return DeleteGalleryItemResponse.fromJson(json);
754
534
}
755
535
756
-
/// Fetch follows for a given actor DID
757
-
Future<FollowsResult> getFollows({required String actor, String? cursor, int limit = 50}) async {
758
-
final uri = Uri.parse(
759
-
'$_apiUrl/xrpc/social.grain.graph.getFollows?actor=$actor&limit=$limit${cursor != null ? '&cursor=$cursor' : ''}',
536
+
Future<CreateGalleryItemResponse> createGalleryItem({
537
+
required CreateGalleryItemRequest request,
538
+
}) async {
539
+
final session = await auth.getValidSession();
540
+
final token = session?.token;
541
+
if (token == null) {
542
+
throw Exception('No access token for createGalleryItem');
543
+
}
544
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.createItem');
545
+
final response = await http.post(
546
+
uri,
547
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
548
+
body: jsonEncode(request.toJson()),
760
549
);
761
-
final response = await http.get(uri, headers: {'Content-Type': 'application/json'});
762
550
if (response.statusCode != 200) {
763
-
throw Exception('Failed to fetch follows: \\${response.statusCode} \\${response.body}');
551
+
throw Exception('Failed to create gallery item: ${response.statusCode} ${response.body}');
764
552
}
765
553
final json = jsonDecode(response.body);
766
-
return FollowsResult.fromJson(json);
554
+
return CreateGalleryItemResponse.fromJson(json);
767
555
}
768
556
769
-
/// Updates the sort order of gallery items using com.atproto.repo.applyWrites
770
-
/// [galleryUri]: The URI of the gallery (at://did/social.grain.gallery/rkey)
771
-
/// [sortedItemUris]: List of item URIs in the desired order
772
-
/// [itemsMeta]: List of GalleryItem meta objects (must include gallery, item, createdAt, uri)
773
-
/// Returns true on success, false on failure
774
-
Future<bool> updateGallerySortOrder({
775
-
required String galleryUri,
776
-
required List<GalleryItem> orderedItems,
777
-
}) async {
557
+
Future<UpdateGalleryResponse> updateGallery({required UpdateGalleryRequest request}) async {
778
558
final session = await auth.getValidSession();
779
-
if (session == null) {
780
-
appLogger.w('No valid session for updateGallerySortOrder');
781
-
return false;
559
+
final token = session?.token;
560
+
if (token == null) {
561
+
throw Exception('No access token for updateGallery');
782
562
}
783
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
784
-
final issuer = session.session.issuer;
785
-
final did = session.session.subject;
786
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.applyWrites');
787
-
788
-
final updates = <Map<String, dynamic>>[];
789
-
int position = 0;
790
-
for (final item in orderedItems) {
791
-
String rkey = '';
792
-
try {
793
-
rkey = AtUri.parse(item.uri).rkey;
794
-
} catch (_) {}
795
-
updates.add({
796
-
'\$type': 'com.atproto.repo.applyWrites#update',
797
-
'collection': 'social.grain.gallery.item',
798
-
'rkey': rkey,
799
-
'value': {
800
-
'gallery': item.gallery,
801
-
'item': item.item,
802
-
'createdAt': item.createdAt,
803
-
'position': position,
804
-
},
805
-
});
806
-
position++;
807
-
}
808
-
if (updates.isEmpty) {
809
-
appLogger.w('No updates to apply for gallery sort order');
810
-
return false;
811
-
}
812
-
final payload = {'repo': did, 'validate': false, 'writes': updates};
813
-
appLogger.i('Applying gallery sort order updates: $payload');
814
-
final response = await dpopClient.send(
815
-
method: 'POST',
816
-
url: url,
817
-
accessToken: session.session.accessToken,
818
-
headers: {'Content-Type': 'application/json'},
819
-
body: jsonEncode(payload),
563
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.updateGallery');
564
+
final response = await http.post(
565
+
uri,
566
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
567
+
body: jsonEncode(request.toJson()),
820
568
);
821
-
if (response.statusCode != 200 && response.statusCode != 201) {
822
-
appLogger.w(
823
-
'Failed to apply gallery sort order: \\${response.statusCode} \\${response.body}',
824
-
);
825
-
return false;
569
+
if (response.statusCode != 200) {
570
+
throw Exception('Failed to update gallery: ${response.statusCode} ${response.body}');
826
571
}
827
-
appLogger.i('Gallery sort order updated successfully');
828
-
return true;
572
+
final json = jsonDecode(response.body);
573
+
return UpdateGalleryResponse.fromJson(json);
829
574
}
830
575
831
-
/// Updates a gallery's title and description.
832
-
/// Returns true on success, false on failure.
833
-
Future<bool> updateGallery({
834
-
required String galleryUri,
835
-
required String title,
836
-
required String description,
837
-
required String createdAt,
838
-
List<Map<String, dynamic>>? facets,
839
-
}) async {
576
+
Future<DeleteGalleryResponse> deleteGallery({required DeleteGalleryRequest request}) async {
840
577
final session = await auth.getValidSession();
841
-
if (session == null) {
842
-
appLogger.w('No valid session for updateGallery');
843
-
return false;
578
+
final token = session?.token;
579
+
if (token == null) {
580
+
throw Exception('No access token for deleteGallery');
844
581
}
845
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
846
-
final issuer = session.session.issuer;
847
-
final did = session.session.subject;
848
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.putRecord');
849
-
// Extract rkey from galleryUri
850
-
String rkey = '';
851
-
try {
852
-
rkey = AtUri.parse(galleryUri).rkey;
853
-
} catch (_) {}
854
-
if (rkey.isEmpty) {
855
-
appLogger.w('No rkey found in galleryUri: $galleryUri');
856
-
return false;
857
-
}
858
-
final record = {
859
-
'collection': 'social.grain.gallery',
860
-
'repo': did,
861
-
'rkey': rkey,
862
-
'record': {
863
-
'title': title,
864
-
'description': description,
865
-
if (facets != null) 'facets': facets,
866
-
'updatedAt': DateTime.now().toUtc().toIso8601String(),
867
-
'createdAt': createdAt,
868
-
},
869
-
};
870
-
appLogger.i('Updating gallery: $record');
871
-
final response = await dpopClient.send(
872
-
method: 'POST',
873
-
url: url,
874
-
accessToken: session.session.accessToken,
875
-
headers: {'Content-Type': 'application/json'},
876
-
body: jsonEncode(record),
582
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.deleteGallery');
583
+
final response = await http.post(
584
+
uri,
585
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
586
+
body: jsonEncode(request.toJson()),
877
587
);
878
-
if (response.statusCode != 200 && response.statusCode != 201) {
879
-
appLogger.w('Failed to update gallery: ${response.statusCode} ${response.body}');
880
-
return false;
588
+
if (response.statusCode != 200) {
589
+
throw Exception('Failed to delete gallery: ${response.statusCode} ${response.body}');
881
590
}
882
-
appLogger.i('Gallery updated successfully');
883
-
return true;
591
+
final json = jsonDecode(response.body);
592
+
return DeleteGalleryResponse.fromJson(json);
884
593
}
885
594
886
-
/// Creates a photo EXIF record in the social.grain.photo.exif collection.
887
-
/// Returns the record URI on success, or null on failure.
888
-
Future<String?> createPhotoExif({
889
-
required String photo,
890
-
String? createdAt,
891
-
String? dateTimeOriginal,
892
-
int? exposureTime,
893
-
int? fNumber,
894
-
String? flash,
895
-
int? focalLengthIn35mmFormat,
896
-
int? iSO,
897
-
String? lensMake,
898
-
String? lensModel,
899
-
String? make,
900
-
String? model,
901
-
}) async {
595
+
Future<CreateGalleryResponse> createGallery({required CreateGalleryRequest request}) async {
902
596
final session = await auth.getValidSession();
903
-
if (session == null) {
904
-
appLogger.w('No valid session for createPhotoExif');
905
-
return null;
597
+
final token = session?.token;
598
+
if (token == null) {
599
+
throw Exception('No access token for createGallery');
906
600
}
907
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
908
-
final issuer = session.session.issuer;
909
-
final did = session.session.subject;
910
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.createRecord');
911
-
final record = {
912
-
'collection': 'social.grain.photo.exif',
913
-
'repo': did,
914
-
'record': {
915
-
'photo': photo,
916
-
'createdAt': createdAt ?? DateTime.now().toUtc().toIso8601String(),
917
-
if (dateTimeOriginal != null) 'dateTimeOriginal': dateTimeOriginal,
918
-
if (exposureTime != null) 'exposureTime': exposureTime,
919
-
if (fNumber != null) 'fNumber': fNumber,
920
-
if (flash != null) 'flash': flash,
921
-
if (focalLengthIn35mmFormat != null) 'focalLengthIn35mmFormat': focalLengthIn35mmFormat,
922
-
if (iSO != null) 'iSO': iSO,
923
-
if (lensMake != null) 'lensMake': lensMake,
924
-
if (lensModel != null) 'lensModel': lensModel,
925
-
if (make != null) 'make': make,
926
-
if (model != null) 'model': model,
927
-
},
928
-
};
929
-
appLogger.i('Creating photo exif record: $record');
930
-
final response = await dpopClient.send(
931
-
method: 'POST',
932
-
url: url,
933
-
accessToken: session.session.accessToken,
934
-
headers: {'Content-Type': 'application/json'},
935
-
body: jsonEncode(record),
601
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.gallery.createGallery');
602
+
final response = await http.post(
603
+
uri,
604
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
605
+
body: jsonEncode(request.toJson()),
936
606
);
937
-
if (response.statusCode != 200 && response.statusCode != 201) {
938
-
appLogger.w(
939
-
'Failed to create photo exif record: \\${response.statusCode} \\${response.body}',
940
-
);
941
-
return null;
607
+
if (response.statusCode != 200) {
608
+
throw Exception('Failed to create gallery: ${response.statusCode} ${response.body}');
942
609
}
943
-
final result = jsonDecode(response.body) as Map<String, dynamic>;
944
-
appLogger.i('Created photo exif record result: $result');
945
-
return result['uri'] as String?;
610
+
final json = jsonDecode(response.body);
611
+
return CreateGalleryResponse.fromJson(json);
946
612
}
947
613
948
-
/// Updates multiple photo records in the social.grain.photo collection using applyWrites.
949
-
/// Each photo in [updates] should have: photoUri, photo, aspectRatio, alt, createdAt
950
-
/// Returns true on success, false on failure.
951
-
Future<bool> updatePhotos(List<Map<String, dynamic>> updates) async {
614
+
Future<DeleteFavoriteResponse> deleteFavorite({required DeleteFavoriteRequest request}) async {
952
615
final session = await auth.getValidSession();
953
-
if (session == null) {
954
-
appLogger.w('No valid session for updatePhotosBatch');
955
-
return false;
616
+
final token = session?.token;
617
+
if (token == null) {
618
+
throw Exception('No access token for deleteFavorite');
956
619
}
957
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
958
-
final issuer = session.session.issuer;
959
-
final did = session.session.subject;
960
-
final url = Uri.parse('$issuer/xrpc/com.atproto.repo.applyWrites');
620
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.favorite.deleteFavorite');
621
+
final response = await http.post(
622
+
uri,
623
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
624
+
body: jsonEncode(request.toJson()),
625
+
);
626
+
if (response.statusCode != 200) {
627
+
throw Exception('Failed to delete favorite: ${response.statusCode} ${response.body}');
628
+
}
629
+
final json = jsonDecode(response.body);
630
+
return DeleteFavoriteResponse.fromJson(json);
631
+
}
961
632
962
-
// Fetch current photo records for all photos
963
-
final photoRecords = await fetchPhotoRecords();
964
-
965
-
final writes = <Map<String, dynamic>>[];
966
-
for (final update in updates) {
967
-
String rkey = '';
968
-
try {
969
-
rkey = AtUri.parse(update['photoUri'] as String).rkey;
970
-
} catch (_) {}
971
-
if (rkey.isEmpty) {
972
-
appLogger.w('No rkey found in photoUri: ${update['photoUri']}');
973
-
continue;
974
-
}
975
-
976
-
// Get the full photo record for this photoUri
977
-
final record = photoRecords[update['photoUri']];
978
-
if (record == null) {
979
-
appLogger.w('No photo record found for photoUri: ${update['photoUri']}');
980
-
continue;
981
-
}
982
-
983
-
// Use provided values or fallback to the record's values
984
-
final photoBlobRef = update['photo'] ?? record['photo'];
985
-
final aspectRatio = update['aspectRatio'] ?? record['aspectRatio'];
986
-
final createdAt = update['createdAt'] ?? record['createdAt'];
987
-
988
-
if (photoBlobRef == null) {
989
-
appLogger.w('No blobRef found for photoUri: ${update['photoUri']}');
990
-
continue;
991
-
}
992
-
993
-
writes.add({
994
-
'\$type': 'com.atproto.repo.applyWrites#update',
995
-
'collection': 'social.grain.photo',
996
-
'rkey': rkey,
997
-
'value': {
998
-
'photo': photoBlobRef,
999
-
'aspectRatio': aspectRatio,
1000
-
'alt': update['alt'] ?? '',
1001
-
'createdAt': createdAt,
1002
-
},
1003
-
});
633
+
Future<CreateFavoriteResponse> createFavorite({required CreateFavoriteRequest request}) async {
634
+
final session = await auth.getValidSession();
635
+
final token = session?.token;
636
+
if (token == null) {
637
+
throw Exception('No access token for createFavorite');
1004
638
}
1005
-
if (writes.isEmpty) {
1006
-
appLogger.w('No valid photo updates to apply');
1007
-
return false;
1008
-
}
1009
-
final payload = {'repo': did, 'validate': false, 'writes': writes};
1010
-
appLogger.i('Applying batch photo updates: $payload');
1011
-
final response = await dpopClient.send(
1012
-
method: 'POST',
1013
-
url: url,
1014
-
accessToken: session.session.accessToken,
1015
-
headers: {'Content-Type': 'application/json'},
1016
-
body: jsonEncode(payload),
639
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.favorite.createFavorite');
640
+
final response = await http.post(
641
+
uri,
642
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
643
+
body: jsonEncode(request.toJson()),
1017
644
);
1018
-
if (response.statusCode != 200 && response.statusCode != 201) {
1019
-
appLogger.w('Failed to apply batch photo updates: ${response.statusCode} ${response.body}');
1020
-
return false;
645
+
if (response.statusCode != 200) {
646
+
throw Exception('Failed to create favorite: ${response.statusCode} ${response.body}');
1021
647
}
1022
-
appLogger.i('Batch photo updates applied successfully');
1023
-
return true;
648
+
final json = jsonDecode(response.body);
649
+
return CreateFavoriteResponse.fromJson(json);
1024
650
}
1025
651
1026
-
/// Fetches the full photo record for each photo in social.grain.photo.
1027
-
/// Returns a map of photoUri -> photo record (Map`<`String, dynamic`>`).
1028
-
Future<Map<String, dynamic>> fetchPhotoRecords() async {
652
+
Future<DeleteCommentResponse> deleteComment({required DeleteCommentRequest request}) async {
1029
653
final session = await auth.getValidSession();
1030
-
if (session == null) {
1031
-
appLogger.w('No valid session for fetchPhotoRecords');
1032
-
return {};
654
+
final token = session?.token;
655
+
if (token == null) {
656
+
throw Exception('No access token for deleteComment');
1033
657
}
1034
-
final dpopClient = DpopHttpClient(dpopKey: session.session.dpopJwk);
1035
-
final issuer = session.session.issuer;
1036
-
final did = session.session.subject;
1037
-
final url = Uri.parse(
1038
-
'$issuer/xrpc/com.atproto.repo.listRecords?repo=$did&collection=social.grain.photo',
658
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.comment.deleteComment');
659
+
final response = await http.post(
660
+
uri,
661
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
662
+
body: jsonEncode(request.toJson()),
1039
663
);
664
+
if (response.statusCode != 200) {
665
+
throw Exception('Failed to delete comment: ${response.statusCode} ${response.body}');
666
+
}
667
+
final json = jsonDecode(response.body);
668
+
return DeleteCommentResponse.fromJson(json);
669
+
}
1040
670
1041
-
final response = await dpopClient.send(
1042
-
method: 'GET',
1043
-
url: url,
1044
-
accessToken: session.session.accessToken,
1045
-
headers: {'Content-Type': 'application/json'},
671
+
Future<CreateCommentResponse> createComment({required CreateCommentRequest request}) async {
672
+
final session = await auth.getValidSession();
673
+
final token = session?.token;
674
+
if (token == null) {
675
+
throw Exception('No access token for createComment');
676
+
}
677
+
final uri = Uri.parse('$_apiUrl/xrpc/social.grain.comment.createComment');
678
+
final response = await http.post(
679
+
uri,
680
+
headers: {'Authorization': "Bearer $token", 'Content-Type': 'application/json'},
681
+
body: jsonEncode(request.toJson()),
1046
682
);
1047
-
1048
683
if (response.statusCode != 200) {
1049
-
appLogger.w('Failed to list photo records: ${response.statusCode} ${response.body}');
1050
-
return {};
684
+
throw Exception('Failed to create comment: ${response.statusCode} ${response.body}');
1051
685
}
1052
-
1053
-
final json = jsonDecode(response.body) as Map<String, dynamic>;
1054
-
final records = json['records'] as List<dynamic>? ?? [];
1055
-
final photoRecords = <String, dynamic>{};
1056
-
1057
-
for (final record in records) {
1058
-
final uri = record['uri'] as String?;
1059
-
final value = record['value'] as Map<String, dynamic>?;
1060
-
if (uri != null && value != null) {
1061
-
photoRecords[uri] = value;
1062
-
}
1063
-
}
1064
-
return photoRecords;
686
+
final json = jsonDecode(response.body);
687
+
return CreateCommentResponse.fromJson(json);
1065
688
}
1066
689
1067
-
/// Notifies the server that the requesting account has seen notifications.
1068
-
/// Sends a POST request with the current ISO timestamp as seenAt.
1069
690
Future<bool> updateSeen() async {
1070
691
final session = await auth.getValidSession();
1071
692
final token = session?.token;
+76
-30
lib/auth.dart
+76
-30
lib/auth.dart
···
5
5
import 'package:grain/api.dart';
6
6
import 'package:grain/app_logger.dart';
7
7
import 'package:grain/main.dart';
8
-
import 'package:grain/models/atproto_session.dart';
9
8
import 'package:grain/models/session.dart';
10
9
11
10
class Auth {
···
14
13
15
14
Future<bool> hasToken() async {
16
15
final session = await _loadSession();
17
-
return session != null && session.token.isNotEmpty && !isSessionExpired(session.session);
16
+
return session != null && session.token.isNotEmpty && !isSessionExpired(session);
18
17
}
19
18
20
19
Future<void> login(String handle) async {
21
20
final apiUrl = AppConfig.apiUrl;
22
-
final redirectedUrl = await FlutterWebAuth2.authenticate(
23
-
url: '$apiUrl/oauth/login?client=native&handle=${Uri.encodeComponent(handle)}',
24
-
callbackUrlScheme: 'grainflutter',
25
-
);
26
-
final uri = Uri.parse(redirectedUrl);
27
-
final token = uri.queryParameters['token'];
21
+
String? token;
22
+
String? refreshToken;
23
+
String? expiresAtStr;
24
+
String? did;
25
+
26
+
try {
27
+
final redirectUrl = await FlutterWebAuth2.authenticate(
28
+
url: '$apiUrl/oauth/login?client=native&handle=${Uri.encodeComponent(handle)}',
29
+
callbackUrlScheme: 'grainflutter',
30
+
);
31
+
32
+
appLogger.i('Redirected URL: $redirectUrl');
33
+
34
+
final uri = Uri.parse(redirectUrl);
35
+
token = uri.queryParameters['token'];
36
+
refreshToken = uri.queryParameters['refreshToken'];
37
+
expiresAtStr = uri.queryParameters['expiresAt'];
38
+
did = uri.queryParameters['did'];
39
+
} catch (e) {
40
+
appLogger.e('Error during authentication: $e');
41
+
throw Exception('Authentication failed');
42
+
}
28
43
29
-
appLogger.i('Redirected URL: $redirectedUrl');
30
44
appLogger.i('User signed in with handle: $handle');
31
45
32
-
final session = await apiService.fetchSession(token);
33
-
if (session == null) {
34
-
throw Exception('Failed to fetch session after login');
46
+
if (token == null || token.isEmpty) {
47
+
throw Exception('No token found in redirect URL');
48
+
}
49
+
if (refreshToken == null || refreshToken.isEmpty) {
50
+
throw Exception('No refreshToken found in redirect URL');
51
+
}
52
+
if (expiresAtStr == null || expiresAtStr.isEmpty) {
53
+
throw Exception('No expiresAt found in redirect URL');
54
+
}
55
+
if (did == null || did.isEmpty) {
56
+
throw Exception('No did found in redirect URL');
57
+
}
58
+
59
+
DateTime expiresAt;
60
+
try {
61
+
expiresAt = DateTime.parse(expiresAtStr);
62
+
} catch (e) {
63
+
throw Exception('Invalid expiresAt format');
35
64
}
65
+
66
+
final session = Session(
67
+
token: token,
68
+
refreshToken: refreshToken,
69
+
expiresAt: expiresAt,
70
+
did: did,
71
+
);
36
72
await _saveSession(session);
37
73
}
38
74
39
75
Future<void> _saveSession(Session session) async {
40
-
final atprotoSessionJson = jsonEncode(session.session.toJson());
41
-
await _storage.write(key: 'atproto_session', value: atprotoSessionJson);
42
-
await _storage.write(key: 'api_token', value: session.token);
76
+
final sessionJson = jsonEncode(session.toJson());
77
+
await _storage.write(key: 'session', value: sessionJson);
43
78
}
44
79
45
80
Future<Session?> _loadSession() async {
46
-
final sessionJsonString = await _storage.read(key: 'atproto_session');
47
-
final token = await _storage.read(key: 'api_token');
48
-
if (sessionJsonString == null || token == null) return null;
81
+
final sessionJsonString = await _storage.read(key: 'session');
82
+
if (sessionJsonString == null) return null;
49
83
50
84
try {
51
85
final sessionJson = jsonDecode(sessionJsonString);
52
-
return Session(session: AtprotoSession.fromJson(sessionJson), token: token);
86
+
return Session.fromJson(sessionJson);
53
87
} catch (e) {
54
88
// Optionally log or clear storage if corrupted
55
89
return null;
56
90
}
57
91
}
58
92
59
-
bool isSessionExpired(
60
-
AtprotoSession session, {
61
-
Duration tolerance = const Duration(seconds: 30),
62
-
}) {
93
+
bool isSessionExpired(Session session, {Duration tolerance = const Duration(seconds: 30)}) {
63
94
final now = DateTime.now().toUtc();
64
95
return session.expiresAt.subtract(tolerance).isBefore(now);
65
96
}
···
70
101
// No session at all, do not attempt refresh
71
102
return null;
72
103
}
73
-
if (isSessionExpired(session.session)) {
104
+
if (isSessionExpired(session)) {
74
105
appLogger.w('Session is expired, attempting refresh');
75
106
try {
76
-
final refreshed = await apiService.fetchSession();
77
-
if (refreshed != null && !isSessionExpired(refreshed.session)) {
107
+
final refreshed = await apiService.refreshSession(session);
108
+
if (refreshed != null && !isSessionExpired(refreshed)) {
78
109
await _saveSession(refreshed);
79
110
appLogger.i('Session refreshed and saved');
80
111
return refreshed;
···
93
124
}
94
125
95
126
Future<void> clearSession() async {
96
-
// Revoke session on the server
97
-
await apiService.revokeSession();
98
127
// Remove session from secure storage
99
-
await _storage.delete(key: 'atproto_session');
100
-
await _storage.delete(key: 'api_token');
128
+
await _storage.delete(key: 'session');
129
+
}
130
+
131
+
Future<void> logout() async {
132
+
final session = await _loadSession();
133
+
134
+
appLogger.i('Logging out user with session: $session');
135
+
101
136
// Clear any in-memory session/user data
102
137
apiService.currentUser = null;
138
+
139
+
if (session == null) {
140
+
appLogger.w('No session to revoke');
141
+
return;
142
+
}
143
+
144
+
await apiService.revokeSession(session);
145
+
146
+
await clearSession();
147
+
148
+
appLogger.i('User logged out and session cleared');
103
149
}
104
150
}
105
151
-153
lib/dpop_client.dart
-153
lib/dpop_client.dart
···
1
-
import 'dart:convert';
2
-
3
-
import 'package:crypto/crypto.dart';
4
-
import 'package:http/http.dart' as http;
5
-
import 'package:jose/jose.dart';
6
-
import 'package:uuid/uuid.dart';
7
-
8
-
class DpopHttpClient {
9
-
final JsonWebKey dpopKey;
10
-
final Map<String, String> _nonces = {}; // origin -> nonce
11
-
12
-
DpopHttpClient({required this.dpopKey});
13
-
14
-
/// Extract origin (scheme + host + port) from a URL
15
-
String _extractOrigin(String url) {
16
-
final uri = Uri.parse(url);
17
-
final portPart = (uri.hasPort && uri.port != 80 && uri.port != 443) ? ':${uri.port}' : '';
18
-
return '${uri.scheme}://${uri.host}$portPart';
19
-
}
20
-
21
-
/// Strip query and fragment from URL per spec
22
-
String _buildHtu(String url) {
23
-
final uri = Uri.parse(url);
24
-
return '${uri.scheme}://${uri.host}${uri.path}';
25
-
}
26
-
27
-
/// Calculate ath claim: base64url(sha256(access_token))
28
-
String _calculateAth(String accessToken) {
29
-
final hash = sha256.convert(utf8.encode(accessToken));
30
-
return base64Url.encode(hash.bytes).replaceAll('=', '');
31
-
}
32
-
33
-
/// Calculate the JWK Thumbprint for EC or RSA keys per RFC 7638.
34
-
/// The input [jwk] is the public part of your key as a Map`<String, dynamic>`.
35
-
///
36
-
/// For EC keys, required fields are: crv, kty, x, y
37
-
/// For RSA keys, required fields are: e, kty, n
38
-
String calculateJwkThumbprint(Map<String, dynamic> jwk) {
39
-
late Map<String, String> ordered;
40
-
41
-
if (jwk['kty'] == 'EC') {
42
-
ordered = {'crv': jwk['crv'], 'kty': jwk['kty'], 'x': jwk['x'], 'y': jwk['y']};
43
-
} else if (jwk['kty'] == 'RSA') {
44
-
ordered = {'e': jwk['e'], 'kty': jwk['kty'], 'n': jwk['n']};
45
-
} else {
46
-
throw ArgumentError('Unsupported key type for thumbprint calculation');
47
-
}
48
-
49
-
final jsonString = jsonEncode(ordered);
50
-
51
-
final digest = sha256.convert(utf8.encode(jsonString));
52
-
return base64Url.encode(digest.bytes).replaceAll('=', '');
53
-
}
54
-
55
-
/// Build the DPoP JWT proof
56
-
Future<String> _buildProof({
57
-
required String htm,
58
-
required String htu,
59
-
String? nonce,
60
-
String? ath,
61
-
}) async {
62
-
final now = (DateTime.now().millisecondsSinceEpoch / 1000).floor();
63
-
final jti = Uuid().v4();
64
-
65
-
final publicJwk = Map<String, String>.from(dpopKey.toJson())..remove('d');
66
-
67
-
final payload = {
68
-
'htu': htu,
69
-
'htm': htm,
70
-
'iat': now,
71
-
'jti': jti,
72
-
if (nonce != null) 'nonce': nonce,
73
-
if (ath != null) 'ath': ath,
74
-
};
75
-
76
-
final builder = JsonWebSignatureBuilder()
77
-
..jsonContent = payload
78
-
..addRecipient(dpopKey, algorithm: dpopKey.algorithm)
79
-
..setProtectedHeader('typ', 'dpop+jwt')
80
-
..setProtectedHeader('jwk', publicJwk);
81
-
82
-
final jws = builder.build();
83
-
return jws.toCompactSerialization();
84
-
}
85
-
86
-
/// Public method to send requests with DPoP proof, retries once on use_dpop_nonce error
87
-
Future<http.Response> send({
88
-
required String method,
89
-
required Uri url,
90
-
required String accessToken,
91
-
Map<String, String>? headers,
92
-
Object? body,
93
-
}) async {
94
-
final origin = _extractOrigin(url.toString());
95
-
final nonce = _nonces[origin];
96
-
97
-
final htu = _buildHtu(url.toString());
98
-
final ath = _calculateAth(accessToken);
99
-
100
-
final proof = await _buildProof(htm: method.toUpperCase(), htu: htu, nonce: nonce, ath: ath);
101
-
102
-
// Compose headers, allowing override of Content-Type for raw uploads
103
-
final requestHeaders = <String, String>{
104
-
'Authorization': 'DPoP $accessToken',
105
-
'DPoP': proof,
106
-
if (headers != null) ...headers,
107
-
};
108
-
109
-
http.Response response;
110
-
switch (method.toUpperCase()) {
111
-
case 'GET':
112
-
response = await http.get(url, headers: requestHeaders);
113
-
break;
114
-
case 'POST':
115
-
response = await http.post(url, headers: requestHeaders, body: body);
116
-
break;
117
-
case 'PUT':
118
-
response = await http.put(url, headers: requestHeaders, body: body);
119
-
break;
120
-
case 'DELETE':
121
-
response = await http.delete(url, headers: requestHeaders, body: body);
122
-
break;
123
-
default:
124
-
throw UnsupportedError('Unsupported HTTP method: $method');
125
-
}
126
-
127
-
final newNonce = response.headers['dpop-nonce'];
128
-
if (newNonce != null && newNonce != nonce) {
129
-
// Save new nonce for origin
130
-
_nonces[origin] = newNonce;
131
-
}
132
-
133
-
if (response.statusCode == 401) {
134
-
final wwwAuth = response.headers['www-authenticate'];
135
-
if (wwwAuth != null &&
136
-
wwwAuth.contains('DPoP') &&
137
-
wwwAuth.contains('error="use_dpop_nonce"') &&
138
-
newNonce != null &&
139
-
newNonce != nonce) {
140
-
// Retry once with updated nonce
141
-
return send(
142
-
method: method,
143
-
url: url,
144
-
accessToken: accessToken,
145
-
headers: headers,
146
-
body: body,
147
-
);
148
-
}
149
-
}
150
-
151
-
return response;
152
-
}
153
-
}
+1
-1
lib/main.dart
+1
-1
lib/main.dart
-19
lib/models/atproto_session.dart
-19
lib/models/atproto_session.dart
···
1
-
import 'package:freezed_annotation/freezed_annotation.dart';
2
-
import 'package:jose/jose.dart';
3
-
4
-
part 'atproto_session.freezed.dart';
5
-
part 'atproto_session.g.dart';
6
-
7
-
@freezed
8
-
class AtprotoSession with _$AtprotoSession {
9
-
const factory AtprotoSession({
10
-
required String accessToken,
11
-
required String tokenType,
12
-
required DateTime expiresAt,
13
-
required JsonWebKey dpopJwk,
14
-
required String issuer,
15
-
required String subject,
16
-
}) = _AtprotoSession;
17
-
18
-
factory AtprotoSession.fromJson(Map<String, dynamic> json) => _$AtprotoSessionFromJson(json);
19
-
}
-293
lib/models/atproto_session.freezed.dart
-293
lib/models/atproto_session.freezed.dart
···
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 'atproto_session.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
-
AtprotoSession _$AtprotoSessionFromJson(Map<String, dynamic> json) {
19
-
return _AtprotoSession.fromJson(json);
20
-
}
21
-
22
-
/// @nodoc
23
-
mixin _$AtprotoSession {
24
-
String get accessToken => throw _privateConstructorUsedError;
25
-
String get tokenType => throw _privateConstructorUsedError;
26
-
DateTime get expiresAt => throw _privateConstructorUsedError;
27
-
JsonWebKey get dpopJwk => throw _privateConstructorUsedError;
28
-
String get issuer => throw _privateConstructorUsedError;
29
-
String get subject => throw _privateConstructorUsedError;
30
-
31
-
/// Serializes this AtprotoSession to a JSON map.
32
-
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
33
-
34
-
/// Create a copy of AtprotoSession
35
-
/// with the given fields replaced by the non-null parameter values.
36
-
@JsonKey(includeFromJson: false, includeToJson: false)
37
-
$AtprotoSessionCopyWith<AtprotoSession> get copyWith =>
38
-
throw _privateConstructorUsedError;
39
-
}
40
-
41
-
/// @nodoc
42
-
abstract class $AtprotoSessionCopyWith<$Res> {
43
-
factory $AtprotoSessionCopyWith(
44
-
AtprotoSession value,
45
-
$Res Function(AtprotoSession) then,
46
-
) = _$AtprotoSessionCopyWithImpl<$Res, AtprotoSession>;
47
-
@useResult
48
-
$Res call({
49
-
String accessToken,
50
-
String tokenType,
51
-
DateTime expiresAt,
52
-
JsonWebKey dpopJwk,
53
-
String issuer,
54
-
String subject,
55
-
});
56
-
}
57
-
58
-
/// @nodoc
59
-
class _$AtprotoSessionCopyWithImpl<$Res, $Val extends AtprotoSession>
60
-
implements $AtprotoSessionCopyWith<$Res> {
61
-
_$AtprotoSessionCopyWithImpl(this._value, this._then);
62
-
63
-
// ignore: unused_field
64
-
final $Val _value;
65
-
// ignore: unused_field
66
-
final $Res Function($Val) _then;
67
-
68
-
/// Create a copy of AtprotoSession
69
-
/// with the given fields replaced by the non-null parameter values.
70
-
@pragma('vm:prefer-inline')
71
-
@override
72
-
$Res call({
73
-
Object? accessToken = null,
74
-
Object? tokenType = null,
75
-
Object? expiresAt = null,
76
-
Object? dpopJwk = null,
77
-
Object? issuer = null,
78
-
Object? subject = null,
79
-
}) {
80
-
return _then(
81
-
_value.copyWith(
82
-
accessToken: null == accessToken
83
-
? _value.accessToken
84
-
: accessToken // ignore: cast_nullable_to_non_nullable
85
-
as String,
86
-
tokenType: null == tokenType
87
-
? _value.tokenType
88
-
: tokenType // ignore: cast_nullable_to_non_nullable
89
-
as String,
90
-
expiresAt: null == expiresAt
91
-
? _value.expiresAt
92
-
: expiresAt // ignore: cast_nullable_to_non_nullable
93
-
as DateTime,
94
-
dpopJwk: null == dpopJwk
95
-
? _value.dpopJwk
96
-
: dpopJwk // ignore: cast_nullable_to_non_nullable
97
-
as JsonWebKey,
98
-
issuer: null == issuer
99
-
? _value.issuer
100
-
: issuer // ignore: cast_nullable_to_non_nullable
101
-
as String,
102
-
subject: null == subject
103
-
? _value.subject
104
-
: subject // ignore: cast_nullable_to_non_nullable
105
-
as String,
106
-
)
107
-
as $Val,
108
-
);
109
-
}
110
-
}
111
-
112
-
/// @nodoc
113
-
abstract class _$$AtprotoSessionImplCopyWith<$Res>
114
-
implements $AtprotoSessionCopyWith<$Res> {
115
-
factory _$$AtprotoSessionImplCopyWith(
116
-
_$AtprotoSessionImpl value,
117
-
$Res Function(_$AtprotoSessionImpl) then,
118
-
) = __$$AtprotoSessionImplCopyWithImpl<$Res>;
119
-
@override
120
-
@useResult
121
-
$Res call({
122
-
String accessToken,
123
-
String tokenType,
124
-
DateTime expiresAt,
125
-
JsonWebKey dpopJwk,
126
-
String issuer,
127
-
String subject,
128
-
});
129
-
}
130
-
131
-
/// @nodoc
132
-
class __$$AtprotoSessionImplCopyWithImpl<$Res>
133
-
extends _$AtprotoSessionCopyWithImpl<$Res, _$AtprotoSessionImpl>
134
-
implements _$$AtprotoSessionImplCopyWith<$Res> {
135
-
__$$AtprotoSessionImplCopyWithImpl(
136
-
_$AtprotoSessionImpl _value,
137
-
$Res Function(_$AtprotoSessionImpl) _then,
138
-
) : super(_value, _then);
139
-
140
-
/// Create a copy of AtprotoSession
141
-
/// with the given fields replaced by the non-null parameter values.
142
-
@pragma('vm:prefer-inline')
143
-
@override
144
-
$Res call({
145
-
Object? accessToken = null,
146
-
Object? tokenType = null,
147
-
Object? expiresAt = null,
148
-
Object? dpopJwk = null,
149
-
Object? issuer = null,
150
-
Object? subject = null,
151
-
}) {
152
-
return _then(
153
-
_$AtprotoSessionImpl(
154
-
accessToken: null == accessToken
155
-
? _value.accessToken
156
-
: accessToken // ignore: cast_nullable_to_non_nullable
157
-
as String,
158
-
tokenType: null == tokenType
159
-
? _value.tokenType
160
-
: tokenType // ignore: cast_nullable_to_non_nullable
161
-
as String,
162
-
expiresAt: null == expiresAt
163
-
? _value.expiresAt
164
-
: expiresAt // ignore: cast_nullable_to_non_nullable
165
-
as DateTime,
166
-
dpopJwk: null == dpopJwk
167
-
? _value.dpopJwk
168
-
: dpopJwk // ignore: cast_nullable_to_non_nullable
169
-
as JsonWebKey,
170
-
issuer: null == issuer
171
-
? _value.issuer
172
-
: issuer // ignore: cast_nullable_to_non_nullable
173
-
as String,
174
-
subject: null == subject
175
-
? _value.subject
176
-
: subject // ignore: cast_nullable_to_non_nullable
177
-
as String,
178
-
),
179
-
);
180
-
}
181
-
}
182
-
183
-
/// @nodoc
184
-
@JsonSerializable()
185
-
class _$AtprotoSessionImpl implements _AtprotoSession {
186
-
const _$AtprotoSessionImpl({
187
-
required this.accessToken,
188
-
required this.tokenType,
189
-
required this.expiresAt,
190
-
required this.dpopJwk,
191
-
required this.issuer,
192
-
required this.subject,
193
-
});
194
-
195
-
factory _$AtprotoSessionImpl.fromJson(Map<String, dynamic> json) =>
196
-
_$$AtprotoSessionImplFromJson(json);
197
-
198
-
@override
199
-
final String accessToken;
200
-
@override
201
-
final String tokenType;
202
-
@override
203
-
final DateTime expiresAt;
204
-
@override
205
-
final JsonWebKey dpopJwk;
206
-
@override
207
-
final String issuer;
208
-
@override
209
-
final String subject;
210
-
211
-
@override
212
-
String toString() {
213
-
return 'AtprotoSession(accessToken: $accessToken, tokenType: $tokenType, expiresAt: $expiresAt, dpopJwk: $dpopJwk, issuer: $issuer, subject: $subject)';
214
-
}
215
-
216
-
@override
217
-
bool operator ==(Object other) {
218
-
return identical(this, other) ||
219
-
(other.runtimeType == runtimeType &&
220
-
other is _$AtprotoSessionImpl &&
221
-
(identical(other.accessToken, accessToken) ||
222
-
other.accessToken == accessToken) &&
223
-
(identical(other.tokenType, tokenType) ||
224
-
other.tokenType == tokenType) &&
225
-
(identical(other.expiresAt, expiresAt) ||
226
-
other.expiresAt == expiresAt) &&
227
-
(identical(other.dpopJwk, dpopJwk) || other.dpopJwk == dpopJwk) &&
228
-
(identical(other.issuer, issuer) || other.issuer == issuer) &&
229
-
(identical(other.subject, subject) || other.subject == subject));
230
-
}
231
-
232
-
@JsonKey(includeFromJson: false, includeToJson: false)
233
-
@override
234
-
int get hashCode => Object.hash(
235
-
runtimeType,
236
-
accessToken,
237
-
tokenType,
238
-
expiresAt,
239
-
dpopJwk,
240
-
issuer,
241
-
subject,
242
-
);
243
-
244
-
/// Create a copy of AtprotoSession
245
-
/// with the given fields replaced by the non-null parameter values.
246
-
@JsonKey(includeFromJson: false, includeToJson: false)
247
-
@override
248
-
@pragma('vm:prefer-inline')
249
-
_$$AtprotoSessionImplCopyWith<_$AtprotoSessionImpl> get copyWith =>
250
-
__$$AtprotoSessionImplCopyWithImpl<_$AtprotoSessionImpl>(
251
-
this,
252
-
_$identity,
253
-
);
254
-
255
-
@override
256
-
Map<String, dynamic> toJson() {
257
-
return _$$AtprotoSessionImplToJson(this);
258
-
}
259
-
}
260
-
261
-
abstract class _AtprotoSession implements AtprotoSession {
262
-
const factory _AtprotoSession({
263
-
required final String accessToken,
264
-
required final String tokenType,
265
-
required final DateTime expiresAt,
266
-
required final JsonWebKey dpopJwk,
267
-
required final String issuer,
268
-
required final String subject,
269
-
}) = _$AtprotoSessionImpl;
270
-
271
-
factory _AtprotoSession.fromJson(Map<String, dynamic> json) =
272
-
_$AtprotoSessionImpl.fromJson;
273
-
274
-
@override
275
-
String get accessToken;
276
-
@override
277
-
String get tokenType;
278
-
@override
279
-
DateTime get expiresAt;
280
-
@override
281
-
JsonWebKey get dpopJwk;
282
-
@override
283
-
String get issuer;
284
-
@override
285
-
String get subject;
286
-
287
-
/// Create a copy of AtprotoSession
288
-
/// with the given fields replaced by the non-null parameter values.
289
-
@override
290
-
@JsonKey(includeFromJson: false, includeToJson: false)
291
-
_$$AtprotoSessionImplCopyWith<_$AtprotoSessionImpl> get copyWith =>
292
-
throw _privateConstructorUsedError;
293
-
}
-28
lib/models/atproto_session.g.dart
-28
lib/models/atproto_session.g.dart
···
1
-
// GENERATED CODE - DO NOT MODIFY BY HAND
2
-
3
-
part of 'atproto_session.dart';
4
-
5
-
// **************************************************************************
6
-
// JsonSerializableGenerator
7
-
// **************************************************************************
8
-
9
-
_$AtprotoSessionImpl _$$AtprotoSessionImplFromJson(Map<String, dynamic> json) =>
10
-
_$AtprotoSessionImpl(
11
-
accessToken: json['accessToken'] as String,
12
-
tokenType: json['tokenType'] as String,
13
-
expiresAt: DateTime.parse(json['expiresAt'] as String),
14
-
dpopJwk: JsonWebKey.fromJson(json['dpopJwk'] as Map<String, dynamic>),
15
-
issuer: json['issuer'] as String,
16
-
subject: json['subject'] as String,
17
-
);
18
-
19
-
Map<String, dynamic> _$$AtprotoSessionImplToJson(
20
-
_$AtprotoSessionImpl instance,
21
-
) => <String, dynamic>{
22
-
'accessToken': instance.accessToken,
23
-
'tokenType': instance.tokenType,
24
-
'expiresAt': instance.expiresAt.toIso8601String(),
25
-
'dpopJwk': instance.dpopJwk,
26
-
'issuer': instance.issuer,
27
-
'subject': instance.subject,
28
-
};
+1
lib/models/photo_exif.dart
+1
lib/models/photo_exif.dart
+31
-3
lib/models/photo_exif.freezed.dart
+31
-3
lib/models/photo_exif.freezed.dart
···
36
36
String? get lensModel => throw _privateConstructorUsedError;
37
37
String? get make => throw _privateConstructorUsedError;
38
38
String? get model => throw _privateConstructorUsedError;
39
+
Map<String, dynamic>? get record => throw _privateConstructorUsedError;
39
40
40
41
/// Serializes this PhotoExif to a JSON map.
41
42
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
···
67
68
String? lensModel,
68
69
String? make,
69
70
String? model,
71
+
Map<String, dynamic>? record,
70
72
});
71
73
}
72
74
···
99
101
Object? lensModel = freezed,
100
102
Object? make = freezed,
101
103
Object? model = freezed,
104
+
Object? record = freezed,
102
105
}) {
103
106
return _then(
104
107
_value.copyWith(
···
158
161
? _value.model
159
162
: model // ignore: cast_nullable_to_non_nullable
160
163
as String?,
164
+
record: freezed == record
165
+
? _value.record
166
+
: record // ignore: cast_nullable_to_non_nullable
167
+
as Map<String, dynamic>?,
161
168
)
162
169
as $Val,
163
170
);
···
188
195
String? lensModel,
189
196
String? make,
190
197
String? model,
198
+
Map<String, dynamic>? record,
191
199
});
192
200
}
193
201
···
219
227
Object? lensModel = freezed,
220
228
Object? make = freezed,
221
229
Object? model = freezed,
230
+
Object? record = freezed,
222
231
}) {
223
232
return _then(
224
233
_$PhotoExifImpl(
···
278
287
? _value.model
279
288
: model // ignore: cast_nullable_to_non_nullable
280
289
as String?,
290
+
record: freezed == record
291
+
? _value._record
292
+
: record // ignore: cast_nullable_to_non_nullable
293
+
as Map<String, dynamic>?,
281
294
),
282
295
);
283
296
}
···
301
314
this.lensModel,
302
315
this.make,
303
316
this.model,
304
-
});
317
+
final Map<String, dynamic>? record,
318
+
}) : _record = record;
305
319
306
320
factory _$PhotoExifImpl.fromJson(Map<String, dynamic> json) =>
307
321
_$$PhotoExifImplFromJson(json);
···
339
353
final String? make;
340
354
@override
341
355
final String? model;
356
+
final Map<String, dynamic>? _record;
357
+
@override
358
+
Map<String, dynamic>? get record {
359
+
final value = _record;
360
+
if (value == null) return null;
361
+
if (_record is EqualUnmodifiableMapView) return _record;
362
+
// ignore: implicit_dynamic_type
363
+
return EqualUnmodifiableMapView(value);
364
+
}
342
365
343
366
@override
344
367
String toString() {
345
-
return 'PhotoExif(photo: $photo, createdAt: $createdAt, uri: $uri, cid: $cid, dateTimeOriginal: $dateTimeOriginal, exposureTime: $exposureTime, fNumber: $fNumber, flash: $flash, focalLengthIn35mmFormat: $focalLengthIn35mmFormat, iSO: $iSO, lensMake: $lensMake, lensModel: $lensModel, make: $make, model: $model)';
368
+
return 'PhotoExif(photo: $photo, createdAt: $createdAt, uri: $uri, cid: $cid, dateTimeOriginal: $dateTimeOriginal, exposureTime: $exposureTime, fNumber: $fNumber, flash: $flash, focalLengthIn35mmFormat: $focalLengthIn35mmFormat, iSO: $iSO, lensMake: $lensMake, lensModel: $lensModel, make: $make, model: $model, record: $record)';
346
369
}
347
370
348
371
@override
···
372
395
(identical(other.lensModel, lensModel) ||
373
396
other.lensModel == lensModel) &&
374
397
(identical(other.make, make) || other.make == make) &&
375
-
(identical(other.model, model) || other.model == model));
398
+
(identical(other.model, model) || other.model == model) &&
399
+
const DeepCollectionEquality().equals(other._record, _record));
376
400
}
377
401
378
402
@JsonKey(includeFromJson: false, includeToJson: false)
···
393
417
lensModel,
394
418
make,
395
419
model,
420
+
const DeepCollectionEquality().hash(_record),
396
421
);
397
422
398
423
/// Create a copy of PhotoExif
···
425
450
final String? lensModel,
426
451
final String? make,
427
452
final String? model,
453
+
final Map<String, dynamic>? record,
428
454
}) = _$PhotoExifImpl;
429
455
430
456
factory _PhotoExif.fromJson(Map<String, dynamic> json) =
···
458
484
String? get make;
459
485
@override
460
486
String? get model;
487
+
@override
488
+
Map<String, dynamic>? get record;
461
489
462
490
/// Create a copy of PhotoExif
463
491
/// with the given fields replaced by the non-null parameter values.
+2
lib/models/photo_exif.g.dart
+2
lib/models/photo_exif.g.dart
···
22
22
lensModel: json['lensModel'] as String?,
23
23
make: json['make'] as String?,
24
24
model: json['model'] as String?,
25
+
record: json['record'] as Map<String, dynamic>?,
25
26
);
26
27
27
28
Map<String, dynamic> _$$PhotoExifImplToJson(_$PhotoExifImpl instance) =>
···
40
41
'lensModel': instance.lensModel,
41
42
'make': instance.make,
42
43
'model': instance.model,
44
+
'record': instance.record,
43
45
};
+15
lib/models/procedures/apply_alts_request.dart
+15
lib/models/procedures/apply_alts_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
import 'apply_alts_update.dart';
4
+
5
+
part 'apply_alts_request.freezed.dart';
6
+
part 'apply_alts_request.g.dart';
7
+
8
+
/// Request to apply alt texts to photos in a gallery.
9
+
/// Requires auth.
10
+
@freezed
11
+
class ApplyAltsRequest with _$ApplyAltsRequest {
12
+
const factory ApplyAltsRequest({required List<ApplyAltsUpdate> writes}) = _ApplyAltsRequest;
13
+
14
+
factory ApplyAltsRequest.fromJson(Map<String, dynamic> json) => _$ApplyAltsRequestFromJson(json);
15
+
}
+179
lib/models/procedures/apply_alts_request.freezed.dart
+179
lib/models/procedures/apply_alts_request.freezed.dart
···
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_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
+
ApplyAltsRequest _$ApplyAltsRequestFromJson(Map<String, dynamic> json) {
19
+
return _ApplyAltsRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$ApplyAltsRequest {
24
+
List<ApplyAltsUpdate> get writes => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this ApplyAltsRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of ApplyAltsRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$ApplyAltsRequestCopyWith<ApplyAltsRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $ApplyAltsRequestCopyWith<$Res> {
38
+
factory $ApplyAltsRequestCopyWith(
39
+
ApplyAltsRequest value,
40
+
$Res Function(ApplyAltsRequest) then,
41
+
) = _$ApplyAltsRequestCopyWithImpl<$Res, ApplyAltsRequest>;
42
+
@useResult
43
+
$Res call({List<ApplyAltsUpdate> writes});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$ApplyAltsRequestCopyWithImpl<$Res, $Val extends ApplyAltsRequest>
48
+
implements $ApplyAltsRequestCopyWith<$Res> {
49
+
_$ApplyAltsRequestCopyWithImpl(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 ApplyAltsRequest
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? writes = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
writes: null == writes
64
+
? _value.writes
65
+
: writes // ignore: cast_nullable_to_non_nullable
66
+
as List<ApplyAltsUpdate>,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$ApplyAltsRequestImplCopyWith<$Res>
75
+
implements $ApplyAltsRequestCopyWith<$Res> {
76
+
factory _$$ApplyAltsRequestImplCopyWith(
77
+
_$ApplyAltsRequestImpl value,
78
+
$Res Function(_$ApplyAltsRequestImpl) then,
79
+
) = __$$ApplyAltsRequestImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({List<ApplyAltsUpdate> writes});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$ApplyAltsRequestImplCopyWithImpl<$Res>
87
+
extends _$ApplyAltsRequestCopyWithImpl<$Res, _$ApplyAltsRequestImpl>
88
+
implements _$$ApplyAltsRequestImplCopyWith<$Res> {
89
+
__$$ApplyAltsRequestImplCopyWithImpl(
90
+
_$ApplyAltsRequestImpl _value,
91
+
$Res Function(_$ApplyAltsRequestImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of ApplyAltsRequest
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? writes = null}) {
99
+
return _then(
100
+
_$ApplyAltsRequestImpl(
101
+
writes: null == writes
102
+
? _value._writes
103
+
: writes // ignore: cast_nullable_to_non_nullable
104
+
as List<ApplyAltsUpdate>,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$ApplyAltsRequestImpl implements _ApplyAltsRequest {
113
+
const _$ApplyAltsRequestImpl({required final List<ApplyAltsUpdate> writes})
114
+
: _writes = writes;
115
+
116
+
factory _$ApplyAltsRequestImpl.fromJson(Map<String, dynamic> json) =>
117
+
_$$ApplyAltsRequestImplFromJson(json);
118
+
119
+
final List<ApplyAltsUpdate> _writes;
120
+
@override
121
+
List<ApplyAltsUpdate> get writes {
122
+
if (_writes is EqualUnmodifiableListView) return _writes;
123
+
// ignore: implicit_dynamic_type
124
+
return EqualUnmodifiableListView(_writes);
125
+
}
126
+
127
+
@override
128
+
String toString() {
129
+
return 'ApplyAltsRequest(writes: $writes)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$ApplyAltsRequestImpl &&
137
+
const DeepCollectionEquality().equals(other._writes, _writes));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode =>
143
+
Object.hash(runtimeType, const DeepCollectionEquality().hash(_writes));
144
+
145
+
/// Create a copy of ApplyAltsRequest
146
+
/// with the given fields replaced by the non-null parameter values.
147
+
@JsonKey(includeFromJson: false, includeToJson: false)
148
+
@override
149
+
@pragma('vm:prefer-inline')
150
+
_$$ApplyAltsRequestImplCopyWith<_$ApplyAltsRequestImpl> get copyWith =>
151
+
__$$ApplyAltsRequestImplCopyWithImpl<_$ApplyAltsRequestImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$ApplyAltsRequestImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _ApplyAltsRequest implements ApplyAltsRequest {
163
+
const factory _ApplyAltsRequest({
164
+
required final List<ApplyAltsUpdate> writes,
165
+
}) = _$ApplyAltsRequestImpl;
166
+
167
+
factory _ApplyAltsRequest.fromJson(Map<String, dynamic> json) =
168
+
_$ApplyAltsRequestImpl.fromJson;
169
+
170
+
@override
171
+
List<ApplyAltsUpdate> get writes;
172
+
173
+
/// Create a copy of ApplyAltsRequest
174
+
/// with the given fields replaced by the non-null parameter values.
175
+
@override
176
+
@JsonKey(includeFromJson: false, includeToJson: false)
177
+
_$$ApplyAltsRequestImplCopyWith<_$ApplyAltsRequestImpl> get copyWith =>
178
+
throw _privateConstructorUsedError;
179
+
}
+19
lib/models/procedures/apply_alts_request.g.dart
+19
lib/models/procedures/apply_alts_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'apply_alts_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$ApplyAltsRequestImpl _$$ApplyAltsRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$ApplyAltsRequestImpl(
12
+
writes: (json['writes'] as List<dynamic>)
13
+
.map((e) => ApplyAltsUpdate.fromJson(e as Map<String, dynamic>))
14
+
.toList(),
15
+
);
16
+
17
+
Map<String, dynamic> _$$ApplyAltsRequestImplToJson(
18
+
_$ApplyAltsRequestImpl instance,
19
+
) => <String, dynamic>{'writes': instance.writes};
+14
lib/models/procedures/apply_alts_response.dart
+14
lib/models/procedures/apply_alts_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'apply_alts_response.freezed.dart';
4
+
part 'apply_alts_response.g.dart';
5
+
6
+
/// Response for applyAlts API.
7
+
/// True if the writes were successfully applied.
8
+
@freezed
9
+
class ApplyAltsResponse with _$ApplyAltsResponse {
10
+
const factory ApplyAltsResponse({required bool success}) = _ApplyAltsResponse;
11
+
12
+
factory ApplyAltsResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$ApplyAltsResponseFromJson(json);
14
+
}
+171
lib/models/procedures/apply_alts_response.freezed.dart
+171
lib/models/procedures/apply_alts_response.freezed.dart
···
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
+15
lib/models/procedures/apply_alts_response.g.dart
···
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
+13
lib/models/procedures/apply_alts_update.dart
···
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
+
}
+188
lib/models/procedures/apply_alts_update.freezed.dart
+188
lib/models/procedures/apply_alts_update.freezed.dart
···
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_update.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
+
ApplyAltsUpdate _$ApplyAltsUpdateFromJson(Map<String, dynamic> json) {
19
+
return _ApplyAltsUpdate.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$ApplyAltsUpdate {
24
+
String get photoUri => throw _privateConstructorUsedError;
25
+
String get alt => throw _privateConstructorUsedError;
26
+
27
+
/// Serializes this ApplyAltsUpdate to a JSON map.
28
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
29
+
30
+
/// Create a copy of ApplyAltsUpdate
31
+
/// with the given fields replaced by the non-null parameter values.
32
+
@JsonKey(includeFromJson: false, includeToJson: false)
33
+
$ApplyAltsUpdateCopyWith<ApplyAltsUpdate> get copyWith =>
34
+
throw _privateConstructorUsedError;
35
+
}
36
+
37
+
/// @nodoc
38
+
abstract class $ApplyAltsUpdateCopyWith<$Res> {
39
+
factory $ApplyAltsUpdateCopyWith(
40
+
ApplyAltsUpdate value,
41
+
$Res Function(ApplyAltsUpdate) then,
42
+
) = _$ApplyAltsUpdateCopyWithImpl<$Res, ApplyAltsUpdate>;
43
+
@useResult
44
+
$Res call({String photoUri, String alt});
45
+
}
46
+
47
+
/// @nodoc
48
+
class _$ApplyAltsUpdateCopyWithImpl<$Res, $Val extends ApplyAltsUpdate>
49
+
implements $ApplyAltsUpdateCopyWith<$Res> {
50
+
_$ApplyAltsUpdateCopyWithImpl(this._value, this._then);
51
+
52
+
// ignore: unused_field
53
+
final $Val _value;
54
+
// ignore: unused_field
55
+
final $Res Function($Val) _then;
56
+
57
+
/// Create a copy of ApplyAltsUpdate
58
+
/// with the given fields replaced by the non-null parameter values.
59
+
@pragma('vm:prefer-inline')
60
+
@override
61
+
$Res call({Object? photoUri = null, Object? alt = null}) {
62
+
return _then(
63
+
_value.copyWith(
64
+
photoUri: null == photoUri
65
+
? _value.photoUri
66
+
: photoUri // ignore: cast_nullable_to_non_nullable
67
+
as String,
68
+
alt: null == alt
69
+
? _value.alt
70
+
: alt // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$ApplyAltsUpdateImplCopyWith<$Res>
80
+
implements $ApplyAltsUpdateCopyWith<$Res> {
81
+
factory _$$ApplyAltsUpdateImplCopyWith(
82
+
_$ApplyAltsUpdateImpl value,
83
+
$Res Function(_$ApplyAltsUpdateImpl) then,
84
+
) = __$$ApplyAltsUpdateImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String photoUri, String alt});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$ApplyAltsUpdateImplCopyWithImpl<$Res>
92
+
extends _$ApplyAltsUpdateCopyWithImpl<$Res, _$ApplyAltsUpdateImpl>
93
+
implements _$$ApplyAltsUpdateImplCopyWith<$Res> {
94
+
__$$ApplyAltsUpdateImplCopyWithImpl(
95
+
_$ApplyAltsUpdateImpl _value,
96
+
$Res Function(_$ApplyAltsUpdateImpl) _then,
97
+
) : super(_value, _then);
98
+
99
+
/// Create a copy of ApplyAltsUpdate
100
+
/// with the given fields replaced by the non-null parameter values.
101
+
@pragma('vm:prefer-inline')
102
+
@override
103
+
$Res call({Object? photoUri = null, Object? alt = null}) {
104
+
return _then(
105
+
_$ApplyAltsUpdateImpl(
106
+
photoUri: null == photoUri
107
+
? _value.photoUri
108
+
: photoUri // ignore: cast_nullable_to_non_nullable
109
+
as String,
110
+
alt: null == alt
111
+
? _value.alt
112
+
: alt // ignore: cast_nullable_to_non_nullable
113
+
as String,
114
+
),
115
+
);
116
+
}
117
+
}
118
+
119
+
/// @nodoc
120
+
@JsonSerializable()
121
+
class _$ApplyAltsUpdateImpl implements _ApplyAltsUpdate {
122
+
const _$ApplyAltsUpdateImpl({required this.photoUri, required this.alt});
123
+
124
+
factory _$ApplyAltsUpdateImpl.fromJson(Map<String, dynamic> json) =>
125
+
_$$ApplyAltsUpdateImplFromJson(json);
126
+
127
+
@override
128
+
final String photoUri;
129
+
@override
130
+
final String alt;
131
+
132
+
@override
133
+
String toString() {
134
+
return 'ApplyAltsUpdate(photoUri: $photoUri, alt: $alt)';
135
+
}
136
+
137
+
@override
138
+
bool operator ==(Object other) {
139
+
return identical(this, other) ||
140
+
(other.runtimeType == runtimeType &&
141
+
other is _$ApplyAltsUpdateImpl &&
142
+
(identical(other.photoUri, photoUri) ||
143
+
other.photoUri == photoUri) &&
144
+
(identical(other.alt, alt) || other.alt == alt));
145
+
}
146
+
147
+
@JsonKey(includeFromJson: false, includeToJson: false)
148
+
@override
149
+
int get hashCode => Object.hash(runtimeType, photoUri, alt);
150
+
151
+
/// Create a copy of ApplyAltsUpdate
152
+
/// with the given fields replaced by the non-null parameter values.
153
+
@JsonKey(includeFromJson: false, includeToJson: false)
154
+
@override
155
+
@pragma('vm:prefer-inline')
156
+
_$$ApplyAltsUpdateImplCopyWith<_$ApplyAltsUpdateImpl> get copyWith =>
157
+
__$$ApplyAltsUpdateImplCopyWithImpl<_$ApplyAltsUpdateImpl>(
158
+
this,
159
+
_$identity,
160
+
);
161
+
162
+
@override
163
+
Map<String, dynamic> toJson() {
164
+
return _$$ApplyAltsUpdateImplToJson(this);
165
+
}
166
+
}
167
+
168
+
abstract class _ApplyAltsUpdate implements ApplyAltsUpdate {
169
+
const factory _ApplyAltsUpdate({
170
+
required final String photoUri,
171
+
required final String alt,
172
+
}) = _$ApplyAltsUpdateImpl;
173
+
174
+
factory _ApplyAltsUpdate.fromJson(Map<String, dynamic> json) =
175
+
_$ApplyAltsUpdateImpl.fromJson;
176
+
177
+
@override
178
+
String get photoUri;
179
+
@override
180
+
String get alt;
181
+
182
+
/// Create a copy of ApplyAltsUpdate
183
+
/// with the given fields replaced by the non-null parameter values.
184
+
@override
185
+
@JsonKey(includeFromJson: false, includeToJson: false)
186
+
_$$ApplyAltsUpdateImplCopyWith<_$ApplyAltsUpdateImpl> get copyWith =>
187
+
throw _privateConstructorUsedError;
188
+
}
+18
lib/models/procedures/apply_alts_update.g.dart
+18
lib/models/procedures/apply_alts_update.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'apply_alts_update.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$ApplyAltsUpdateImpl _$$ApplyAltsUpdateImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$ApplyAltsUpdateImpl(
12
+
photoUri: json['photoUri'] as String,
13
+
alt: json['alt'] as String,
14
+
);
15
+
16
+
Map<String, dynamic> _$$ApplyAltsUpdateImplToJson(
17
+
_$ApplyAltsUpdateImpl instance,
18
+
) => <String, dynamic>{'photoUri': instance.photoUri, 'alt': instance.alt};
+24
lib/models/procedures/apply_sort_request.dart
+24
lib/models/procedures/apply_sort_request.dart
···
1
+
import 'package:json_annotation/json_annotation.dart';
2
+
3
+
part 'apply_sort_request.g.dart';
4
+
5
+
@JsonSerializable()
6
+
class ApplySortRequest {
7
+
final List<ApplySortUpdate> writes;
8
+
9
+
ApplySortRequest({required this.writes});
10
+
11
+
factory ApplySortRequest.fromJson(Map<String, dynamic> json) => _$ApplySortRequestFromJson(json);
12
+
Map<String, dynamic> toJson() => _$ApplySortRequestToJson(this);
13
+
}
14
+
15
+
@JsonSerializable()
16
+
class ApplySortUpdate {
17
+
final String itemUri;
18
+
final int position;
19
+
20
+
ApplySortUpdate({required this.itemUri, required this.position});
21
+
22
+
factory ApplySortUpdate.fromJson(Map<String, dynamic> json) => _$ApplySortUpdateFromJson(json);
23
+
Map<String, dynamic> toJson() => _$ApplySortUpdateToJson(this);
24
+
}
+29
lib/models/procedures/apply_sort_request.g.dart
+29
lib/models/procedures/apply_sort_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'apply_sort_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
ApplySortRequest _$ApplySortRequestFromJson(Map<String, dynamic> json) =>
10
+
ApplySortRequest(
11
+
writes: (json['writes'] as List<dynamic>)
12
+
.map((e) => ApplySortUpdate.fromJson(e as Map<String, dynamic>))
13
+
.toList(),
14
+
);
15
+
16
+
Map<String, dynamic> _$ApplySortRequestToJson(ApplySortRequest instance) =>
17
+
<String, dynamic>{'writes': instance.writes};
18
+
19
+
ApplySortUpdate _$ApplySortUpdateFromJson(Map<String, dynamic> json) =>
20
+
ApplySortUpdate(
21
+
itemUri: json['itemUri'] as String,
22
+
position: (json['position'] as num).toInt(),
23
+
);
24
+
25
+
Map<String, dynamic> _$ApplySortUpdateToJson(ApplySortUpdate instance) =>
26
+
<String, dynamic>{
27
+
'itemUri': instance.itemUri,
28
+
'position': instance.position,
29
+
};
+14
lib/models/procedures/apply_sort_response.dart
+14
lib/models/procedures/apply_sort_response.dart
···
1
+
import 'package:json_annotation/json_annotation.dart';
2
+
3
+
part 'apply_sort_response.g.dart';
4
+
5
+
@JsonSerializable()
6
+
class ApplySortResponse {
7
+
final bool success;
8
+
9
+
ApplySortResponse({required this.success});
10
+
11
+
factory ApplySortResponse.fromJson(Map<String, dynamic> json) =>
12
+
_$ApplySortResponseFromJson(json);
13
+
Map<String, dynamic> toJson() => _$ApplySortResponseToJson(this);
14
+
}
+13
lib/models/procedures/apply_sort_response.g.dart
+13
lib/models/procedures/apply_sort_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'apply_sort_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
ApplySortResponse _$ApplySortResponseFromJson(Map<String, dynamic> json) =>
10
+
ApplySortResponse(success: json['success'] as bool);
11
+
12
+
Map<String, dynamic> _$ApplySortResponseToJson(ApplySortResponse instance) =>
13
+
<String, dynamic>{'success': instance.success};
+19
lib/models/procedures/create_comment_request.dart
+19
lib/models/procedures/create_comment_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_comment_request.freezed.dart';
4
+
part 'create_comment_request.g.dart';
5
+
6
+
/// Request model for creating a comment.
7
+
/// See lexicon: social.grain.comment.createComment
8
+
@freezed
9
+
class CreateCommentRequest with _$CreateCommentRequest {
10
+
const factory CreateCommentRequest({
11
+
required String text,
12
+
required String subject,
13
+
String? focus,
14
+
String? replyTo,
15
+
}) = _CreateCommentRequest;
16
+
17
+
factory CreateCommentRequest.fromJson(Map<String, dynamic> json) =>
18
+
_$CreateCommentRequestFromJson(json);
19
+
}
+236
lib/models/procedures/create_comment_request.freezed.dart
+236
lib/models/procedures/create_comment_request.freezed.dart
···
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_comment_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
+
CreateCommentRequest _$CreateCommentRequestFromJson(Map<String, dynamic> json) {
19
+
return _CreateCommentRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$CreateCommentRequest {
24
+
String get text => throw _privateConstructorUsedError;
25
+
String get subject => throw _privateConstructorUsedError;
26
+
String? get focus => throw _privateConstructorUsedError;
27
+
String? get replyTo => throw _privateConstructorUsedError;
28
+
29
+
/// Serializes this CreateCommentRequest to a JSON map.
30
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
31
+
32
+
/// Create a copy of CreateCommentRequest
33
+
/// with the given fields replaced by the non-null parameter values.
34
+
@JsonKey(includeFromJson: false, includeToJson: false)
35
+
$CreateCommentRequestCopyWith<CreateCommentRequest> get copyWith =>
36
+
throw _privateConstructorUsedError;
37
+
}
38
+
39
+
/// @nodoc
40
+
abstract class $CreateCommentRequestCopyWith<$Res> {
41
+
factory $CreateCommentRequestCopyWith(
42
+
CreateCommentRequest value,
43
+
$Res Function(CreateCommentRequest) then,
44
+
) = _$CreateCommentRequestCopyWithImpl<$Res, CreateCommentRequest>;
45
+
@useResult
46
+
$Res call({String text, String subject, String? focus, String? replyTo});
47
+
}
48
+
49
+
/// @nodoc
50
+
class _$CreateCommentRequestCopyWithImpl<
51
+
$Res,
52
+
$Val extends CreateCommentRequest
53
+
>
54
+
implements $CreateCommentRequestCopyWith<$Res> {
55
+
_$CreateCommentRequestCopyWithImpl(this._value, this._then);
56
+
57
+
// ignore: unused_field
58
+
final $Val _value;
59
+
// ignore: unused_field
60
+
final $Res Function($Val) _then;
61
+
62
+
/// Create a copy of CreateCommentRequest
63
+
/// with the given fields replaced by the non-null parameter values.
64
+
@pragma('vm:prefer-inline')
65
+
@override
66
+
$Res call({
67
+
Object? text = null,
68
+
Object? subject = null,
69
+
Object? focus = freezed,
70
+
Object? replyTo = freezed,
71
+
}) {
72
+
return _then(
73
+
_value.copyWith(
74
+
text: null == text
75
+
? _value.text
76
+
: text // ignore: cast_nullable_to_non_nullable
77
+
as String,
78
+
subject: null == subject
79
+
? _value.subject
80
+
: subject // ignore: cast_nullable_to_non_nullable
81
+
as String,
82
+
focus: freezed == focus
83
+
? _value.focus
84
+
: focus // ignore: cast_nullable_to_non_nullable
85
+
as String?,
86
+
replyTo: freezed == replyTo
87
+
? _value.replyTo
88
+
: replyTo // ignore: cast_nullable_to_non_nullable
89
+
as String?,
90
+
)
91
+
as $Val,
92
+
);
93
+
}
94
+
}
95
+
96
+
/// @nodoc
97
+
abstract class _$$CreateCommentRequestImplCopyWith<$Res>
98
+
implements $CreateCommentRequestCopyWith<$Res> {
99
+
factory _$$CreateCommentRequestImplCopyWith(
100
+
_$CreateCommentRequestImpl value,
101
+
$Res Function(_$CreateCommentRequestImpl) then,
102
+
) = __$$CreateCommentRequestImplCopyWithImpl<$Res>;
103
+
@override
104
+
@useResult
105
+
$Res call({String text, String subject, String? focus, String? replyTo});
106
+
}
107
+
108
+
/// @nodoc
109
+
class __$$CreateCommentRequestImplCopyWithImpl<$Res>
110
+
extends _$CreateCommentRequestCopyWithImpl<$Res, _$CreateCommentRequestImpl>
111
+
implements _$$CreateCommentRequestImplCopyWith<$Res> {
112
+
__$$CreateCommentRequestImplCopyWithImpl(
113
+
_$CreateCommentRequestImpl _value,
114
+
$Res Function(_$CreateCommentRequestImpl) _then,
115
+
) : super(_value, _then);
116
+
117
+
/// Create a copy of CreateCommentRequest
118
+
/// with the given fields replaced by the non-null parameter values.
119
+
@pragma('vm:prefer-inline')
120
+
@override
121
+
$Res call({
122
+
Object? text = null,
123
+
Object? subject = null,
124
+
Object? focus = freezed,
125
+
Object? replyTo = freezed,
126
+
}) {
127
+
return _then(
128
+
_$CreateCommentRequestImpl(
129
+
text: null == text
130
+
? _value.text
131
+
: text // ignore: cast_nullable_to_non_nullable
132
+
as String,
133
+
subject: null == subject
134
+
? _value.subject
135
+
: subject // ignore: cast_nullable_to_non_nullable
136
+
as String,
137
+
focus: freezed == focus
138
+
? _value.focus
139
+
: focus // ignore: cast_nullable_to_non_nullable
140
+
as String?,
141
+
replyTo: freezed == replyTo
142
+
? _value.replyTo
143
+
: replyTo // ignore: cast_nullable_to_non_nullable
144
+
as String?,
145
+
),
146
+
);
147
+
}
148
+
}
149
+
150
+
/// @nodoc
151
+
@JsonSerializable()
152
+
class _$CreateCommentRequestImpl implements _CreateCommentRequest {
153
+
const _$CreateCommentRequestImpl({
154
+
required this.text,
155
+
required this.subject,
156
+
this.focus,
157
+
this.replyTo,
158
+
});
159
+
160
+
factory _$CreateCommentRequestImpl.fromJson(Map<String, dynamic> json) =>
161
+
_$$CreateCommentRequestImplFromJson(json);
162
+
163
+
@override
164
+
final String text;
165
+
@override
166
+
final String subject;
167
+
@override
168
+
final String? focus;
169
+
@override
170
+
final String? replyTo;
171
+
172
+
@override
173
+
String toString() {
174
+
return 'CreateCommentRequest(text: $text, subject: $subject, focus: $focus, replyTo: $replyTo)';
175
+
}
176
+
177
+
@override
178
+
bool operator ==(Object other) {
179
+
return identical(this, other) ||
180
+
(other.runtimeType == runtimeType &&
181
+
other is _$CreateCommentRequestImpl &&
182
+
(identical(other.text, text) || other.text == text) &&
183
+
(identical(other.subject, subject) || other.subject == subject) &&
184
+
(identical(other.focus, focus) || other.focus == focus) &&
185
+
(identical(other.replyTo, replyTo) || other.replyTo == replyTo));
186
+
}
187
+
188
+
@JsonKey(includeFromJson: false, includeToJson: false)
189
+
@override
190
+
int get hashCode => Object.hash(runtimeType, text, subject, focus, replyTo);
191
+
192
+
/// Create a copy of CreateCommentRequest
193
+
/// with the given fields replaced by the non-null parameter values.
194
+
@JsonKey(includeFromJson: false, includeToJson: false)
195
+
@override
196
+
@pragma('vm:prefer-inline')
197
+
_$$CreateCommentRequestImplCopyWith<_$CreateCommentRequestImpl>
198
+
get copyWith =>
199
+
__$$CreateCommentRequestImplCopyWithImpl<_$CreateCommentRequestImpl>(
200
+
this,
201
+
_$identity,
202
+
);
203
+
204
+
@override
205
+
Map<String, dynamic> toJson() {
206
+
return _$$CreateCommentRequestImplToJson(this);
207
+
}
208
+
}
209
+
210
+
abstract class _CreateCommentRequest implements CreateCommentRequest {
211
+
const factory _CreateCommentRequest({
212
+
required final String text,
213
+
required final String subject,
214
+
final String? focus,
215
+
final String? replyTo,
216
+
}) = _$CreateCommentRequestImpl;
217
+
218
+
factory _CreateCommentRequest.fromJson(Map<String, dynamic> json) =
219
+
_$CreateCommentRequestImpl.fromJson;
220
+
221
+
@override
222
+
String get text;
223
+
@override
224
+
String get subject;
225
+
@override
226
+
String? get focus;
227
+
@override
228
+
String? get replyTo;
229
+
230
+
/// Create a copy of CreateCommentRequest
231
+
/// with the given fields replaced by the non-null parameter values.
232
+
@override
233
+
@JsonKey(includeFromJson: false, includeToJson: false)
234
+
_$$CreateCommentRequestImplCopyWith<_$CreateCommentRequestImpl>
235
+
get copyWith => throw _privateConstructorUsedError;
236
+
}
+25
lib/models/procedures/create_comment_request.g.dart
+25
lib/models/procedures/create_comment_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_comment_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateCommentRequestImpl _$$CreateCommentRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateCommentRequestImpl(
12
+
text: json['text'] as String,
13
+
subject: json['subject'] as String,
14
+
focus: json['focus'] as String?,
15
+
replyTo: json['replyTo'] as String?,
16
+
);
17
+
18
+
Map<String, dynamic> _$$CreateCommentRequestImplToJson(
19
+
_$CreateCommentRequestImpl instance,
20
+
) => <String, dynamic>{
21
+
'text': instance.text,
22
+
'subject': instance.subject,
23
+
'focus': instance.focus,
24
+
'replyTo': instance.replyTo,
25
+
};
+14
lib/models/procedures/create_comment_response.dart
+14
lib/models/procedures/create_comment_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_comment_response.freezed.dart';
4
+
part 'create_comment_response.g.dart';
5
+
6
+
/// Response model for creating a comment.
7
+
/// See lexicon: social.grain.comment.createComment
8
+
@freezed
9
+
class CreateCommentResponse with _$CreateCommentResponse {
10
+
const factory CreateCommentResponse({required String commentUri}) = _CreateCommentResponse;
11
+
12
+
factory CreateCommentResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$CreateCommentResponseFromJson(json);
14
+
}
+179
lib/models/procedures/create_comment_response.freezed.dart
+179
lib/models/procedures/create_comment_response.freezed.dart
···
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_comment_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
+
CreateCommentResponse _$CreateCommentResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateCommentResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateCommentResponse {
26
+
String get commentUri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this CreateCommentResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of CreateCommentResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$CreateCommentResponseCopyWith<CreateCommentResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $CreateCommentResponseCopyWith<$Res> {
40
+
factory $CreateCommentResponseCopyWith(
41
+
CreateCommentResponse value,
42
+
$Res Function(CreateCommentResponse) then,
43
+
) = _$CreateCommentResponseCopyWithImpl<$Res, CreateCommentResponse>;
44
+
@useResult
45
+
$Res call({String commentUri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$CreateCommentResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends CreateCommentResponse
52
+
>
53
+
implements $CreateCommentResponseCopyWith<$Res> {
54
+
_$CreateCommentResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of CreateCommentResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? commentUri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
commentUri: null == commentUri
69
+
? _value.commentUri
70
+
: commentUri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$CreateCommentResponseImplCopyWith<$Res>
80
+
implements $CreateCommentResponseCopyWith<$Res> {
81
+
factory _$$CreateCommentResponseImplCopyWith(
82
+
_$CreateCommentResponseImpl value,
83
+
$Res Function(_$CreateCommentResponseImpl) then,
84
+
) = __$$CreateCommentResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String commentUri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$CreateCommentResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$CreateCommentResponseCopyWithImpl<$Res, _$CreateCommentResponseImpl>
94
+
implements _$$CreateCommentResponseImplCopyWith<$Res> {
95
+
__$$CreateCommentResponseImplCopyWithImpl(
96
+
_$CreateCommentResponseImpl _value,
97
+
$Res Function(_$CreateCommentResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of CreateCommentResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? commentUri = null}) {
105
+
return _then(
106
+
_$CreateCommentResponseImpl(
107
+
commentUri: null == commentUri
108
+
? _value.commentUri
109
+
: commentUri // ignore: cast_nullable_to_non_nullable
110
+
as String,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$CreateCommentResponseImpl implements _CreateCommentResponse {
119
+
const _$CreateCommentResponseImpl({required this.commentUri});
120
+
121
+
factory _$CreateCommentResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$CreateCommentResponseImplFromJson(json);
123
+
124
+
@override
125
+
final String commentUri;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'CreateCommentResponse(commentUri: $commentUri)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$CreateCommentResponseImpl &&
137
+
(identical(other.commentUri, commentUri) ||
138
+
other.commentUri == commentUri));
139
+
}
140
+
141
+
@JsonKey(includeFromJson: false, includeToJson: false)
142
+
@override
143
+
int get hashCode => Object.hash(runtimeType, commentUri);
144
+
145
+
/// Create a copy of CreateCommentResponse
146
+
/// with the given fields replaced by the non-null parameter values.
147
+
@JsonKey(includeFromJson: false, includeToJson: false)
148
+
@override
149
+
@pragma('vm:prefer-inline')
150
+
_$$CreateCommentResponseImplCopyWith<_$CreateCommentResponseImpl>
151
+
get copyWith =>
152
+
__$$CreateCommentResponseImplCopyWithImpl<_$CreateCommentResponseImpl>(
153
+
this,
154
+
_$identity,
155
+
);
156
+
157
+
@override
158
+
Map<String, dynamic> toJson() {
159
+
return _$$CreateCommentResponseImplToJson(this);
160
+
}
161
+
}
162
+
163
+
abstract class _CreateCommentResponse implements CreateCommentResponse {
164
+
const factory _CreateCommentResponse({required final String commentUri}) =
165
+
_$CreateCommentResponseImpl;
166
+
167
+
factory _CreateCommentResponse.fromJson(Map<String, dynamic> json) =
168
+
_$CreateCommentResponseImpl.fromJson;
169
+
170
+
@override
171
+
String get commentUri;
172
+
173
+
/// Create a copy of CreateCommentResponse
174
+
/// with the given fields replaced by the non-null parameter values.
175
+
@override
176
+
@JsonKey(includeFromJson: false, includeToJson: false)
177
+
_$$CreateCommentResponseImplCopyWith<_$CreateCommentResponseImpl>
178
+
get copyWith => throw _privateConstructorUsedError;
179
+
}
+15
lib/models/procedures/create_comment_response.g.dart
+15
lib/models/procedures/create_comment_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_comment_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateCommentResponseImpl _$$CreateCommentResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateCommentResponseImpl(commentUri: json['commentUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateCommentResponseImplToJson(
14
+
_$CreateCommentResponseImpl instance,
15
+
) => <String, dynamic>{'commentUri': instance.commentUri};
+25
lib/models/procedures/create_exif_request.dart
+25
lib/models/procedures/create_exif_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_exif_request.freezed.dart';
4
+
part 'create_exif_request.g.dart';
5
+
6
+
/// Request model for creating a new Exif record for a photo.
7
+
@freezed
8
+
class CreateExifRequest with _$CreateExifRequest {
9
+
const factory CreateExifRequest({
10
+
required String photo,
11
+
String? dateTimeOriginal,
12
+
int? exposureTime,
13
+
int? fNumber,
14
+
String? flash,
15
+
int? focalLengthIn35mmFormat,
16
+
int? iSO,
17
+
String? lensMake,
18
+
String? lensModel,
19
+
String? make,
20
+
String? model,
21
+
}) = _CreateExifRequest;
22
+
23
+
factory CreateExifRequest.fromJson(Map<String, dynamic> json) =>
24
+
_$CreateExifRequestFromJson(json);
25
+
}
+403
lib/models/procedures/create_exif_request.freezed.dart
+403
lib/models/procedures/create_exif_request.freezed.dart
···
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
+39
lib/models/procedures/create_exif_request.g.dart
···
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
+15
lib/models/procedures/create_exif_response.dart
···
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
+
}
+171
lib/models/procedures/create_exif_response.freezed.dart
+171
lib/models/procedures/create_exif_response.freezed.dart
···
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_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
+
CreateExifResponse _$CreateExifResponseFromJson(Map<String, dynamic> json) {
19
+
return _CreateExifResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$CreateExifResponse {
24
+
String get exifUri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this CreateExifResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of CreateExifResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$CreateExifResponseCopyWith<CreateExifResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $CreateExifResponseCopyWith<$Res> {
38
+
factory $CreateExifResponseCopyWith(
39
+
CreateExifResponse value,
40
+
$Res Function(CreateExifResponse) then,
41
+
) = _$CreateExifResponseCopyWithImpl<$Res, CreateExifResponse>;
42
+
@useResult
43
+
$Res call({String exifUri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$CreateExifResponseCopyWithImpl<$Res, $Val extends CreateExifResponse>
48
+
implements $CreateExifResponseCopyWith<$Res> {
49
+
_$CreateExifResponseCopyWithImpl(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 CreateExifResponse
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? exifUri = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
exifUri: null == exifUri
64
+
? _value.exifUri
65
+
: exifUri // ignore: cast_nullable_to_non_nullable
66
+
as String,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$CreateExifResponseImplCopyWith<$Res>
75
+
implements $CreateExifResponseCopyWith<$Res> {
76
+
factory _$$CreateExifResponseImplCopyWith(
77
+
_$CreateExifResponseImpl value,
78
+
$Res Function(_$CreateExifResponseImpl) then,
79
+
) = __$$CreateExifResponseImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({String exifUri});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$CreateExifResponseImplCopyWithImpl<$Res>
87
+
extends _$CreateExifResponseCopyWithImpl<$Res, _$CreateExifResponseImpl>
88
+
implements _$$CreateExifResponseImplCopyWith<$Res> {
89
+
__$$CreateExifResponseImplCopyWithImpl(
90
+
_$CreateExifResponseImpl _value,
91
+
$Res Function(_$CreateExifResponseImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of CreateExifResponse
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? exifUri = null}) {
99
+
return _then(
100
+
_$CreateExifResponseImpl(
101
+
exifUri: null == exifUri
102
+
? _value.exifUri
103
+
: exifUri // ignore: cast_nullable_to_non_nullable
104
+
as String,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$CreateExifResponseImpl implements _CreateExifResponse {
113
+
const _$CreateExifResponseImpl({required this.exifUri});
114
+
115
+
factory _$CreateExifResponseImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$CreateExifResponseImplFromJson(json);
117
+
118
+
@override
119
+
final String exifUri;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'CreateExifResponse(exifUri: $exifUri)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$CreateExifResponseImpl &&
131
+
(identical(other.exifUri, exifUri) || other.exifUri == exifUri));
132
+
}
133
+
134
+
@JsonKey(includeFromJson: false, includeToJson: false)
135
+
@override
136
+
int get hashCode => Object.hash(runtimeType, exifUri);
137
+
138
+
/// Create a copy of CreateExifResponse
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
+
_$$CreateExifResponseImplCopyWith<_$CreateExifResponseImpl> get copyWith =>
144
+
__$$CreateExifResponseImplCopyWithImpl<_$CreateExifResponseImpl>(
145
+
this,
146
+
_$identity,
147
+
);
148
+
149
+
@override
150
+
Map<String, dynamic> toJson() {
151
+
return _$$CreateExifResponseImplToJson(this);
152
+
}
153
+
}
154
+
155
+
abstract class _CreateExifResponse implements CreateExifResponse {
156
+
const factory _CreateExifResponse({required final String exifUri}) =
157
+
_$CreateExifResponseImpl;
158
+
159
+
factory _CreateExifResponse.fromJson(Map<String, dynamic> json) =
160
+
_$CreateExifResponseImpl.fromJson;
161
+
162
+
@override
163
+
String get exifUri;
164
+
165
+
/// Create a copy of CreateExifResponse
166
+
/// with the given fields replaced by the non-null parameter values.
167
+
@override
168
+
@JsonKey(includeFromJson: false, includeToJson: false)
169
+
_$$CreateExifResponseImplCopyWith<_$CreateExifResponseImpl> get copyWith =>
170
+
throw _privateConstructorUsedError;
171
+
}
+15
lib/models/procedures/create_exif_response.g.dart
+15
lib/models/procedures/create_exif_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_exif_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateExifResponseImpl _$$CreateExifResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateExifResponseImpl(exifUri: json['exifUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateExifResponseImplToJson(
14
+
_$CreateExifResponseImpl instance,
15
+
) => <String, dynamic>{'exifUri': instance.exifUri};
+14
lib/models/procedures/create_favorite_request.dart
+14
lib/models/procedures/create_favorite_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_favorite_request.freezed.dart';
4
+
part 'create_favorite_request.g.dart';
5
+
6
+
/// Request model for creating a favorite.
7
+
/// See lexicon: social.grain.favorite.createFavorite
8
+
@freezed
9
+
class CreateFavoriteRequest with _$CreateFavoriteRequest {
10
+
const factory CreateFavoriteRequest({required String subject}) = _CreateFavoriteRequest;
11
+
12
+
factory CreateFavoriteRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$CreateFavoriteRequestFromJson(json);
14
+
}
+178
lib/models/procedures/create_favorite_request.freezed.dart
+178
lib/models/procedures/create_favorite_request.freezed.dart
···
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_favorite_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
+
CreateFavoriteRequest _$CreateFavoriteRequestFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateFavoriteRequest.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateFavoriteRequest {
26
+
String get subject => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this CreateFavoriteRequest to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of CreateFavoriteRequest
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$CreateFavoriteRequestCopyWith<CreateFavoriteRequest> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $CreateFavoriteRequestCopyWith<$Res> {
40
+
factory $CreateFavoriteRequestCopyWith(
41
+
CreateFavoriteRequest value,
42
+
$Res Function(CreateFavoriteRequest) then,
43
+
) = _$CreateFavoriteRequestCopyWithImpl<$Res, CreateFavoriteRequest>;
44
+
@useResult
45
+
$Res call({String subject});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$CreateFavoriteRequestCopyWithImpl<
50
+
$Res,
51
+
$Val extends CreateFavoriteRequest
52
+
>
53
+
implements $CreateFavoriteRequestCopyWith<$Res> {
54
+
_$CreateFavoriteRequestCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of CreateFavoriteRequest
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? subject = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
subject: null == subject
69
+
? _value.subject
70
+
: subject // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$CreateFavoriteRequestImplCopyWith<$Res>
80
+
implements $CreateFavoriteRequestCopyWith<$Res> {
81
+
factory _$$CreateFavoriteRequestImplCopyWith(
82
+
_$CreateFavoriteRequestImpl value,
83
+
$Res Function(_$CreateFavoriteRequestImpl) then,
84
+
) = __$$CreateFavoriteRequestImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String subject});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$CreateFavoriteRequestImplCopyWithImpl<$Res>
92
+
extends
93
+
_$CreateFavoriteRequestCopyWithImpl<$Res, _$CreateFavoriteRequestImpl>
94
+
implements _$$CreateFavoriteRequestImplCopyWith<$Res> {
95
+
__$$CreateFavoriteRequestImplCopyWithImpl(
96
+
_$CreateFavoriteRequestImpl _value,
97
+
$Res Function(_$CreateFavoriteRequestImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of CreateFavoriteRequest
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? subject = null}) {
105
+
return _then(
106
+
_$CreateFavoriteRequestImpl(
107
+
subject: null == subject
108
+
? _value.subject
109
+
: subject // ignore: cast_nullable_to_non_nullable
110
+
as String,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$CreateFavoriteRequestImpl implements _CreateFavoriteRequest {
119
+
const _$CreateFavoriteRequestImpl({required this.subject});
120
+
121
+
factory _$CreateFavoriteRequestImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$CreateFavoriteRequestImplFromJson(json);
123
+
124
+
@override
125
+
final String subject;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'CreateFavoriteRequest(subject: $subject)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$CreateFavoriteRequestImpl &&
137
+
(identical(other.subject, subject) || other.subject == subject));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, subject);
143
+
144
+
/// Create a copy of CreateFavoriteRequest
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$CreateFavoriteRequestImplCopyWith<_$CreateFavoriteRequestImpl>
150
+
get copyWith =>
151
+
__$$CreateFavoriteRequestImplCopyWithImpl<_$CreateFavoriteRequestImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$CreateFavoriteRequestImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _CreateFavoriteRequest implements CreateFavoriteRequest {
163
+
const factory _CreateFavoriteRequest({required final String subject}) =
164
+
_$CreateFavoriteRequestImpl;
165
+
166
+
factory _CreateFavoriteRequest.fromJson(Map<String, dynamic> json) =
167
+
_$CreateFavoriteRequestImpl.fromJson;
168
+
169
+
@override
170
+
String get subject;
171
+
172
+
/// Create a copy of CreateFavoriteRequest
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$CreateFavoriteRequestImplCopyWith<_$CreateFavoriteRequestImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/create_favorite_request.g.dart
+15
lib/models/procedures/create_favorite_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_favorite_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateFavoriteRequestImpl _$$CreateFavoriteRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateFavoriteRequestImpl(subject: json['subject'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateFavoriteRequestImplToJson(
14
+
_$CreateFavoriteRequestImpl instance,
15
+
) => <String, dynamic>{'subject': instance.subject};
+14
lib/models/procedures/create_favorite_response.dart
+14
lib/models/procedures/create_favorite_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_favorite_response.freezed.dart';
4
+
part 'create_favorite_response.g.dart';
5
+
6
+
/// Response model for creating a favorite.
7
+
/// See lexicon: social.grain.favorite.createFavorite
8
+
@freezed
9
+
class CreateFavoriteResponse with _$CreateFavoriteResponse {
10
+
const factory CreateFavoriteResponse({required String favoriteUri}) = _CreateFavoriteResponse;
11
+
12
+
factory CreateFavoriteResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$CreateFavoriteResponseFromJson(json);
14
+
}
+179
lib/models/procedures/create_favorite_response.freezed.dart
+179
lib/models/procedures/create_favorite_response.freezed.dart
···
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_favorite_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
+
CreateFavoriteResponse _$CreateFavoriteResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateFavoriteResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateFavoriteResponse {
26
+
String get favoriteUri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this CreateFavoriteResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of CreateFavoriteResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$CreateFavoriteResponseCopyWith<CreateFavoriteResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $CreateFavoriteResponseCopyWith<$Res> {
40
+
factory $CreateFavoriteResponseCopyWith(
41
+
CreateFavoriteResponse value,
42
+
$Res Function(CreateFavoriteResponse) then,
43
+
) = _$CreateFavoriteResponseCopyWithImpl<$Res, CreateFavoriteResponse>;
44
+
@useResult
45
+
$Res call({String favoriteUri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$CreateFavoriteResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends CreateFavoriteResponse
52
+
>
53
+
implements $CreateFavoriteResponseCopyWith<$Res> {
54
+
_$CreateFavoriteResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of CreateFavoriteResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? favoriteUri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
favoriteUri: null == favoriteUri
69
+
? _value.favoriteUri
70
+
: favoriteUri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$CreateFavoriteResponseImplCopyWith<$Res>
80
+
implements $CreateFavoriteResponseCopyWith<$Res> {
81
+
factory _$$CreateFavoriteResponseImplCopyWith(
82
+
_$CreateFavoriteResponseImpl value,
83
+
$Res Function(_$CreateFavoriteResponseImpl) then,
84
+
) = __$$CreateFavoriteResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String favoriteUri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$CreateFavoriteResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$CreateFavoriteResponseCopyWithImpl<$Res, _$CreateFavoriteResponseImpl>
94
+
implements _$$CreateFavoriteResponseImplCopyWith<$Res> {
95
+
__$$CreateFavoriteResponseImplCopyWithImpl(
96
+
_$CreateFavoriteResponseImpl _value,
97
+
$Res Function(_$CreateFavoriteResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of CreateFavoriteResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? favoriteUri = null}) {
105
+
return _then(
106
+
_$CreateFavoriteResponseImpl(
107
+
favoriteUri: null == favoriteUri
108
+
? _value.favoriteUri
109
+
: favoriteUri // ignore: cast_nullable_to_non_nullable
110
+
as String,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$CreateFavoriteResponseImpl implements _CreateFavoriteResponse {
119
+
const _$CreateFavoriteResponseImpl({required this.favoriteUri});
120
+
121
+
factory _$CreateFavoriteResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$CreateFavoriteResponseImplFromJson(json);
123
+
124
+
@override
125
+
final String favoriteUri;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'CreateFavoriteResponse(favoriteUri: $favoriteUri)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$CreateFavoriteResponseImpl &&
137
+
(identical(other.favoriteUri, favoriteUri) ||
138
+
other.favoriteUri == favoriteUri));
139
+
}
140
+
141
+
@JsonKey(includeFromJson: false, includeToJson: false)
142
+
@override
143
+
int get hashCode => Object.hash(runtimeType, favoriteUri);
144
+
145
+
/// Create a copy of CreateFavoriteResponse
146
+
/// with the given fields replaced by the non-null parameter values.
147
+
@JsonKey(includeFromJson: false, includeToJson: false)
148
+
@override
149
+
@pragma('vm:prefer-inline')
150
+
_$$CreateFavoriteResponseImplCopyWith<_$CreateFavoriteResponseImpl>
151
+
get copyWith =>
152
+
__$$CreateFavoriteResponseImplCopyWithImpl<_$CreateFavoriteResponseImpl>(
153
+
this,
154
+
_$identity,
155
+
);
156
+
157
+
@override
158
+
Map<String, dynamic> toJson() {
159
+
return _$$CreateFavoriteResponseImplToJson(this);
160
+
}
161
+
}
162
+
163
+
abstract class _CreateFavoriteResponse implements CreateFavoriteResponse {
164
+
const factory _CreateFavoriteResponse({required final String favoriteUri}) =
165
+
_$CreateFavoriteResponseImpl;
166
+
167
+
factory _CreateFavoriteResponse.fromJson(Map<String, dynamic> json) =
168
+
_$CreateFavoriteResponseImpl.fromJson;
169
+
170
+
@override
171
+
String get favoriteUri;
172
+
173
+
/// Create a copy of CreateFavoriteResponse
174
+
/// with the given fields replaced by the non-null parameter values.
175
+
@override
176
+
@JsonKey(includeFromJson: false, includeToJson: false)
177
+
_$$CreateFavoriteResponseImplCopyWith<_$CreateFavoriteResponseImpl>
178
+
get copyWith => throw _privateConstructorUsedError;
179
+
}
+15
lib/models/procedures/create_favorite_response.g.dart
+15
lib/models/procedures/create_favorite_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_favorite_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateFavoriteResponseImpl _$$CreateFavoriteResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateFavoriteResponseImpl(favoriteUri: json['favoriteUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateFavoriteResponseImplToJson(
14
+
_$CreateFavoriteResponseImpl instance,
15
+
) => <String, dynamic>{'favoriteUri': instance.favoriteUri};
+15
lib/models/procedures/create_follow_request.dart
+15
lib/models/procedures/create_follow_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_follow_request.freezed.dart';
4
+
part 'create_follow_request.g.dart';
5
+
6
+
/// Request model for creating a follow relationship.
7
+
///
8
+
/// [subject] - The actor DID to follow.
9
+
@freezed
10
+
class CreateFollowRequest with _$CreateFollowRequest {
11
+
const factory CreateFollowRequest({required String subject}) = _CreateFollowRequest;
12
+
13
+
factory CreateFollowRequest.fromJson(Map<String, dynamic> json) =>
14
+
_$CreateFollowRequestFromJson(json);
15
+
}
+171
lib/models/procedures/create_follow_request.freezed.dart
+171
lib/models/procedures/create_follow_request.freezed.dart
···
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_follow_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
+
CreateFollowRequest _$CreateFollowRequestFromJson(Map<String, dynamic> json) {
19
+
return _CreateFollowRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$CreateFollowRequest {
24
+
String get subject => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this CreateFollowRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of CreateFollowRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$CreateFollowRequestCopyWith<CreateFollowRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $CreateFollowRequestCopyWith<$Res> {
38
+
factory $CreateFollowRequestCopyWith(
39
+
CreateFollowRequest value,
40
+
$Res Function(CreateFollowRequest) then,
41
+
) = _$CreateFollowRequestCopyWithImpl<$Res, CreateFollowRequest>;
42
+
@useResult
43
+
$Res call({String subject});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$CreateFollowRequestCopyWithImpl<$Res, $Val extends CreateFollowRequest>
48
+
implements $CreateFollowRequestCopyWith<$Res> {
49
+
_$CreateFollowRequestCopyWithImpl(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 CreateFollowRequest
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? subject = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
subject: null == subject
64
+
? _value.subject
65
+
: subject // ignore: cast_nullable_to_non_nullable
66
+
as String,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$CreateFollowRequestImplCopyWith<$Res>
75
+
implements $CreateFollowRequestCopyWith<$Res> {
76
+
factory _$$CreateFollowRequestImplCopyWith(
77
+
_$CreateFollowRequestImpl value,
78
+
$Res Function(_$CreateFollowRequestImpl) then,
79
+
) = __$$CreateFollowRequestImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({String subject});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$CreateFollowRequestImplCopyWithImpl<$Res>
87
+
extends _$CreateFollowRequestCopyWithImpl<$Res, _$CreateFollowRequestImpl>
88
+
implements _$$CreateFollowRequestImplCopyWith<$Res> {
89
+
__$$CreateFollowRequestImplCopyWithImpl(
90
+
_$CreateFollowRequestImpl _value,
91
+
$Res Function(_$CreateFollowRequestImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of CreateFollowRequest
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? subject = null}) {
99
+
return _then(
100
+
_$CreateFollowRequestImpl(
101
+
subject: null == subject
102
+
? _value.subject
103
+
: subject // ignore: cast_nullable_to_non_nullable
104
+
as String,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$CreateFollowRequestImpl implements _CreateFollowRequest {
113
+
const _$CreateFollowRequestImpl({required this.subject});
114
+
115
+
factory _$CreateFollowRequestImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$CreateFollowRequestImplFromJson(json);
117
+
118
+
@override
119
+
final String subject;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'CreateFollowRequest(subject: $subject)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$CreateFollowRequestImpl &&
131
+
(identical(other.subject, subject) || other.subject == subject));
132
+
}
133
+
134
+
@JsonKey(includeFromJson: false, includeToJson: false)
135
+
@override
136
+
int get hashCode => Object.hash(runtimeType, subject);
137
+
138
+
/// Create a copy of CreateFollowRequest
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
+
_$$CreateFollowRequestImplCopyWith<_$CreateFollowRequestImpl> get copyWith =>
144
+
__$$CreateFollowRequestImplCopyWithImpl<_$CreateFollowRequestImpl>(
145
+
this,
146
+
_$identity,
147
+
);
148
+
149
+
@override
150
+
Map<String, dynamic> toJson() {
151
+
return _$$CreateFollowRequestImplToJson(this);
152
+
}
153
+
}
154
+
155
+
abstract class _CreateFollowRequest implements CreateFollowRequest {
156
+
const factory _CreateFollowRequest({required final String subject}) =
157
+
_$CreateFollowRequestImpl;
158
+
159
+
factory _CreateFollowRequest.fromJson(Map<String, dynamic> json) =
160
+
_$CreateFollowRequestImpl.fromJson;
161
+
162
+
@override
163
+
String get subject;
164
+
165
+
/// Create a copy of CreateFollowRequest
166
+
/// with the given fields replaced by the non-null parameter values.
167
+
@override
168
+
@JsonKey(includeFromJson: false, includeToJson: false)
169
+
_$$CreateFollowRequestImplCopyWith<_$CreateFollowRequestImpl> get copyWith =>
170
+
throw _privateConstructorUsedError;
171
+
}
+15
lib/models/procedures/create_follow_request.g.dart
+15
lib/models/procedures/create_follow_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_follow_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateFollowRequestImpl _$$CreateFollowRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateFollowRequestImpl(subject: json['subject'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateFollowRequestImplToJson(
14
+
_$CreateFollowRequestImpl instance,
15
+
) => <String, dynamic>{'subject': instance.subject};
+15
lib/models/procedures/create_follow_response.dart
+15
lib/models/procedures/create_follow_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_follow_response.freezed.dart';
4
+
part 'create_follow_response.g.dart';
5
+
6
+
/// Response model for creating a follow relationship.
7
+
///
8
+
/// [followUri] - The URI of the created follow relationship.
9
+
@freezed
10
+
class CreateFollowResponse with _$CreateFollowResponse {
11
+
const factory CreateFollowResponse({required String followUri}) = _CreateFollowResponse;
12
+
13
+
factory CreateFollowResponse.fromJson(Map<String, dynamic> json) =>
14
+
_$CreateFollowResponseFromJson(json);
15
+
}
+176
lib/models/procedures/create_follow_response.freezed.dart
+176
lib/models/procedures/create_follow_response.freezed.dart
···
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_follow_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
+
CreateFollowResponse _$CreateFollowResponseFromJson(Map<String, dynamic> json) {
19
+
return _CreateFollowResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$CreateFollowResponse {
24
+
String get followUri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this CreateFollowResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of CreateFollowResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$CreateFollowResponseCopyWith<CreateFollowResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $CreateFollowResponseCopyWith<$Res> {
38
+
factory $CreateFollowResponseCopyWith(
39
+
CreateFollowResponse value,
40
+
$Res Function(CreateFollowResponse) then,
41
+
) = _$CreateFollowResponseCopyWithImpl<$Res, CreateFollowResponse>;
42
+
@useResult
43
+
$Res call({String followUri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$CreateFollowResponseCopyWithImpl<
48
+
$Res,
49
+
$Val extends CreateFollowResponse
50
+
>
51
+
implements $CreateFollowResponseCopyWith<$Res> {
52
+
_$CreateFollowResponseCopyWithImpl(this._value, this._then);
53
+
54
+
// ignore: unused_field
55
+
final $Val _value;
56
+
// ignore: unused_field
57
+
final $Res Function($Val) _then;
58
+
59
+
/// Create a copy of CreateFollowResponse
60
+
/// with the given fields replaced by the non-null parameter values.
61
+
@pragma('vm:prefer-inline')
62
+
@override
63
+
$Res call({Object? followUri = null}) {
64
+
return _then(
65
+
_value.copyWith(
66
+
followUri: null == followUri
67
+
? _value.followUri
68
+
: followUri // ignore: cast_nullable_to_non_nullable
69
+
as String,
70
+
)
71
+
as $Val,
72
+
);
73
+
}
74
+
}
75
+
76
+
/// @nodoc
77
+
abstract class _$$CreateFollowResponseImplCopyWith<$Res>
78
+
implements $CreateFollowResponseCopyWith<$Res> {
79
+
factory _$$CreateFollowResponseImplCopyWith(
80
+
_$CreateFollowResponseImpl value,
81
+
$Res Function(_$CreateFollowResponseImpl) then,
82
+
) = __$$CreateFollowResponseImplCopyWithImpl<$Res>;
83
+
@override
84
+
@useResult
85
+
$Res call({String followUri});
86
+
}
87
+
88
+
/// @nodoc
89
+
class __$$CreateFollowResponseImplCopyWithImpl<$Res>
90
+
extends _$CreateFollowResponseCopyWithImpl<$Res, _$CreateFollowResponseImpl>
91
+
implements _$$CreateFollowResponseImplCopyWith<$Res> {
92
+
__$$CreateFollowResponseImplCopyWithImpl(
93
+
_$CreateFollowResponseImpl _value,
94
+
$Res Function(_$CreateFollowResponseImpl) _then,
95
+
) : super(_value, _then);
96
+
97
+
/// Create a copy of CreateFollowResponse
98
+
/// with the given fields replaced by the non-null parameter values.
99
+
@pragma('vm:prefer-inline')
100
+
@override
101
+
$Res call({Object? followUri = null}) {
102
+
return _then(
103
+
_$CreateFollowResponseImpl(
104
+
followUri: null == followUri
105
+
? _value.followUri
106
+
: followUri // ignore: cast_nullable_to_non_nullable
107
+
as String,
108
+
),
109
+
);
110
+
}
111
+
}
112
+
113
+
/// @nodoc
114
+
@JsonSerializable()
115
+
class _$CreateFollowResponseImpl implements _CreateFollowResponse {
116
+
const _$CreateFollowResponseImpl({required this.followUri});
117
+
118
+
factory _$CreateFollowResponseImpl.fromJson(Map<String, dynamic> json) =>
119
+
_$$CreateFollowResponseImplFromJson(json);
120
+
121
+
@override
122
+
final String followUri;
123
+
124
+
@override
125
+
String toString() {
126
+
return 'CreateFollowResponse(followUri: $followUri)';
127
+
}
128
+
129
+
@override
130
+
bool operator ==(Object other) {
131
+
return identical(this, other) ||
132
+
(other.runtimeType == runtimeType &&
133
+
other is _$CreateFollowResponseImpl &&
134
+
(identical(other.followUri, followUri) ||
135
+
other.followUri == followUri));
136
+
}
137
+
138
+
@JsonKey(includeFromJson: false, includeToJson: false)
139
+
@override
140
+
int get hashCode => Object.hash(runtimeType, followUri);
141
+
142
+
/// Create a copy of CreateFollowResponse
143
+
/// with the given fields replaced by the non-null parameter values.
144
+
@JsonKey(includeFromJson: false, includeToJson: false)
145
+
@override
146
+
@pragma('vm:prefer-inline')
147
+
_$$CreateFollowResponseImplCopyWith<_$CreateFollowResponseImpl>
148
+
get copyWith =>
149
+
__$$CreateFollowResponseImplCopyWithImpl<_$CreateFollowResponseImpl>(
150
+
this,
151
+
_$identity,
152
+
);
153
+
154
+
@override
155
+
Map<String, dynamic> toJson() {
156
+
return _$$CreateFollowResponseImplToJson(this);
157
+
}
158
+
}
159
+
160
+
abstract class _CreateFollowResponse implements CreateFollowResponse {
161
+
const factory _CreateFollowResponse({required final String followUri}) =
162
+
_$CreateFollowResponseImpl;
163
+
164
+
factory _CreateFollowResponse.fromJson(Map<String, dynamic> json) =
165
+
_$CreateFollowResponseImpl.fromJson;
166
+
167
+
@override
168
+
String get followUri;
169
+
170
+
/// Create a copy of CreateFollowResponse
171
+
/// with the given fields replaced by the non-null parameter values.
172
+
@override
173
+
@JsonKey(includeFromJson: false, includeToJson: false)
174
+
_$$CreateFollowResponseImplCopyWith<_$CreateFollowResponseImpl>
175
+
get copyWith => throw _privateConstructorUsedError;
176
+
}
+15
lib/models/procedures/create_follow_response.g.dart
+15
lib/models/procedures/create_follow_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_follow_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateFollowResponseImpl _$$CreateFollowResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateFollowResponseImpl(followUri: json['followUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateFollowResponseImplToJson(
14
+
_$CreateFollowResponseImpl instance,
15
+
) => <String, dynamic>{'followUri': instance.followUri};
+18
lib/models/procedures/create_gallery_item_request.dart
+18
lib/models/procedures/create_gallery_item_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_gallery_item_request.freezed.dart';
4
+
part 'create_gallery_item_request.g.dart';
5
+
6
+
/// Request model for creating a gallery item.
7
+
/// See lexicon: social.grain.gallery.createItem
8
+
@freezed
9
+
class CreateGalleryItemRequest with _$CreateGalleryItemRequest {
10
+
const factory CreateGalleryItemRequest({
11
+
required String galleryUri,
12
+
required String photoUri,
13
+
required int position,
14
+
}) = _CreateGalleryItemRequest;
15
+
16
+
factory CreateGalleryItemRequest.fromJson(Map<String, dynamic> json) =>
17
+
_$CreateGalleryItemRequestFromJson(json);
18
+
}
+226
lib/models/procedures/create_gallery_item_request.freezed.dart
+226
lib/models/procedures/create_gallery_item_request.freezed.dart
···
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_gallery_item_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
+
CreateGalleryItemRequest _$CreateGalleryItemRequestFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateGalleryItemRequest.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateGalleryItemRequest {
26
+
String get galleryUri => throw _privateConstructorUsedError;
27
+
String get photoUri => throw _privateConstructorUsedError;
28
+
int get position => throw _privateConstructorUsedError;
29
+
30
+
/// Serializes this CreateGalleryItemRequest to a JSON map.
31
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
32
+
33
+
/// Create a copy of CreateGalleryItemRequest
34
+
/// with the given fields replaced by the non-null parameter values.
35
+
@JsonKey(includeFromJson: false, includeToJson: false)
36
+
$CreateGalleryItemRequestCopyWith<CreateGalleryItemRequest> get copyWith =>
37
+
throw _privateConstructorUsedError;
38
+
}
39
+
40
+
/// @nodoc
41
+
abstract class $CreateGalleryItemRequestCopyWith<$Res> {
42
+
factory $CreateGalleryItemRequestCopyWith(
43
+
CreateGalleryItemRequest value,
44
+
$Res Function(CreateGalleryItemRequest) then,
45
+
) = _$CreateGalleryItemRequestCopyWithImpl<$Res, CreateGalleryItemRequest>;
46
+
@useResult
47
+
$Res call({String galleryUri, String photoUri, int position});
48
+
}
49
+
50
+
/// @nodoc
51
+
class _$CreateGalleryItemRequestCopyWithImpl<
52
+
$Res,
53
+
$Val extends CreateGalleryItemRequest
54
+
>
55
+
implements $CreateGalleryItemRequestCopyWith<$Res> {
56
+
_$CreateGalleryItemRequestCopyWithImpl(this._value, this._then);
57
+
58
+
// ignore: unused_field
59
+
final $Val _value;
60
+
// ignore: unused_field
61
+
final $Res Function($Val) _then;
62
+
63
+
/// Create a copy of CreateGalleryItemRequest
64
+
/// with the given fields replaced by the non-null parameter values.
65
+
@pragma('vm:prefer-inline')
66
+
@override
67
+
$Res call({
68
+
Object? galleryUri = null,
69
+
Object? photoUri = null,
70
+
Object? position = null,
71
+
}) {
72
+
return _then(
73
+
_value.copyWith(
74
+
galleryUri: null == galleryUri
75
+
? _value.galleryUri
76
+
: galleryUri // ignore: cast_nullable_to_non_nullable
77
+
as String,
78
+
photoUri: null == photoUri
79
+
? _value.photoUri
80
+
: photoUri // ignore: cast_nullable_to_non_nullable
81
+
as String,
82
+
position: null == position
83
+
? _value.position
84
+
: position // ignore: cast_nullable_to_non_nullable
85
+
as int,
86
+
)
87
+
as $Val,
88
+
);
89
+
}
90
+
}
91
+
92
+
/// @nodoc
93
+
abstract class _$$CreateGalleryItemRequestImplCopyWith<$Res>
94
+
implements $CreateGalleryItemRequestCopyWith<$Res> {
95
+
factory _$$CreateGalleryItemRequestImplCopyWith(
96
+
_$CreateGalleryItemRequestImpl value,
97
+
$Res Function(_$CreateGalleryItemRequestImpl) then,
98
+
) = __$$CreateGalleryItemRequestImplCopyWithImpl<$Res>;
99
+
@override
100
+
@useResult
101
+
$Res call({String galleryUri, String photoUri, int position});
102
+
}
103
+
104
+
/// @nodoc
105
+
class __$$CreateGalleryItemRequestImplCopyWithImpl<$Res>
106
+
extends
107
+
_$CreateGalleryItemRequestCopyWithImpl<
108
+
$Res,
109
+
_$CreateGalleryItemRequestImpl
110
+
>
111
+
implements _$$CreateGalleryItemRequestImplCopyWith<$Res> {
112
+
__$$CreateGalleryItemRequestImplCopyWithImpl(
113
+
_$CreateGalleryItemRequestImpl _value,
114
+
$Res Function(_$CreateGalleryItemRequestImpl) _then,
115
+
) : super(_value, _then);
116
+
117
+
/// Create a copy of CreateGalleryItemRequest
118
+
/// with the given fields replaced by the non-null parameter values.
119
+
@pragma('vm:prefer-inline')
120
+
@override
121
+
$Res call({
122
+
Object? galleryUri = null,
123
+
Object? photoUri = null,
124
+
Object? position = null,
125
+
}) {
126
+
return _then(
127
+
_$CreateGalleryItemRequestImpl(
128
+
galleryUri: null == galleryUri
129
+
? _value.galleryUri
130
+
: galleryUri // ignore: cast_nullable_to_non_nullable
131
+
as String,
132
+
photoUri: null == photoUri
133
+
? _value.photoUri
134
+
: photoUri // ignore: cast_nullable_to_non_nullable
135
+
as String,
136
+
position: null == position
137
+
? _value.position
138
+
: position // ignore: cast_nullable_to_non_nullable
139
+
as int,
140
+
),
141
+
);
142
+
}
143
+
}
144
+
145
+
/// @nodoc
146
+
@JsonSerializable()
147
+
class _$CreateGalleryItemRequestImpl implements _CreateGalleryItemRequest {
148
+
const _$CreateGalleryItemRequestImpl({
149
+
required this.galleryUri,
150
+
required this.photoUri,
151
+
required this.position,
152
+
});
153
+
154
+
factory _$CreateGalleryItemRequestImpl.fromJson(Map<String, dynamic> json) =>
155
+
_$$CreateGalleryItemRequestImplFromJson(json);
156
+
157
+
@override
158
+
final String galleryUri;
159
+
@override
160
+
final String photoUri;
161
+
@override
162
+
final int position;
163
+
164
+
@override
165
+
String toString() {
166
+
return 'CreateGalleryItemRequest(galleryUri: $galleryUri, photoUri: $photoUri, position: $position)';
167
+
}
168
+
169
+
@override
170
+
bool operator ==(Object other) {
171
+
return identical(this, other) ||
172
+
(other.runtimeType == runtimeType &&
173
+
other is _$CreateGalleryItemRequestImpl &&
174
+
(identical(other.galleryUri, galleryUri) ||
175
+
other.galleryUri == galleryUri) &&
176
+
(identical(other.photoUri, photoUri) ||
177
+
other.photoUri == photoUri) &&
178
+
(identical(other.position, position) ||
179
+
other.position == position));
180
+
}
181
+
182
+
@JsonKey(includeFromJson: false, includeToJson: false)
183
+
@override
184
+
int get hashCode => Object.hash(runtimeType, galleryUri, photoUri, position);
185
+
186
+
/// Create a copy of CreateGalleryItemRequest
187
+
/// with the given fields replaced by the non-null parameter values.
188
+
@JsonKey(includeFromJson: false, includeToJson: false)
189
+
@override
190
+
@pragma('vm:prefer-inline')
191
+
_$$CreateGalleryItemRequestImplCopyWith<_$CreateGalleryItemRequestImpl>
192
+
get copyWith =>
193
+
__$$CreateGalleryItemRequestImplCopyWithImpl<
194
+
_$CreateGalleryItemRequestImpl
195
+
>(this, _$identity);
196
+
197
+
@override
198
+
Map<String, dynamic> toJson() {
199
+
return _$$CreateGalleryItemRequestImplToJson(this);
200
+
}
201
+
}
202
+
203
+
abstract class _CreateGalleryItemRequest implements CreateGalleryItemRequest {
204
+
const factory _CreateGalleryItemRequest({
205
+
required final String galleryUri,
206
+
required final String photoUri,
207
+
required final int position,
208
+
}) = _$CreateGalleryItemRequestImpl;
209
+
210
+
factory _CreateGalleryItemRequest.fromJson(Map<String, dynamic> json) =
211
+
_$CreateGalleryItemRequestImpl.fromJson;
212
+
213
+
@override
214
+
String get galleryUri;
215
+
@override
216
+
String get photoUri;
217
+
@override
218
+
int get position;
219
+
220
+
/// Create a copy of CreateGalleryItemRequest
221
+
/// with the given fields replaced by the non-null parameter values.
222
+
@override
223
+
@JsonKey(includeFromJson: false, includeToJson: false)
224
+
_$$CreateGalleryItemRequestImplCopyWith<_$CreateGalleryItemRequestImpl>
225
+
get copyWith => throw _privateConstructorUsedError;
226
+
}
+23
lib/models/procedures/create_gallery_item_request.g.dart
+23
lib/models/procedures/create_gallery_item_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_gallery_item_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateGalleryItemRequestImpl _$$CreateGalleryItemRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateGalleryItemRequestImpl(
12
+
galleryUri: json['galleryUri'] as String,
13
+
photoUri: json['photoUri'] as String,
14
+
position: (json['position'] as num).toInt(),
15
+
);
16
+
17
+
Map<String, dynamic> _$$CreateGalleryItemRequestImplToJson(
18
+
_$CreateGalleryItemRequestImpl instance,
19
+
) => <String, dynamic>{
20
+
'galleryUri': instance.galleryUri,
21
+
'photoUri': instance.photoUri,
22
+
'position': instance.position,
23
+
};
+14
lib/models/procedures/create_gallery_item_response.dart
+14
lib/models/procedures/create_gallery_item_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_gallery_item_response.freezed.dart';
4
+
part 'create_gallery_item_response.g.dart';
5
+
6
+
/// Response model for creating a gallery item.
7
+
/// See lexicon: social.grain.gallery.createItem
8
+
@freezed
9
+
class CreateGalleryItemResponse with _$CreateGalleryItemResponse {
10
+
const factory CreateGalleryItemResponse({required String itemUri}) = _CreateGalleryItemResponse;
11
+
12
+
factory CreateGalleryItemResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$CreateGalleryItemResponseFromJson(json);
14
+
}
+180
lib/models/procedures/create_gallery_item_response.freezed.dart
+180
lib/models/procedures/create_gallery_item_response.freezed.dart
···
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_gallery_item_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
+
CreateGalleryItemResponse _$CreateGalleryItemResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateGalleryItemResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateGalleryItemResponse {
26
+
String get itemUri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this CreateGalleryItemResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of CreateGalleryItemResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$CreateGalleryItemResponseCopyWith<CreateGalleryItemResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $CreateGalleryItemResponseCopyWith<$Res> {
40
+
factory $CreateGalleryItemResponseCopyWith(
41
+
CreateGalleryItemResponse value,
42
+
$Res Function(CreateGalleryItemResponse) then,
43
+
) = _$CreateGalleryItemResponseCopyWithImpl<$Res, CreateGalleryItemResponse>;
44
+
@useResult
45
+
$Res call({String itemUri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$CreateGalleryItemResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends CreateGalleryItemResponse
52
+
>
53
+
implements $CreateGalleryItemResponseCopyWith<$Res> {
54
+
_$CreateGalleryItemResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of CreateGalleryItemResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? itemUri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
itemUri: null == itemUri
69
+
? _value.itemUri
70
+
: itemUri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$CreateGalleryItemResponseImplCopyWith<$Res>
80
+
implements $CreateGalleryItemResponseCopyWith<$Res> {
81
+
factory _$$CreateGalleryItemResponseImplCopyWith(
82
+
_$CreateGalleryItemResponseImpl value,
83
+
$Res Function(_$CreateGalleryItemResponseImpl) then,
84
+
) = __$$CreateGalleryItemResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String itemUri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$CreateGalleryItemResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$CreateGalleryItemResponseCopyWithImpl<
94
+
$Res,
95
+
_$CreateGalleryItemResponseImpl
96
+
>
97
+
implements _$$CreateGalleryItemResponseImplCopyWith<$Res> {
98
+
__$$CreateGalleryItemResponseImplCopyWithImpl(
99
+
_$CreateGalleryItemResponseImpl _value,
100
+
$Res Function(_$CreateGalleryItemResponseImpl) _then,
101
+
) : super(_value, _then);
102
+
103
+
/// Create a copy of CreateGalleryItemResponse
104
+
/// with the given fields replaced by the non-null parameter values.
105
+
@pragma('vm:prefer-inline')
106
+
@override
107
+
$Res call({Object? itemUri = null}) {
108
+
return _then(
109
+
_$CreateGalleryItemResponseImpl(
110
+
itemUri: null == itemUri
111
+
? _value.itemUri
112
+
: itemUri // ignore: cast_nullable_to_non_nullable
113
+
as String,
114
+
),
115
+
);
116
+
}
117
+
}
118
+
119
+
/// @nodoc
120
+
@JsonSerializable()
121
+
class _$CreateGalleryItemResponseImpl implements _CreateGalleryItemResponse {
122
+
const _$CreateGalleryItemResponseImpl({required this.itemUri});
123
+
124
+
factory _$CreateGalleryItemResponseImpl.fromJson(Map<String, dynamic> json) =>
125
+
_$$CreateGalleryItemResponseImplFromJson(json);
126
+
127
+
@override
128
+
final String itemUri;
129
+
130
+
@override
131
+
String toString() {
132
+
return 'CreateGalleryItemResponse(itemUri: $itemUri)';
133
+
}
134
+
135
+
@override
136
+
bool operator ==(Object other) {
137
+
return identical(this, other) ||
138
+
(other.runtimeType == runtimeType &&
139
+
other is _$CreateGalleryItemResponseImpl &&
140
+
(identical(other.itemUri, itemUri) || other.itemUri == itemUri));
141
+
}
142
+
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
int get hashCode => Object.hash(runtimeType, itemUri);
146
+
147
+
/// Create a copy of CreateGalleryItemResponse
148
+
/// with the given fields replaced by the non-null parameter values.
149
+
@JsonKey(includeFromJson: false, includeToJson: false)
150
+
@override
151
+
@pragma('vm:prefer-inline')
152
+
_$$CreateGalleryItemResponseImplCopyWith<_$CreateGalleryItemResponseImpl>
153
+
get copyWith =>
154
+
__$$CreateGalleryItemResponseImplCopyWithImpl<
155
+
_$CreateGalleryItemResponseImpl
156
+
>(this, _$identity);
157
+
158
+
@override
159
+
Map<String, dynamic> toJson() {
160
+
return _$$CreateGalleryItemResponseImplToJson(this);
161
+
}
162
+
}
163
+
164
+
abstract class _CreateGalleryItemResponse implements CreateGalleryItemResponse {
165
+
const factory _CreateGalleryItemResponse({required final String itemUri}) =
166
+
_$CreateGalleryItemResponseImpl;
167
+
168
+
factory _CreateGalleryItemResponse.fromJson(Map<String, dynamic> json) =
169
+
_$CreateGalleryItemResponseImpl.fromJson;
170
+
171
+
@override
172
+
String get itemUri;
173
+
174
+
/// Create a copy of CreateGalleryItemResponse
175
+
/// with the given fields replaced by the non-null parameter values.
176
+
@override
177
+
@JsonKey(includeFromJson: false, includeToJson: false)
178
+
_$$CreateGalleryItemResponseImplCopyWith<_$CreateGalleryItemResponseImpl>
179
+
get copyWith => throw _privateConstructorUsedError;
180
+
}
+15
lib/models/procedures/create_gallery_item_response.g.dart
+15
lib/models/procedures/create_gallery_item_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_gallery_item_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateGalleryItemResponseImpl _$$CreateGalleryItemResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateGalleryItemResponseImpl(itemUri: json['itemUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateGalleryItemResponseImplToJson(
14
+
_$CreateGalleryItemResponseImpl instance,
15
+
) => <String, dynamic>{'itemUri': instance.itemUri};
+15
lib/models/procedures/create_gallery_request.dart
+15
lib/models/procedures/create_gallery_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_gallery_request.freezed.dart';
4
+
part 'create_gallery_request.g.dart';
5
+
6
+
/// Request model for creating a gallery.
7
+
/// See lexicon: social.grain.gallery.createGallery
8
+
@freezed
9
+
class CreateGalleryRequest with _$CreateGalleryRequest {
10
+
const factory CreateGalleryRequest({required String title, String? description}) =
11
+
_CreateGalleryRequest;
12
+
13
+
factory CreateGalleryRequest.fromJson(Map<String, dynamic> json) =>
14
+
_$CreateGalleryRequestFromJson(json);
15
+
}
+192
lib/models/procedures/create_gallery_request.freezed.dart
+192
lib/models/procedures/create_gallery_request.freezed.dart
···
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_gallery_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
+
CreateGalleryRequest _$CreateGalleryRequestFromJson(Map<String, dynamic> json) {
19
+
return _CreateGalleryRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$CreateGalleryRequest {
24
+
String get title => throw _privateConstructorUsedError;
25
+
String? get description => throw _privateConstructorUsedError;
26
+
27
+
/// Serializes this CreateGalleryRequest to a JSON map.
28
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
29
+
30
+
/// Create a copy of CreateGalleryRequest
31
+
/// with the given fields replaced by the non-null parameter values.
32
+
@JsonKey(includeFromJson: false, includeToJson: false)
33
+
$CreateGalleryRequestCopyWith<CreateGalleryRequest> get copyWith =>
34
+
throw _privateConstructorUsedError;
35
+
}
36
+
37
+
/// @nodoc
38
+
abstract class $CreateGalleryRequestCopyWith<$Res> {
39
+
factory $CreateGalleryRequestCopyWith(
40
+
CreateGalleryRequest value,
41
+
$Res Function(CreateGalleryRequest) then,
42
+
) = _$CreateGalleryRequestCopyWithImpl<$Res, CreateGalleryRequest>;
43
+
@useResult
44
+
$Res call({String title, String? description});
45
+
}
46
+
47
+
/// @nodoc
48
+
class _$CreateGalleryRequestCopyWithImpl<
49
+
$Res,
50
+
$Val extends CreateGalleryRequest
51
+
>
52
+
implements $CreateGalleryRequestCopyWith<$Res> {
53
+
_$CreateGalleryRequestCopyWithImpl(this._value, this._then);
54
+
55
+
// ignore: unused_field
56
+
final $Val _value;
57
+
// ignore: unused_field
58
+
final $Res Function($Val) _then;
59
+
60
+
/// Create a copy of CreateGalleryRequest
61
+
/// with the given fields replaced by the non-null parameter values.
62
+
@pragma('vm:prefer-inline')
63
+
@override
64
+
$Res call({Object? title = null, Object? description = freezed}) {
65
+
return _then(
66
+
_value.copyWith(
67
+
title: null == title
68
+
? _value.title
69
+
: title // ignore: cast_nullable_to_non_nullable
70
+
as String,
71
+
description: freezed == description
72
+
? _value.description
73
+
: description // ignore: cast_nullable_to_non_nullable
74
+
as String?,
75
+
)
76
+
as $Val,
77
+
);
78
+
}
79
+
}
80
+
81
+
/// @nodoc
82
+
abstract class _$$CreateGalleryRequestImplCopyWith<$Res>
83
+
implements $CreateGalleryRequestCopyWith<$Res> {
84
+
factory _$$CreateGalleryRequestImplCopyWith(
85
+
_$CreateGalleryRequestImpl value,
86
+
$Res Function(_$CreateGalleryRequestImpl) then,
87
+
) = __$$CreateGalleryRequestImplCopyWithImpl<$Res>;
88
+
@override
89
+
@useResult
90
+
$Res call({String title, String? description});
91
+
}
92
+
93
+
/// @nodoc
94
+
class __$$CreateGalleryRequestImplCopyWithImpl<$Res>
95
+
extends _$CreateGalleryRequestCopyWithImpl<$Res, _$CreateGalleryRequestImpl>
96
+
implements _$$CreateGalleryRequestImplCopyWith<$Res> {
97
+
__$$CreateGalleryRequestImplCopyWithImpl(
98
+
_$CreateGalleryRequestImpl _value,
99
+
$Res Function(_$CreateGalleryRequestImpl) _then,
100
+
) : super(_value, _then);
101
+
102
+
/// Create a copy of CreateGalleryRequest
103
+
/// with the given fields replaced by the non-null parameter values.
104
+
@pragma('vm:prefer-inline')
105
+
@override
106
+
$Res call({Object? title = null, Object? description = freezed}) {
107
+
return _then(
108
+
_$CreateGalleryRequestImpl(
109
+
title: null == title
110
+
? _value.title
111
+
: title // ignore: cast_nullable_to_non_nullable
112
+
as String,
113
+
description: freezed == description
114
+
? _value.description
115
+
: description // ignore: cast_nullable_to_non_nullable
116
+
as String?,
117
+
),
118
+
);
119
+
}
120
+
}
121
+
122
+
/// @nodoc
123
+
@JsonSerializable()
124
+
class _$CreateGalleryRequestImpl implements _CreateGalleryRequest {
125
+
const _$CreateGalleryRequestImpl({required this.title, this.description});
126
+
127
+
factory _$CreateGalleryRequestImpl.fromJson(Map<String, dynamic> json) =>
128
+
_$$CreateGalleryRequestImplFromJson(json);
129
+
130
+
@override
131
+
final String title;
132
+
@override
133
+
final String? description;
134
+
135
+
@override
136
+
String toString() {
137
+
return 'CreateGalleryRequest(title: $title, description: $description)';
138
+
}
139
+
140
+
@override
141
+
bool operator ==(Object other) {
142
+
return identical(this, other) ||
143
+
(other.runtimeType == runtimeType &&
144
+
other is _$CreateGalleryRequestImpl &&
145
+
(identical(other.title, title) || other.title == title) &&
146
+
(identical(other.description, description) ||
147
+
other.description == description));
148
+
}
149
+
150
+
@JsonKey(includeFromJson: false, includeToJson: false)
151
+
@override
152
+
int get hashCode => Object.hash(runtimeType, title, description);
153
+
154
+
/// Create a copy of CreateGalleryRequest
155
+
/// with the given fields replaced by the non-null parameter values.
156
+
@JsonKey(includeFromJson: false, includeToJson: false)
157
+
@override
158
+
@pragma('vm:prefer-inline')
159
+
_$$CreateGalleryRequestImplCopyWith<_$CreateGalleryRequestImpl>
160
+
get copyWith =>
161
+
__$$CreateGalleryRequestImplCopyWithImpl<_$CreateGalleryRequestImpl>(
162
+
this,
163
+
_$identity,
164
+
);
165
+
166
+
@override
167
+
Map<String, dynamic> toJson() {
168
+
return _$$CreateGalleryRequestImplToJson(this);
169
+
}
170
+
}
171
+
172
+
abstract class _CreateGalleryRequest implements CreateGalleryRequest {
173
+
const factory _CreateGalleryRequest({
174
+
required final String title,
175
+
final String? description,
176
+
}) = _$CreateGalleryRequestImpl;
177
+
178
+
factory _CreateGalleryRequest.fromJson(Map<String, dynamic> json) =
179
+
_$CreateGalleryRequestImpl.fromJson;
180
+
181
+
@override
182
+
String get title;
183
+
@override
184
+
String? get description;
185
+
186
+
/// Create a copy of CreateGalleryRequest
187
+
/// with the given fields replaced by the non-null parameter values.
188
+
@override
189
+
@JsonKey(includeFromJson: false, includeToJson: false)
190
+
_$$CreateGalleryRequestImplCopyWith<_$CreateGalleryRequestImpl>
191
+
get copyWith => throw _privateConstructorUsedError;
192
+
}
+21
lib/models/procedures/create_gallery_request.g.dart
+21
lib/models/procedures/create_gallery_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_gallery_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateGalleryRequestImpl _$$CreateGalleryRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateGalleryRequestImpl(
12
+
title: json['title'] as String,
13
+
description: json['description'] as String?,
14
+
);
15
+
16
+
Map<String, dynamic> _$$CreateGalleryRequestImplToJson(
17
+
_$CreateGalleryRequestImpl instance,
18
+
) => <String, dynamic>{
19
+
'title': instance.title,
20
+
'description': instance.description,
21
+
};
+14
lib/models/procedures/create_gallery_response.dart
+14
lib/models/procedures/create_gallery_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'create_gallery_response.freezed.dart';
4
+
part 'create_gallery_response.g.dart';
5
+
6
+
/// Response model for creating a gallery.
7
+
/// See lexicon: social.grain.gallery.createGallery
8
+
@freezed
9
+
class CreateGalleryResponse with _$CreateGalleryResponse {
10
+
const factory CreateGalleryResponse({required String galleryUri}) = _CreateGalleryResponse;
11
+
12
+
factory CreateGalleryResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$CreateGalleryResponseFromJson(json);
14
+
}
+179
lib/models/procedures/create_gallery_response.freezed.dart
+179
lib/models/procedures/create_gallery_response.freezed.dart
···
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_gallery_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
+
CreateGalleryResponse _$CreateGalleryResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _CreateGalleryResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$CreateGalleryResponse {
26
+
String get galleryUri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this CreateGalleryResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of CreateGalleryResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$CreateGalleryResponseCopyWith<CreateGalleryResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $CreateGalleryResponseCopyWith<$Res> {
40
+
factory $CreateGalleryResponseCopyWith(
41
+
CreateGalleryResponse value,
42
+
$Res Function(CreateGalleryResponse) then,
43
+
) = _$CreateGalleryResponseCopyWithImpl<$Res, CreateGalleryResponse>;
44
+
@useResult
45
+
$Res call({String galleryUri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$CreateGalleryResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends CreateGalleryResponse
52
+
>
53
+
implements $CreateGalleryResponseCopyWith<$Res> {
54
+
_$CreateGalleryResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of CreateGalleryResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? galleryUri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
galleryUri: null == galleryUri
69
+
? _value.galleryUri
70
+
: galleryUri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$CreateGalleryResponseImplCopyWith<$Res>
80
+
implements $CreateGalleryResponseCopyWith<$Res> {
81
+
factory _$$CreateGalleryResponseImplCopyWith(
82
+
_$CreateGalleryResponseImpl value,
83
+
$Res Function(_$CreateGalleryResponseImpl) then,
84
+
) = __$$CreateGalleryResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String galleryUri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$CreateGalleryResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$CreateGalleryResponseCopyWithImpl<$Res, _$CreateGalleryResponseImpl>
94
+
implements _$$CreateGalleryResponseImplCopyWith<$Res> {
95
+
__$$CreateGalleryResponseImplCopyWithImpl(
96
+
_$CreateGalleryResponseImpl _value,
97
+
$Res Function(_$CreateGalleryResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of CreateGalleryResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? galleryUri = null}) {
105
+
return _then(
106
+
_$CreateGalleryResponseImpl(
107
+
galleryUri: null == galleryUri
108
+
? _value.galleryUri
109
+
: galleryUri // ignore: cast_nullable_to_non_nullable
110
+
as String,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$CreateGalleryResponseImpl implements _CreateGalleryResponse {
119
+
const _$CreateGalleryResponseImpl({required this.galleryUri});
120
+
121
+
factory _$CreateGalleryResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$CreateGalleryResponseImplFromJson(json);
123
+
124
+
@override
125
+
final String galleryUri;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'CreateGalleryResponse(galleryUri: $galleryUri)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$CreateGalleryResponseImpl &&
137
+
(identical(other.galleryUri, galleryUri) ||
138
+
other.galleryUri == galleryUri));
139
+
}
140
+
141
+
@JsonKey(includeFromJson: false, includeToJson: false)
142
+
@override
143
+
int get hashCode => Object.hash(runtimeType, galleryUri);
144
+
145
+
/// Create a copy of CreateGalleryResponse
146
+
/// with the given fields replaced by the non-null parameter values.
147
+
@JsonKey(includeFromJson: false, includeToJson: false)
148
+
@override
149
+
@pragma('vm:prefer-inline')
150
+
_$$CreateGalleryResponseImplCopyWith<_$CreateGalleryResponseImpl>
151
+
get copyWith =>
152
+
__$$CreateGalleryResponseImplCopyWithImpl<_$CreateGalleryResponseImpl>(
153
+
this,
154
+
_$identity,
155
+
);
156
+
157
+
@override
158
+
Map<String, dynamic> toJson() {
159
+
return _$$CreateGalleryResponseImplToJson(this);
160
+
}
161
+
}
162
+
163
+
abstract class _CreateGalleryResponse implements CreateGalleryResponse {
164
+
const factory _CreateGalleryResponse({required final String galleryUri}) =
165
+
_$CreateGalleryResponseImpl;
166
+
167
+
factory _CreateGalleryResponse.fromJson(Map<String, dynamic> json) =
168
+
_$CreateGalleryResponseImpl.fromJson;
169
+
170
+
@override
171
+
String get galleryUri;
172
+
173
+
/// Create a copy of CreateGalleryResponse
174
+
/// with the given fields replaced by the non-null parameter values.
175
+
@override
176
+
@JsonKey(includeFromJson: false, includeToJson: false)
177
+
_$$CreateGalleryResponseImplCopyWith<_$CreateGalleryResponseImpl>
178
+
get copyWith => throw _privateConstructorUsedError;
179
+
}
+15
lib/models/procedures/create_gallery_response.g.dart
+15
lib/models/procedures/create_gallery_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'create_gallery_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$CreateGalleryResponseImpl _$$CreateGalleryResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$CreateGalleryResponseImpl(galleryUri: json['galleryUri'] as String);
12
+
13
+
Map<String, dynamic> _$$CreateGalleryResponseImplToJson(
14
+
_$CreateGalleryResponseImpl instance,
15
+
) => <String, dynamic>{'galleryUri': instance.galleryUri};
+14
lib/models/procedures/delete_comment_request.dart
+14
lib/models/procedures/delete_comment_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_comment_request.freezed.dart';
4
+
part 'delete_comment_request.g.dart';
5
+
6
+
/// Request model for deleting a comment.
7
+
/// See lexicon: social.grain.comment.deleteComment
8
+
@freezed
9
+
class DeleteCommentRequest with _$DeleteCommentRequest {
10
+
const factory DeleteCommentRequest({required String uri}) = _DeleteCommentRequest;
11
+
12
+
factory DeleteCommentRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteCommentRequestFromJson(json);
14
+
}
+175
lib/models/procedures/delete_comment_request.freezed.dart
+175
lib/models/procedures/delete_comment_request.freezed.dart
···
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 'delete_comment_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
+
DeleteCommentRequest _$DeleteCommentRequestFromJson(Map<String, dynamic> json) {
19
+
return _DeleteCommentRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeleteCommentRequest {
24
+
String get uri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeleteCommentRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeleteCommentRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeleteCommentRequestCopyWith<DeleteCommentRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeleteCommentRequestCopyWith<$Res> {
38
+
factory $DeleteCommentRequestCopyWith(
39
+
DeleteCommentRequest value,
40
+
$Res Function(DeleteCommentRequest) then,
41
+
) = _$DeleteCommentRequestCopyWithImpl<$Res, DeleteCommentRequest>;
42
+
@useResult
43
+
$Res call({String uri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeleteCommentRequestCopyWithImpl<
48
+
$Res,
49
+
$Val extends DeleteCommentRequest
50
+
>
51
+
implements $DeleteCommentRequestCopyWith<$Res> {
52
+
_$DeleteCommentRequestCopyWithImpl(this._value, this._then);
53
+
54
+
// ignore: unused_field
55
+
final $Val _value;
56
+
// ignore: unused_field
57
+
final $Res Function($Val) _then;
58
+
59
+
/// Create a copy of DeleteCommentRequest
60
+
/// with the given fields replaced by the non-null parameter values.
61
+
@pragma('vm:prefer-inline')
62
+
@override
63
+
$Res call({Object? uri = null}) {
64
+
return _then(
65
+
_value.copyWith(
66
+
uri: null == uri
67
+
? _value.uri
68
+
: uri // ignore: cast_nullable_to_non_nullable
69
+
as String,
70
+
)
71
+
as $Val,
72
+
);
73
+
}
74
+
}
75
+
76
+
/// @nodoc
77
+
abstract class _$$DeleteCommentRequestImplCopyWith<$Res>
78
+
implements $DeleteCommentRequestCopyWith<$Res> {
79
+
factory _$$DeleteCommentRequestImplCopyWith(
80
+
_$DeleteCommentRequestImpl value,
81
+
$Res Function(_$DeleteCommentRequestImpl) then,
82
+
) = __$$DeleteCommentRequestImplCopyWithImpl<$Res>;
83
+
@override
84
+
@useResult
85
+
$Res call({String uri});
86
+
}
87
+
88
+
/// @nodoc
89
+
class __$$DeleteCommentRequestImplCopyWithImpl<$Res>
90
+
extends _$DeleteCommentRequestCopyWithImpl<$Res, _$DeleteCommentRequestImpl>
91
+
implements _$$DeleteCommentRequestImplCopyWith<$Res> {
92
+
__$$DeleteCommentRequestImplCopyWithImpl(
93
+
_$DeleteCommentRequestImpl _value,
94
+
$Res Function(_$DeleteCommentRequestImpl) _then,
95
+
) : super(_value, _then);
96
+
97
+
/// Create a copy of DeleteCommentRequest
98
+
/// with the given fields replaced by the non-null parameter values.
99
+
@pragma('vm:prefer-inline')
100
+
@override
101
+
$Res call({Object? uri = null}) {
102
+
return _then(
103
+
_$DeleteCommentRequestImpl(
104
+
uri: null == uri
105
+
? _value.uri
106
+
: uri // ignore: cast_nullable_to_non_nullable
107
+
as String,
108
+
),
109
+
);
110
+
}
111
+
}
112
+
113
+
/// @nodoc
114
+
@JsonSerializable()
115
+
class _$DeleteCommentRequestImpl implements _DeleteCommentRequest {
116
+
const _$DeleteCommentRequestImpl({required this.uri});
117
+
118
+
factory _$DeleteCommentRequestImpl.fromJson(Map<String, dynamic> json) =>
119
+
_$$DeleteCommentRequestImplFromJson(json);
120
+
121
+
@override
122
+
final String uri;
123
+
124
+
@override
125
+
String toString() {
126
+
return 'DeleteCommentRequest(uri: $uri)';
127
+
}
128
+
129
+
@override
130
+
bool operator ==(Object other) {
131
+
return identical(this, other) ||
132
+
(other.runtimeType == runtimeType &&
133
+
other is _$DeleteCommentRequestImpl &&
134
+
(identical(other.uri, uri) || other.uri == uri));
135
+
}
136
+
137
+
@JsonKey(includeFromJson: false, includeToJson: false)
138
+
@override
139
+
int get hashCode => Object.hash(runtimeType, uri);
140
+
141
+
/// Create a copy of DeleteCommentRequest
142
+
/// with the given fields replaced by the non-null parameter values.
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
@pragma('vm:prefer-inline')
146
+
_$$DeleteCommentRequestImplCopyWith<_$DeleteCommentRequestImpl>
147
+
get copyWith =>
148
+
__$$DeleteCommentRequestImplCopyWithImpl<_$DeleteCommentRequestImpl>(
149
+
this,
150
+
_$identity,
151
+
);
152
+
153
+
@override
154
+
Map<String, dynamic> toJson() {
155
+
return _$$DeleteCommentRequestImplToJson(this);
156
+
}
157
+
}
158
+
159
+
abstract class _DeleteCommentRequest implements DeleteCommentRequest {
160
+
const factory _DeleteCommentRequest({required final String uri}) =
161
+
_$DeleteCommentRequestImpl;
162
+
163
+
factory _DeleteCommentRequest.fromJson(Map<String, dynamic> json) =
164
+
_$DeleteCommentRequestImpl.fromJson;
165
+
166
+
@override
167
+
String get uri;
168
+
169
+
/// Create a copy of DeleteCommentRequest
170
+
/// with the given fields replaced by the non-null parameter values.
171
+
@override
172
+
@JsonKey(includeFromJson: false, includeToJson: false)
173
+
_$$DeleteCommentRequestImplCopyWith<_$DeleteCommentRequestImpl>
174
+
get copyWith => throw _privateConstructorUsedError;
175
+
}
+15
lib/models/procedures/delete_comment_request.g.dart
+15
lib/models/procedures/delete_comment_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_comment_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteCommentRequestImpl _$$DeleteCommentRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteCommentRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeleteCommentRequestImplToJson(
14
+
_$DeleteCommentRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+14
lib/models/procedures/delete_comment_response.dart
+14
lib/models/procedures/delete_comment_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_comment_response.freezed.dart';
4
+
part 'delete_comment_response.g.dart';
5
+
6
+
/// Response model for deleting a comment.
7
+
/// See lexicon: social.grain.comment.deleteComment
8
+
@freezed
9
+
class DeleteCommentResponse with _$DeleteCommentResponse {
10
+
const factory DeleteCommentResponse({required bool success}) = _DeleteCommentResponse;
11
+
12
+
factory DeleteCommentResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteCommentResponseFromJson(json);
14
+
}
+178
lib/models/procedures/delete_comment_response.freezed.dart
+178
lib/models/procedures/delete_comment_response.freezed.dart
···
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 'delete_comment_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
+
DeleteCommentResponse _$DeleteCommentResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteCommentResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteCommentResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteCommentResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteCommentResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteCommentResponseCopyWith<DeleteCommentResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteCommentResponseCopyWith<$Res> {
40
+
factory $DeleteCommentResponseCopyWith(
41
+
DeleteCommentResponse value,
42
+
$Res Function(DeleteCommentResponse) then,
43
+
) = _$DeleteCommentResponseCopyWithImpl<$Res, DeleteCommentResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteCommentResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteCommentResponse
52
+
>
53
+
implements $DeleteCommentResponseCopyWith<$Res> {
54
+
_$DeleteCommentResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteCommentResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteCommentResponseImplCopyWith<$Res>
80
+
implements $DeleteCommentResponseCopyWith<$Res> {
81
+
factory _$$DeleteCommentResponseImplCopyWith(
82
+
_$DeleteCommentResponseImpl value,
83
+
$Res Function(_$DeleteCommentResponseImpl) then,
84
+
) = __$$DeleteCommentResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteCommentResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteCommentResponseCopyWithImpl<$Res, _$DeleteCommentResponseImpl>
94
+
implements _$$DeleteCommentResponseImplCopyWith<$Res> {
95
+
__$$DeleteCommentResponseImplCopyWithImpl(
96
+
_$DeleteCommentResponseImpl _value,
97
+
$Res Function(_$DeleteCommentResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of DeleteCommentResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? success = null}) {
105
+
return _then(
106
+
_$DeleteCommentResponseImpl(
107
+
success: null == success
108
+
? _value.success
109
+
: success // ignore: cast_nullable_to_non_nullable
110
+
as bool,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$DeleteCommentResponseImpl implements _DeleteCommentResponse {
119
+
const _$DeleteCommentResponseImpl({required this.success});
120
+
121
+
factory _$DeleteCommentResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$DeleteCommentResponseImplFromJson(json);
123
+
124
+
@override
125
+
final bool success;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'DeleteCommentResponse(success: $success)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$DeleteCommentResponseImpl &&
137
+
(identical(other.success, success) || other.success == success));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, success);
143
+
144
+
/// Create a copy of DeleteCommentResponse
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$DeleteCommentResponseImplCopyWith<_$DeleteCommentResponseImpl>
150
+
get copyWith =>
151
+
__$$DeleteCommentResponseImplCopyWithImpl<_$DeleteCommentResponseImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$DeleteCommentResponseImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _DeleteCommentResponse implements DeleteCommentResponse {
163
+
const factory _DeleteCommentResponse({required final bool success}) =
164
+
_$DeleteCommentResponseImpl;
165
+
166
+
factory _DeleteCommentResponse.fromJson(Map<String, dynamic> json) =
167
+
_$DeleteCommentResponseImpl.fromJson;
168
+
169
+
@override
170
+
bool get success;
171
+
172
+
/// Create a copy of DeleteCommentResponse
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$DeleteCommentResponseImplCopyWith<_$DeleteCommentResponseImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/delete_comment_response.g.dart
+15
lib/models/procedures/delete_comment_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_comment_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteCommentResponseImpl _$$DeleteCommentResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteCommentResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeleteCommentResponseImplToJson(
14
+
_$DeleteCommentResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+14
lib/models/procedures/delete_favorite_request.dart
+14
lib/models/procedures/delete_favorite_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_favorite_request.freezed.dart';
4
+
part 'delete_favorite_request.g.dart';
5
+
6
+
/// Request model for deleting a favorite.
7
+
/// See lexicon: social.grain.favorite.deleteFavorite
8
+
@freezed
9
+
class DeleteFavoriteRequest with _$DeleteFavoriteRequest {
10
+
const factory DeleteFavoriteRequest({required String uri}) = _DeleteFavoriteRequest;
11
+
12
+
factory DeleteFavoriteRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteFavoriteRequestFromJson(json);
14
+
}
+178
lib/models/procedures/delete_favorite_request.freezed.dart
+178
lib/models/procedures/delete_favorite_request.freezed.dart
···
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 'delete_favorite_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
+
DeleteFavoriteRequest _$DeleteFavoriteRequestFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteFavoriteRequest.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteFavoriteRequest {
26
+
String get uri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteFavoriteRequest to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteFavoriteRequest
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteFavoriteRequestCopyWith<DeleteFavoriteRequest> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteFavoriteRequestCopyWith<$Res> {
40
+
factory $DeleteFavoriteRequestCopyWith(
41
+
DeleteFavoriteRequest value,
42
+
$Res Function(DeleteFavoriteRequest) then,
43
+
) = _$DeleteFavoriteRequestCopyWithImpl<$Res, DeleteFavoriteRequest>;
44
+
@useResult
45
+
$Res call({String uri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteFavoriteRequestCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteFavoriteRequest
52
+
>
53
+
implements $DeleteFavoriteRequestCopyWith<$Res> {
54
+
_$DeleteFavoriteRequestCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteFavoriteRequest
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? uri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
uri: null == uri
69
+
? _value.uri
70
+
: uri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteFavoriteRequestImplCopyWith<$Res>
80
+
implements $DeleteFavoriteRequestCopyWith<$Res> {
81
+
factory _$$DeleteFavoriteRequestImplCopyWith(
82
+
_$DeleteFavoriteRequestImpl value,
83
+
$Res Function(_$DeleteFavoriteRequestImpl) then,
84
+
) = __$$DeleteFavoriteRequestImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String uri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteFavoriteRequestImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteFavoriteRequestCopyWithImpl<$Res, _$DeleteFavoriteRequestImpl>
94
+
implements _$$DeleteFavoriteRequestImplCopyWith<$Res> {
95
+
__$$DeleteFavoriteRequestImplCopyWithImpl(
96
+
_$DeleteFavoriteRequestImpl _value,
97
+
$Res Function(_$DeleteFavoriteRequestImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of DeleteFavoriteRequest
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? uri = null}) {
105
+
return _then(
106
+
_$DeleteFavoriteRequestImpl(
107
+
uri: null == uri
108
+
? _value.uri
109
+
: uri // ignore: cast_nullable_to_non_nullable
110
+
as String,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$DeleteFavoriteRequestImpl implements _DeleteFavoriteRequest {
119
+
const _$DeleteFavoriteRequestImpl({required this.uri});
120
+
121
+
factory _$DeleteFavoriteRequestImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$DeleteFavoriteRequestImplFromJson(json);
123
+
124
+
@override
125
+
final String uri;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'DeleteFavoriteRequest(uri: $uri)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$DeleteFavoriteRequestImpl &&
137
+
(identical(other.uri, uri) || other.uri == uri));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, uri);
143
+
144
+
/// Create a copy of DeleteFavoriteRequest
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$DeleteFavoriteRequestImplCopyWith<_$DeleteFavoriteRequestImpl>
150
+
get copyWith =>
151
+
__$$DeleteFavoriteRequestImplCopyWithImpl<_$DeleteFavoriteRequestImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$DeleteFavoriteRequestImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _DeleteFavoriteRequest implements DeleteFavoriteRequest {
163
+
const factory _DeleteFavoriteRequest({required final String uri}) =
164
+
_$DeleteFavoriteRequestImpl;
165
+
166
+
factory _DeleteFavoriteRequest.fromJson(Map<String, dynamic> json) =
167
+
_$DeleteFavoriteRequestImpl.fromJson;
168
+
169
+
@override
170
+
String get uri;
171
+
172
+
/// Create a copy of DeleteFavoriteRequest
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$DeleteFavoriteRequestImplCopyWith<_$DeleteFavoriteRequestImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/delete_favorite_request.g.dart
+15
lib/models/procedures/delete_favorite_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_favorite_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteFavoriteRequestImpl _$$DeleteFavoriteRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteFavoriteRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeleteFavoriteRequestImplToJson(
14
+
_$DeleteFavoriteRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+14
lib/models/procedures/delete_favorite_response.dart
+14
lib/models/procedures/delete_favorite_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_favorite_response.freezed.dart';
4
+
part 'delete_favorite_response.g.dart';
5
+
6
+
/// Response model for deleting a favorite.
7
+
/// See lexicon: social.grain.favorite.deleteFavorite
8
+
@freezed
9
+
class DeleteFavoriteResponse with _$DeleteFavoriteResponse {
10
+
const factory DeleteFavoriteResponse({required bool success}) = _DeleteFavoriteResponse;
11
+
12
+
factory DeleteFavoriteResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteFavoriteResponseFromJson(json);
14
+
}
+178
lib/models/procedures/delete_favorite_response.freezed.dart
+178
lib/models/procedures/delete_favorite_response.freezed.dart
···
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 'delete_favorite_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
+
DeleteFavoriteResponse _$DeleteFavoriteResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteFavoriteResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteFavoriteResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteFavoriteResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteFavoriteResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteFavoriteResponseCopyWith<DeleteFavoriteResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteFavoriteResponseCopyWith<$Res> {
40
+
factory $DeleteFavoriteResponseCopyWith(
41
+
DeleteFavoriteResponse value,
42
+
$Res Function(DeleteFavoriteResponse) then,
43
+
) = _$DeleteFavoriteResponseCopyWithImpl<$Res, DeleteFavoriteResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteFavoriteResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteFavoriteResponse
52
+
>
53
+
implements $DeleteFavoriteResponseCopyWith<$Res> {
54
+
_$DeleteFavoriteResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteFavoriteResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteFavoriteResponseImplCopyWith<$Res>
80
+
implements $DeleteFavoriteResponseCopyWith<$Res> {
81
+
factory _$$DeleteFavoriteResponseImplCopyWith(
82
+
_$DeleteFavoriteResponseImpl value,
83
+
$Res Function(_$DeleteFavoriteResponseImpl) then,
84
+
) = __$$DeleteFavoriteResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteFavoriteResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteFavoriteResponseCopyWithImpl<$Res, _$DeleteFavoriteResponseImpl>
94
+
implements _$$DeleteFavoriteResponseImplCopyWith<$Res> {
95
+
__$$DeleteFavoriteResponseImplCopyWithImpl(
96
+
_$DeleteFavoriteResponseImpl _value,
97
+
$Res Function(_$DeleteFavoriteResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of DeleteFavoriteResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? success = null}) {
105
+
return _then(
106
+
_$DeleteFavoriteResponseImpl(
107
+
success: null == success
108
+
? _value.success
109
+
: success // ignore: cast_nullable_to_non_nullable
110
+
as bool,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$DeleteFavoriteResponseImpl implements _DeleteFavoriteResponse {
119
+
const _$DeleteFavoriteResponseImpl({required this.success});
120
+
121
+
factory _$DeleteFavoriteResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$DeleteFavoriteResponseImplFromJson(json);
123
+
124
+
@override
125
+
final bool success;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'DeleteFavoriteResponse(success: $success)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$DeleteFavoriteResponseImpl &&
137
+
(identical(other.success, success) || other.success == success));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, success);
143
+
144
+
/// Create a copy of DeleteFavoriteResponse
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$DeleteFavoriteResponseImplCopyWith<_$DeleteFavoriteResponseImpl>
150
+
get copyWith =>
151
+
__$$DeleteFavoriteResponseImplCopyWithImpl<_$DeleteFavoriteResponseImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$DeleteFavoriteResponseImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _DeleteFavoriteResponse implements DeleteFavoriteResponse {
163
+
const factory _DeleteFavoriteResponse({required final bool success}) =
164
+
_$DeleteFavoriteResponseImpl;
165
+
166
+
factory _DeleteFavoriteResponse.fromJson(Map<String, dynamic> json) =
167
+
_$DeleteFavoriteResponseImpl.fromJson;
168
+
169
+
@override
170
+
bool get success;
171
+
172
+
/// Create a copy of DeleteFavoriteResponse
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$DeleteFavoriteResponseImplCopyWith<_$DeleteFavoriteResponseImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/delete_favorite_response.g.dart
+15
lib/models/procedures/delete_favorite_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_favorite_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteFavoriteResponseImpl _$$DeleteFavoriteResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteFavoriteResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeleteFavoriteResponseImplToJson(
14
+
_$DeleteFavoriteResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+15
lib/models/procedures/delete_follow_request.dart
+15
lib/models/procedures/delete_follow_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_follow_request.freezed.dart';
4
+
part 'delete_follow_request.g.dart';
5
+
6
+
/// Request model for deleting a follow relationship.
7
+
///
8
+
/// [uri] - The URI of the follow relationship to delete.
9
+
@freezed
10
+
class DeleteFollowRequest with _$DeleteFollowRequest {
11
+
const factory DeleteFollowRequest({required String uri}) = _DeleteFollowRequest;
12
+
13
+
factory DeleteFollowRequest.fromJson(Map<String, dynamic> json) =>
14
+
_$DeleteFollowRequestFromJson(json);
15
+
}
+171
lib/models/procedures/delete_follow_request.freezed.dart
+171
lib/models/procedures/delete_follow_request.freezed.dart
···
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 'delete_follow_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
+
DeleteFollowRequest _$DeleteFollowRequestFromJson(Map<String, dynamic> json) {
19
+
return _DeleteFollowRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeleteFollowRequest {
24
+
String get uri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeleteFollowRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeleteFollowRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeleteFollowRequestCopyWith<DeleteFollowRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeleteFollowRequestCopyWith<$Res> {
38
+
factory $DeleteFollowRequestCopyWith(
39
+
DeleteFollowRequest value,
40
+
$Res Function(DeleteFollowRequest) then,
41
+
) = _$DeleteFollowRequestCopyWithImpl<$Res, DeleteFollowRequest>;
42
+
@useResult
43
+
$Res call({String uri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeleteFollowRequestCopyWithImpl<$Res, $Val extends DeleteFollowRequest>
48
+
implements $DeleteFollowRequestCopyWith<$Res> {
49
+
_$DeleteFollowRequestCopyWithImpl(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 DeleteFollowRequest
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? uri = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
uri: null == uri
64
+
? _value.uri
65
+
: uri // ignore: cast_nullable_to_non_nullable
66
+
as String,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$DeleteFollowRequestImplCopyWith<$Res>
75
+
implements $DeleteFollowRequestCopyWith<$Res> {
76
+
factory _$$DeleteFollowRequestImplCopyWith(
77
+
_$DeleteFollowRequestImpl value,
78
+
$Res Function(_$DeleteFollowRequestImpl) then,
79
+
) = __$$DeleteFollowRequestImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({String uri});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$DeleteFollowRequestImplCopyWithImpl<$Res>
87
+
extends _$DeleteFollowRequestCopyWithImpl<$Res, _$DeleteFollowRequestImpl>
88
+
implements _$$DeleteFollowRequestImplCopyWith<$Res> {
89
+
__$$DeleteFollowRequestImplCopyWithImpl(
90
+
_$DeleteFollowRequestImpl _value,
91
+
$Res Function(_$DeleteFollowRequestImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of DeleteFollowRequest
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? uri = null}) {
99
+
return _then(
100
+
_$DeleteFollowRequestImpl(
101
+
uri: null == uri
102
+
? _value.uri
103
+
: uri // ignore: cast_nullable_to_non_nullable
104
+
as String,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$DeleteFollowRequestImpl implements _DeleteFollowRequest {
113
+
const _$DeleteFollowRequestImpl({required this.uri});
114
+
115
+
factory _$DeleteFollowRequestImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$DeleteFollowRequestImplFromJson(json);
117
+
118
+
@override
119
+
final String uri;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'DeleteFollowRequest(uri: $uri)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$DeleteFollowRequestImpl &&
131
+
(identical(other.uri, uri) || other.uri == uri));
132
+
}
133
+
134
+
@JsonKey(includeFromJson: false, includeToJson: false)
135
+
@override
136
+
int get hashCode => Object.hash(runtimeType, uri);
137
+
138
+
/// Create a copy of DeleteFollowRequest
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
+
_$$DeleteFollowRequestImplCopyWith<_$DeleteFollowRequestImpl> get copyWith =>
144
+
__$$DeleteFollowRequestImplCopyWithImpl<_$DeleteFollowRequestImpl>(
145
+
this,
146
+
_$identity,
147
+
);
148
+
149
+
@override
150
+
Map<String, dynamic> toJson() {
151
+
return _$$DeleteFollowRequestImplToJson(this);
152
+
}
153
+
}
154
+
155
+
abstract class _DeleteFollowRequest implements DeleteFollowRequest {
156
+
const factory _DeleteFollowRequest({required final String uri}) =
157
+
_$DeleteFollowRequestImpl;
158
+
159
+
factory _DeleteFollowRequest.fromJson(Map<String, dynamic> json) =
160
+
_$DeleteFollowRequestImpl.fromJson;
161
+
162
+
@override
163
+
String get uri;
164
+
165
+
/// Create a copy of DeleteFollowRequest
166
+
/// with the given fields replaced by the non-null parameter values.
167
+
@override
168
+
@JsonKey(includeFromJson: false, includeToJson: false)
169
+
_$$DeleteFollowRequestImplCopyWith<_$DeleteFollowRequestImpl> get copyWith =>
170
+
throw _privateConstructorUsedError;
171
+
}
+15
lib/models/procedures/delete_follow_request.g.dart
+15
lib/models/procedures/delete_follow_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_follow_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteFollowRequestImpl _$$DeleteFollowRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteFollowRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeleteFollowRequestImplToJson(
14
+
_$DeleteFollowRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+15
lib/models/procedures/delete_follow_response.dart
+15
lib/models/procedures/delete_follow_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_follow_response.freezed.dart';
4
+
part 'delete_follow_response.g.dart';
5
+
6
+
/// Response model for deleting a follow relationship.
7
+
///
8
+
/// [success] - Indicates if the deletion was successful.
9
+
@freezed
10
+
class DeleteFollowResponse with _$DeleteFollowResponse {
11
+
const factory DeleteFollowResponse({required bool success}) = _DeleteFollowResponse;
12
+
13
+
factory DeleteFollowResponse.fromJson(Map<String, dynamic> json) =>
14
+
_$DeleteFollowResponseFromJson(json);
15
+
}
+175
lib/models/procedures/delete_follow_response.freezed.dart
+175
lib/models/procedures/delete_follow_response.freezed.dart
···
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 'delete_follow_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
+
DeleteFollowResponse _$DeleteFollowResponseFromJson(Map<String, dynamic> json) {
19
+
return _DeleteFollowResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeleteFollowResponse {
24
+
bool get success => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeleteFollowResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeleteFollowResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeleteFollowResponseCopyWith<DeleteFollowResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeleteFollowResponseCopyWith<$Res> {
38
+
factory $DeleteFollowResponseCopyWith(
39
+
DeleteFollowResponse value,
40
+
$Res Function(DeleteFollowResponse) then,
41
+
) = _$DeleteFollowResponseCopyWithImpl<$Res, DeleteFollowResponse>;
42
+
@useResult
43
+
$Res call({bool success});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeleteFollowResponseCopyWithImpl<
48
+
$Res,
49
+
$Val extends DeleteFollowResponse
50
+
>
51
+
implements $DeleteFollowResponseCopyWith<$Res> {
52
+
_$DeleteFollowResponseCopyWithImpl(this._value, this._then);
53
+
54
+
// ignore: unused_field
55
+
final $Val _value;
56
+
// ignore: unused_field
57
+
final $Res Function($Val) _then;
58
+
59
+
/// Create a copy of DeleteFollowResponse
60
+
/// with the given fields replaced by the non-null parameter values.
61
+
@pragma('vm:prefer-inline')
62
+
@override
63
+
$Res call({Object? success = null}) {
64
+
return _then(
65
+
_value.copyWith(
66
+
success: null == success
67
+
? _value.success
68
+
: success // ignore: cast_nullable_to_non_nullable
69
+
as bool,
70
+
)
71
+
as $Val,
72
+
);
73
+
}
74
+
}
75
+
76
+
/// @nodoc
77
+
abstract class _$$DeleteFollowResponseImplCopyWith<$Res>
78
+
implements $DeleteFollowResponseCopyWith<$Res> {
79
+
factory _$$DeleteFollowResponseImplCopyWith(
80
+
_$DeleteFollowResponseImpl value,
81
+
$Res Function(_$DeleteFollowResponseImpl) then,
82
+
) = __$$DeleteFollowResponseImplCopyWithImpl<$Res>;
83
+
@override
84
+
@useResult
85
+
$Res call({bool success});
86
+
}
87
+
88
+
/// @nodoc
89
+
class __$$DeleteFollowResponseImplCopyWithImpl<$Res>
90
+
extends _$DeleteFollowResponseCopyWithImpl<$Res, _$DeleteFollowResponseImpl>
91
+
implements _$$DeleteFollowResponseImplCopyWith<$Res> {
92
+
__$$DeleteFollowResponseImplCopyWithImpl(
93
+
_$DeleteFollowResponseImpl _value,
94
+
$Res Function(_$DeleteFollowResponseImpl) _then,
95
+
) : super(_value, _then);
96
+
97
+
/// Create a copy of DeleteFollowResponse
98
+
/// with the given fields replaced by the non-null parameter values.
99
+
@pragma('vm:prefer-inline')
100
+
@override
101
+
$Res call({Object? success = null}) {
102
+
return _then(
103
+
_$DeleteFollowResponseImpl(
104
+
success: null == success
105
+
? _value.success
106
+
: success // ignore: cast_nullable_to_non_nullable
107
+
as bool,
108
+
),
109
+
);
110
+
}
111
+
}
112
+
113
+
/// @nodoc
114
+
@JsonSerializable()
115
+
class _$DeleteFollowResponseImpl implements _DeleteFollowResponse {
116
+
const _$DeleteFollowResponseImpl({required this.success});
117
+
118
+
factory _$DeleteFollowResponseImpl.fromJson(Map<String, dynamic> json) =>
119
+
_$$DeleteFollowResponseImplFromJson(json);
120
+
121
+
@override
122
+
final bool success;
123
+
124
+
@override
125
+
String toString() {
126
+
return 'DeleteFollowResponse(success: $success)';
127
+
}
128
+
129
+
@override
130
+
bool operator ==(Object other) {
131
+
return identical(this, other) ||
132
+
(other.runtimeType == runtimeType &&
133
+
other is _$DeleteFollowResponseImpl &&
134
+
(identical(other.success, success) || other.success == success));
135
+
}
136
+
137
+
@JsonKey(includeFromJson: false, includeToJson: false)
138
+
@override
139
+
int get hashCode => Object.hash(runtimeType, success);
140
+
141
+
/// Create a copy of DeleteFollowResponse
142
+
/// with the given fields replaced by the non-null parameter values.
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
@pragma('vm:prefer-inline')
146
+
_$$DeleteFollowResponseImplCopyWith<_$DeleteFollowResponseImpl>
147
+
get copyWith =>
148
+
__$$DeleteFollowResponseImplCopyWithImpl<_$DeleteFollowResponseImpl>(
149
+
this,
150
+
_$identity,
151
+
);
152
+
153
+
@override
154
+
Map<String, dynamic> toJson() {
155
+
return _$$DeleteFollowResponseImplToJson(this);
156
+
}
157
+
}
158
+
159
+
abstract class _DeleteFollowResponse implements DeleteFollowResponse {
160
+
const factory _DeleteFollowResponse({required final bool success}) =
161
+
_$DeleteFollowResponseImpl;
162
+
163
+
factory _DeleteFollowResponse.fromJson(Map<String, dynamic> json) =
164
+
_$DeleteFollowResponseImpl.fromJson;
165
+
166
+
@override
167
+
bool get success;
168
+
169
+
/// Create a copy of DeleteFollowResponse
170
+
/// with the given fields replaced by the non-null parameter values.
171
+
@override
172
+
@JsonKey(includeFromJson: false, includeToJson: false)
173
+
_$$DeleteFollowResponseImplCopyWith<_$DeleteFollowResponseImpl>
174
+
get copyWith => throw _privateConstructorUsedError;
175
+
}
+15
lib/models/procedures/delete_follow_response.g.dart
+15
lib/models/procedures/delete_follow_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_follow_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteFollowResponseImpl _$$DeleteFollowResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteFollowResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeleteFollowResponseImplToJson(
14
+
_$DeleteFollowResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+14
lib/models/procedures/delete_gallery_item_request.dart
+14
lib/models/procedures/delete_gallery_item_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_gallery_item_request.freezed.dart';
4
+
part 'delete_gallery_item_request.g.dart';
5
+
6
+
/// Request model for deleting a gallery item.
7
+
/// See lexicon: social.grain.gallery.deleteItem
8
+
@freezed
9
+
class DeleteGalleryItemRequest with _$DeleteGalleryItemRequest {
10
+
const factory DeleteGalleryItemRequest({required String uri}) = _DeleteGalleryItemRequest;
11
+
12
+
factory DeleteGalleryItemRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteGalleryItemRequestFromJson(json);
14
+
}
+180
lib/models/procedures/delete_gallery_item_request.freezed.dart
+180
lib/models/procedures/delete_gallery_item_request.freezed.dart
···
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 'delete_gallery_item_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
+
DeleteGalleryItemRequest _$DeleteGalleryItemRequestFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteGalleryItemRequest.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteGalleryItemRequest {
26
+
String get uri => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteGalleryItemRequest to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteGalleryItemRequest
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteGalleryItemRequestCopyWith<DeleteGalleryItemRequest> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteGalleryItemRequestCopyWith<$Res> {
40
+
factory $DeleteGalleryItemRequestCopyWith(
41
+
DeleteGalleryItemRequest value,
42
+
$Res Function(DeleteGalleryItemRequest) then,
43
+
) = _$DeleteGalleryItemRequestCopyWithImpl<$Res, DeleteGalleryItemRequest>;
44
+
@useResult
45
+
$Res call({String uri});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteGalleryItemRequestCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteGalleryItemRequest
52
+
>
53
+
implements $DeleteGalleryItemRequestCopyWith<$Res> {
54
+
_$DeleteGalleryItemRequestCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteGalleryItemRequest
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? uri = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
uri: null == uri
69
+
? _value.uri
70
+
: uri // ignore: cast_nullable_to_non_nullable
71
+
as String,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteGalleryItemRequestImplCopyWith<$Res>
80
+
implements $DeleteGalleryItemRequestCopyWith<$Res> {
81
+
factory _$$DeleteGalleryItemRequestImplCopyWith(
82
+
_$DeleteGalleryItemRequestImpl value,
83
+
$Res Function(_$DeleteGalleryItemRequestImpl) then,
84
+
) = __$$DeleteGalleryItemRequestImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({String uri});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteGalleryItemRequestImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteGalleryItemRequestCopyWithImpl<
94
+
$Res,
95
+
_$DeleteGalleryItemRequestImpl
96
+
>
97
+
implements _$$DeleteGalleryItemRequestImplCopyWith<$Res> {
98
+
__$$DeleteGalleryItemRequestImplCopyWithImpl(
99
+
_$DeleteGalleryItemRequestImpl _value,
100
+
$Res Function(_$DeleteGalleryItemRequestImpl) _then,
101
+
) : super(_value, _then);
102
+
103
+
/// Create a copy of DeleteGalleryItemRequest
104
+
/// with the given fields replaced by the non-null parameter values.
105
+
@pragma('vm:prefer-inline')
106
+
@override
107
+
$Res call({Object? uri = null}) {
108
+
return _then(
109
+
_$DeleteGalleryItemRequestImpl(
110
+
uri: null == uri
111
+
? _value.uri
112
+
: uri // ignore: cast_nullable_to_non_nullable
113
+
as String,
114
+
),
115
+
);
116
+
}
117
+
}
118
+
119
+
/// @nodoc
120
+
@JsonSerializable()
121
+
class _$DeleteGalleryItemRequestImpl implements _DeleteGalleryItemRequest {
122
+
const _$DeleteGalleryItemRequestImpl({required this.uri});
123
+
124
+
factory _$DeleteGalleryItemRequestImpl.fromJson(Map<String, dynamic> json) =>
125
+
_$$DeleteGalleryItemRequestImplFromJson(json);
126
+
127
+
@override
128
+
final String uri;
129
+
130
+
@override
131
+
String toString() {
132
+
return 'DeleteGalleryItemRequest(uri: $uri)';
133
+
}
134
+
135
+
@override
136
+
bool operator ==(Object other) {
137
+
return identical(this, other) ||
138
+
(other.runtimeType == runtimeType &&
139
+
other is _$DeleteGalleryItemRequestImpl &&
140
+
(identical(other.uri, uri) || other.uri == uri));
141
+
}
142
+
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
int get hashCode => Object.hash(runtimeType, uri);
146
+
147
+
/// Create a copy of DeleteGalleryItemRequest
148
+
/// with the given fields replaced by the non-null parameter values.
149
+
@JsonKey(includeFromJson: false, includeToJson: false)
150
+
@override
151
+
@pragma('vm:prefer-inline')
152
+
_$$DeleteGalleryItemRequestImplCopyWith<_$DeleteGalleryItemRequestImpl>
153
+
get copyWith =>
154
+
__$$DeleteGalleryItemRequestImplCopyWithImpl<
155
+
_$DeleteGalleryItemRequestImpl
156
+
>(this, _$identity);
157
+
158
+
@override
159
+
Map<String, dynamic> toJson() {
160
+
return _$$DeleteGalleryItemRequestImplToJson(this);
161
+
}
162
+
}
163
+
164
+
abstract class _DeleteGalleryItemRequest implements DeleteGalleryItemRequest {
165
+
const factory _DeleteGalleryItemRequest({required final String uri}) =
166
+
_$DeleteGalleryItemRequestImpl;
167
+
168
+
factory _DeleteGalleryItemRequest.fromJson(Map<String, dynamic> json) =
169
+
_$DeleteGalleryItemRequestImpl.fromJson;
170
+
171
+
@override
172
+
String get uri;
173
+
174
+
/// Create a copy of DeleteGalleryItemRequest
175
+
/// with the given fields replaced by the non-null parameter values.
176
+
@override
177
+
@JsonKey(includeFromJson: false, includeToJson: false)
178
+
_$$DeleteGalleryItemRequestImplCopyWith<_$DeleteGalleryItemRequestImpl>
179
+
get copyWith => throw _privateConstructorUsedError;
180
+
}
+15
lib/models/procedures/delete_gallery_item_request.g.dart
+15
lib/models/procedures/delete_gallery_item_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_gallery_item_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteGalleryItemRequestImpl _$$DeleteGalleryItemRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteGalleryItemRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeleteGalleryItemRequestImplToJson(
14
+
_$DeleteGalleryItemRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+14
lib/models/procedures/delete_gallery_item_response.dart
+14
lib/models/procedures/delete_gallery_item_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_gallery_item_response.freezed.dart';
4
+
part 'delete_gallery_item_response.g.dart';
5
+
6
+
/// Response model for deleting a gallery item.
7
+
/// See lexicon: social.grain.gallery.deleteItem
8
+
@freezed
9
+
class DeleteGalleryItemResponse with _$DeleteGalleryItemResponse {
10
+
const factory DeleteGalleryItemResponse({required bool success}) = _DeleteGalleryItemResponse;
11
+
12
+
factory DeleteGalleryItemResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteGalleryItemResponseFromJson(json);
14
+
}
+180
lib/models/procedures/delete_gallery_item_response.freezed.dart
+180
lib/models/procedures/delete_gallery_item_response.freezed.dart
···
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 'delete_gallery_item_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
+
DeleteGalleryItemResponse _$DeleteGalleryItemResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteGalleryItemResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteGalleryItemResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteGalleryItemResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteGalleryItemResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteGalleryItemResponseCopyWith<DeleteGalleryItemResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteGalleryItemResponseCopyWith<$Res> {
40
+
factory $DeleteGalleryItemResponseCopyWith(
41
+
DeleteGalleryItemResponse value,
42
+
$Res Function(DeleteGalleryItemResponse) then,
43
+
) = _$DeleteGalleryItemResponseCopyWithImpl<$Res, DeleteGalleryItemResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteGalleryItemResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteGalleryItemResponse
52
+
>
53
+
implements $DeleteGalleryItemResponseCopyWith<$Res> {
54
+
_$DeleteGalleryItemResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteGalleryItemResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteGalleryItemResponseImplCopyWith<$Res>
80
+
implements $DeleteGalleryItemResponseCopyWith<$Res> {
81
+
factory _$$DeleteGalleryItemResponseImplCopyWith(
82
+
_$DeleteGalleryItemResponseImpl value,
83
+
$Res Function(_$DeleteGalleryItemResponseImpl) then,
84
+
) = __$$DeleteGalleryItemResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteGalleryItemResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteGalleryItemResponseCopyWithImpl<
94
+
$Res,
95
+
_$DeleteGalleryItemResponseImpl
96
+
>
97
+
implements _$$DeleteGalleryItemResponseImplCopyWith<$Res> {
98
+
__$$DeleteGalleryItemResponseImplCopyWithImpl(
99
+
_$DeleteGalleryItemResponseImpl _value,
100
+
$Res Function(_$DeleteGalleryItemResponseImpl) _then,
101
+
) : super(_value, _then);
102
+
103
+
/// Create a copy of DeleteGalleryItemResponse
104
+
/// with the given fields replaced by the non-null parameter values.
105
+
@pragma('vm:prefer-inline')
106
+
@override
107
+
$Res call({Object? success = null}) {
108
+
return _then(
109
+
_$DeleteGalleryItemResponseImpl(
110
+
success: null == success
111
+
? _value.success
112
+
: success // ignore: cast_nullable_to_non_nullable
113
+
as bool,
114
+
),
115
+
);
116
+
}
117
+
}
118
+
119
+
/// @nodoc
120
+
@JsonSerializable()
121
+
class _$DeleteGalleryItemResponseImpl implements _DeleteGalleryItemResponse {
122
+
const _$DeleteGalleryItemResponseImpl({required this.success});
123
+
124
+
factory _$DeleteGalleryItemResponseImpl.fromJson(Map<String, dynamic> json) =>
125
+
_$$DeleteGalleryItemResponseImplFromJson(json);
126
+
127
+
@override
128
+
final bool success;
129
+
130
+
@override
131
+
String toString() {
132
+
return 'DeleteGalleryItemResponse(success: $success)';
133
+
}
134
+
135
+
@override
136
+
bool operator ==(Object other) {
137
+
return identical(this, other) ||
138
+
(other.runtimeType == runtimeType &&
139
+
other is _$DeleteGalleryItemResponseImpl &&
140
+
(identical(other.success, success) || other.success == success));
141
+
}
142
+
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
int get hashCode => Object.hash(runtimeType, success);
146
+
147
+
/// Create a copy of DeleteGalleryItemResponse
148
+
/// with the given fields replaced by the non-null parameter values.
149
+
@JsonKey(includeFromJson: false, includeToJson: false)
150
+
@override
151
+
@pragma('vm:prefer-inline')
152
+
_$$DeleteGalleryItemResponseImplCopyWith<_$DeleteGalleryItemResponseImpl>
153
+
get copyWith =>
154
+
__$$DeleteGalleryItemResponseImplCopyWithImpl<
155
+
_$DeleteGalleryItemResponseImpl
156
+
>(this, _$identity);
157
+
158
+
@override
159
+
Map<String, dynamic> toJson() {
160
+
return _$$DeleteGalleryItemResponseImplToJson(this);
161
+
}
162
+
}
163
+
164
+
abstract class _DeleteGalleryItemResponse implements DeleteGalleryItemResponse {
165
+
const factory _DeleteGalleryItemResponse({required final bool success}) =
166
+
_$DeleteGalleryItemResponseImpl;
167
+
168
+
factory _DeleteGalleryItemResponse.fromJson(Map<String, dynamic> json) =
169
+
_$DeleteGalleryItemResponseImpl.fromJson;
170
+
171
+
@override
172
+
bool get success;
173
+
174
+
/// Create a copy of DeleteGalleryItemResponse
175
+
/// with the given fields replaced by the non-null parameter values.
176
+
@override
177
+
@JsonKey(includeFromJson: false, includeToJson: false)
178
+
_$$DeleteGalleryItemResponseImplCopyWith<_$DeleteGalleryItemResponseImpl>
179
+
get copyWith => throw _privateConstructorUsedError;
180
+
}
+15
lib/models/procedures/delete_gallery_item_response.g.dart
+15
lib/models/procedures/delete_gallery_item_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_gallery_item_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteGalleryItemResponseImpl _$$DeleteGalleryItemResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteGalleryItemResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeleteGalleryItemResponseImplToJson(
14
+
_$DeleteGalleryItemResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+14
lib/models/procedures/delete_gallery_request.dart
+14
lib/models/procedures/delete_gallery_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_gallery_request.freezed.dart';
4
+
part 'delete_gallery_request.g.dart';
5
+
6
+
/// Request model for deleting a gallery.
7
+
/// See lexicon: social.grain.gallery.deleteGallery
8
+
@freezed
9
+
class DeleteGalleryRequest with _$DeleteGalleryRequest {
10
+
const factory DeleteGalleryRequest({required String uri}) = _DeleteGalleryRequest;
11
+
12
+
factory DeleteGalleryRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteGalleryRequestFromJson(json);
14
+
}
+175
lib/models/procedures/delete_gallery_request.freezed.dart
+175
lib/models/procedures/delete_gallery_request.freezed.dart
···
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 'delete_gallery_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
+
DeleteGalleryRequest _$DeleteGalleryRequestFromJson(Map<String, dynamic> json) {
19
+
return _DeleteGalleryRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeleteGalleryRequest {
24
+
String get uri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeleteGalleryRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeleteGalleryRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeleteGalleryRequestCopyWith<DeleteGalleryRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeleteGalleryRequestCopyWith<$Res> {
38
+
factory $DeleteGalleryRequestCopyWith(
39
+
DeleteGalleryRequest value,
40
+
$Res Function(DeleteGalleryRequest) then,
41
+
) = _$DeleteGalleryRequestCopyWithImpl<$Res, DeleteGalleryRequest>;
42
+
@useResult
43
+
$Res call({String uri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeleteGalleryRequestCopyWithImpl<
48
+
$Res,
49
+
$Val extends DeleteGalleryRequest
50
+
>
51
+
implements $DeleteGalleryRequestCopyWith<$Res> {
52
+
_$DeleteGalleryRequestCopyWithImpl(this._value, this._then);
53
+
54
+
// ignore: unused_field
55
+
final $Val _value;
56
+
// ignore: unused_field
57
+
final $Res Function($Val) _then;
58
+
59
+
/// Create a copy of DeleteGalleryRequest
60
+
/// with the given fields replaced by the non-null parameter values.
61
+
@pragma('vm:prefer-inline')
62
+
@override
63
+
$Res call({Object? uri = null}) {
64
+
return _then(
65
+
_value.copyWith(
66
+
uri: null == uri
67
+
? _value.uri
68
+
: uri // ignore: cast_nullable_to_non_nullable
69
+
as String,
70
+
)
71
+
as $Val,
72
+
);
73
+
}
74
+
}
75
+
76
+
/// @nodoc
77
+
abstract class _$$DeleteGalleryRequestImplCopyWith<$Res>
78
+
implements $DeleteGalleryRequestCopyWith<$Res> {
79
+
factory _$$DeleteGalleryRequestImplCopyWith(
80
+
_$DeleteGalleryRequestImpl value,
81
+
$Res Function(_$DeleteGalleryRequestImpl) then,
82
+
) = __$$DeleteGalleryRequestImplCopyWithImpl<$Res>;
83
+
@override
84
+
@useResult
85
+
$Res call({String uri});
86
+
}
87
+
88
+
/// @nodoc
89
+
class __$$DeleteGalleryRequestImplCopyWithImpl<$Res>
90
+
extends _$DeleteGalleryRequestCopyWithImpl<$Res, _$DeleteGalleryRequestImpl>
91
+
implements _$$DeleteGalleryRequestImplCopyWith<$Res> {
92
+
__$$DeleteGalleryRequestImplCopyWithImpl(
93
+
_$DeleteGalleryRequestImpl _value,
94
+
$Res Function(_$DeleteGalleryRequestImpl) _then,
95
+
) : super(_value, _then);
96
+
97
+
/// Create a copy of DeleteGalleryRequest
98
+
/// with the given fields replaced by the non-null parameter values.
99
+
@pragma('vm:prefer-inline')
100
+
@override
101
+
$Res call({Object? uri = null}) {
102
+
return _then(
103
+
_$DeleteGalleryRequestImpl(
104
+
uri: null == uri
105
+
? _value.uri
106
+
: uri // ignore: cast_nullable_to_non_nullable
107
+
as String,
108
+
),
109
+
);
110
+
}
111
+
}
112
+
113
+
/// @nodoc
114
+
@JsonSerializable()
115
+
class _$DeleteGalleryRequestImpl implements _DeleteGalleryRequest {
116
+
const _$DeleteGalleryRequestImpl({required this.uri});
117
+
118
+
factory _$DeleteGalleryRequestImpl.fromJson(Map<String, dynamic> json) =>
119
+
_$$DeleteGalleryRequestImplFromJson(json);
120
+
121
+
@override
122
+
final String uri;
123
+
124
+
@override
125
+
String toString() {
126
+
return 'DeleteGalleryRequest(uri: $uri)';
127
+
}
128
+
129
+
@override
130
+
bool operator ==(Object other) {
131
+
return identical(this, other) ||
132
+
(other.runtimeType == runtimeType &&
133
+
other is _$DeleteGalleryRequestImpl &&
134
+
(identical(other.uri, uri) || other.uri == uri));
135
+
}
136
+
137
+
@JsonKey(includeFromJson: false, includeToJson: false)
138
+
@override
139
+
int get hashCode => Object.hash(runtimeType, uri);
140
+
141
+
/// Create a copy of DeleteGalleryRequest
142
+
/// with the given fields replaced by the non-null parameter values.
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
@pragma('vm:prefer-inline')
146
+
_$$DeleteGalleryRequestImplCopyWith<_$DeleteGalleryRequestImpl>
147
+
get copyWith =>
148
+
__$$DeleteGalleryRequestImplCopyWithImpl<_$DeleteGalleryRequestImpl>(
149
+
this,
150
+
_$identity,
151
+
);
152
+
153
+
@override
154
+
Map<String, dynamic> toJson() {
155
+
return _$$DeleteGalleryRequestImplToJson(this);
156
+
}
157
+
}
158
+
159
+
abstract class _DeleteGalleryRequest implements DeleteGalleryRequest {
160
+
const factory _DeleteGalleryRequest({required final String uri}) =
161
+
_$DeleteGalleryRequestImpl;
162
+
163
+
factory _DeleteGalleryRequest.fromJson(Map<String, dynamic> json) =
164
+
_$DeleteGalleryRequestImpl.fromJson;
165
+
166
+
@override
167
+
String get uri;
168
+
169
+
/// Create a copy of DeleteGalleryRequest
170
+
/// with the given fields replaced by the non-null parameter values.
171
+
@override
172
+
@JsonKey(includeFromJson: false, includeToJson: false)
173
+
_$$DeleteGalleryRequestImplCopyWith<_$DeleteGalleryRequestImpl>
174
+
get copyWith => throw _privateConstructorUsedError;
175
+
}
+15
lib/models/procedures/delete_gallery_request.g.dart
+15
lib/models/procedures/delete_gallery_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_gallery_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteGalleryRequestImpl _$$DeleteGalleryRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteGalleryRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeleteGalleryRequestImplToJson(
14
+
_$DeleteGalleryRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+14
lib/models/procedures/delete_gallery_response.dart
+14
lib/models/procedures/delete_gallery_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_gallery_response.freezed.dart';
4
+
part 'delete_gallery_response.g.dart';
5
+
6
+
/// Response model for deleting a gallery.
7
+
/// See lexicon: social.grain.gallery.deleteGallery
8
+
@freezed
9
+
class DeleteGalleryResponse with _$DeleteGalleryResponse {
10
+
const factory DeleteGalleryResponse({required bool success}) = _DeleteGalleryResponse;
11
+
12
+
factory DeleteGalleryResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$DeleteGalleryResponseFromJson(json);
14
+
}
+178
lib/models/procedures/delete_gallery_response.freezed.dart
+178
lib/models/procedures/delete_gallery_response.freezed.dart
···
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 'delete_gallery_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
+
DeleteGalleryResponse _$DeleteGalleryResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _DeleteGalleryResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$DeleteGalleryResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this DeleteGalleryResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of DeleteGalleryResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$DeleteGalleryResponseCopyWith<DeleteGalleryResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $DeleteGalleryResponseCopyWith<$Res> {
40
+
factory $DeleteGalleryResponseCopyWith(
41
+
DeleteGalleryResponse value,
42
+
$Res Function(DeleteGalleryResponse) then,
43
+
) = _$DeleteGalleryResponseCopyWithImpl<$Res, DeleteGalleryResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$DeleteGalleryResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends DeleteGalleryResponse
52
+
>
53
+
implements $DeleteGalleryResponseCopyWith<$Res> {
54
+
_$DeleteGalleryResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of DeleteGalleryResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$DeleteGalleryResponseImplCopyWith<$Res>
80
+
implements $DeleteGalleryResponseCopyWith<$Res> {
81
+
factory _$$DeleteGalleryResponseImplCopyWith(
82
+
_$DeleteGalleryResponseImpl value,
83
+
$Res Function(_$DeleteGalleryResponseImpl) then,
84
+
) = __$$DeleteGalleryResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$DeleteGalleryResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$DeleteGalleryResponseCopyWithImpl<$Res, _$DeleteGalleryResponseImpl>
94
+
implements _$$DeleteGalleryResponseImplCopyWith<$Res> {
95
+
__$$DeleteGalleryResponseImplCopyWithImpl(
96
+
_$DeleteGalleryResponseImpl _value,
97
+
$Res Function(_$DeleteGalleryResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of DeleteGalleryResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? success = null}) {
105
+
return _then(
106
+
_$DeleteGalleryResponseImpl(
107
+
success: null == success
108
+
? _value.success
109
+
: success // ignore: cast_nullable_to_non_nullable
110
+
as bool,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$DeleteGalleryResponseImpl implements _DeleteGalleryResponse {
119
+
const _$DeleteGalleryResponseImpl({required this.success});
120
+
121
+
factory _$DeleteGalleryResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$DeleteGalleryResponseImplFromJson(json);
123
+
124
+
@override
125
+
final bool success;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'DeleteGalleryResponse(success: $success)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$DeleteGalleryResponseImpl &&
137
+
(identical(other.success, success) || other.success == success));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, success);
143
+
144
+
/// Create a copy of DeleteGalleryResponse
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$DeleteGalleryResponseImplCopyWith<_$DeleteGalleryResponseImpl>
150
+
get copyWith =>
151
+
__$$DeleteGalleryResponseImplCopyWithImpl<_$DeleteGalleryResponseImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$DeleteGalleryResponseImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _DeleteGalleryResponse implements DeleteGalleryResponse {
163
+
const factory _DeleteGalleryResponse({required final bool success}) =
164
+
_$DeleteGalleryResponseImpl;
165
+
166
+
factory _DeleteGalleryResponse.fromJson(Map<String, dynamic> json) =
167
+
_$DeleteGalleryResponseImpl.fromJson;
168
+
169
+
@override
170
+
bool get success;
171
+
172
+
/// Create a copy of DeleteGalleryResponse
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$DeleteGalleryResponseImplCopyWith<_$DeleteGalleryResponseImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/delete_gallery_response.g.dart
+15
lib/models/procedures/delete_gallery_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_gallery_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeleteGalleryResponseImpl _$$DeleteGalleryResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeleteGalleryResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeleteGalleryResponseImplToJson(
14
+
_$DeleteGalleryResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+14
lib/models/procedures/delete_photo_request.dart
+14
lib/models/procedures/delete_photo_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_photo_request.freezed.dart';
4
+
part 'delete_photo_request.g.dart';
5
+
6
+
/// Request model for deleting a photo.
7
+
/// See lexicon: social.grain.photo.deletePhoto
8
+
@freezed
9
+
class DeletePhotoRequest with _$DeletePhotoRequest {
10
+
const factory DeletePhotoRequest({required String uri}) = _DeletePhotoRequest;
11
+
12
+
factory DeletePhotoRequest.fromJson(Map<String, dynamic> json) =>
13
+
_$DeletePhotoRequestFromJson(json);
14
+
}
+171
lib/models/procedures/delete_photo_request.freezed.dart
+171
lib/models/procedures/delete_photo_request.freezed.dart
···
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 'delete_photo_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
+
DeletePhotoRequest _$DeletePhotoRequestFromJson(Map<String, dynamic> json) {
19
+
return _DeletePhotoRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeletePhotoRequest {
24
+
String get uri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeletePhotoRequest to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeletePhotoRequest
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeletePhotoRequestCopyWith<DeletePhotoRequest> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeletePhotoRequestCopyWith<$Res> {
38
+
factory $DeletePhotoRequestCopyWith(
39
+
DeletePhotoRequest value,
40
+
$Res Function(DeletePhotoRequest) then,
41
+
) = _$DeletePhotoRequestCopyWithImpl<$Res, DeletePhotoRequest>;
42
+
@useResult
43
+
$Res call({String uri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeletePhotoRequestCopyWithImpl<$Res, $Val extends DeletePhotoRequest>
48
+
implements $DeletePhotoRequestCopyWith<$Res> {
49
+
_$DeletePhotoRequestCopyWithImpl(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 DeletePhotoRequest
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? uri = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
uri: null == uri
64
+
? _value.uri
65
+
: uri // ignore: cast_nullable_to_non_nullable
66
+
as String,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$DeletePhotoRequestImplCopyWith<$Res>
75
+
implements $DeletePhotoRequestCopyWith<$Res> {
76
+
factory _$$DeletePhotoRequestImplCopyWith(
77
+
_$DeletePhotoRequestImpl value,
78
+
$Res Function(_$DeletePhotoRequestImpl) then,
79
+
) = __$$DeletePhotoRequestImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({String uri});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$DeletePhotoRequestImplCopyWithImpl<$Res>
87
+
extends _$DeletePhotoRequestCopyWithImpl<$Res, _$DeletePhotoRequestImpl>
88
+
implements _$$DeletePhotoRequestImplCopyWith<$Res> {
89
+
__$$DeletePhotoRequestImplCopyWithImpl(
90
+
_$DeletePhotoRequestImpl _value,
91
+
$Res Function(_$DeletePhotoRequestImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of DeletePhotoRequest
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? uri = null}) {
99
+
return _then(
100
+
_$DeletePhotoRequestImpl(
101
+
uri: null == uri
102
+
? _value.uri
103
+
: uri // ignore: cast_nullable_to_non_nullable
104
+
as String,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$DeletePhotoRequestImpl implements _DeletePhotoRequest {
113
+
const _$DeletePhotoRequestImpl({required this.uri});
114
+
115
+
factory _$DeletePhotoRequestImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$DeletePhotoRequestImplFromJson(json);
117
+
118
+
@override
119
+
final String uri;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'DeletePhotoRequest(uri: $uri)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$DeletePhotoRequestImpl &&
131
+
(identical(other.uri, uri) || other.uri == uri));
132
+
}
133
+
134
+
@JsonKey(includeFromJson: false, includeToJson: false)
135
+
@override
136
+
int get hashCode => Object.hash(runtimeType, uri);
137
+
138
+
/// Create a copy of DeletePhotoRequest
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
+
_$$DeletePhotoRequestImplCopyWith<_$DeletePhotoRequestImpl> get copyWith =>
144
+
__$$DeletePhotoRequestImplCopyWithImpl<_$DeletePhotoRequestImpl>(
145
+
this,
146
+
_$identity,
147
+
);
148
+
149
+
@override
150
+
Map<String, dynamic> toJson() {
151
+
return _$$DeletePhotoRequestImplToJson(this);
152
+
}
153
+
}
154
+
155
+
abstract class _DeletePhotoRequest implements DeletePhotoRequest {
156
+
const factory _DeletePhotoRequest({required final String uri}) =
157
+
_$DeletePhotoRequestImpl;
158
+
159
+
factory _DeletePhotoRequest.fromJson(Map<String, dynamic> json) =
160
+
_$DeletePhotoRequestImpl.fromJson;
161
+
162
+
@override
163
+
String get uri;
164
+
165
+
/// Create a copy of DeletePhotoRequest
166
+
/// with the given fields replaced by the non-null parameter values.
167
+
@override
168
+
@JsonKey(includeFromJson: false, includeToJson: false)
169
+
_$$DeletePhotoRequestImplCopyWith<_$DeletePhotoRequestImpl> get copyWith =>
170
+
throw _privateConstructorUsedError;
171
+
}
+15
lib/models/procedures/delete_photo_request.g.dart
+15
lib/models/procedures/delete_photo_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_photo_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeletePhotoRequestImpl _$$DeletePhotoRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeletePhotoRequestImpl(uri: json['uri'] as String);
12
+
13
+
Map<String, dynamic> _$$DeletePhotoRequestImplToJson(
14
+
_$DeletePhotoRequestImpl instance,
15
+
) => <String, dynamic>{'uri': instance.uri};
+14
lib/models/procedures/delete_photo_response.dart
+14
lib/models/procedures/delete_photo_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'delete_photo_response.freezed.dart';
4
+
part 'delete_photo_response.g.dart';
5
+
6
+
/// Response model for deleting a photo.
7
+
/// See lexicon: social.grain.photo.deletePhoto
8
+
@freezed
9
+
class DeletePhotoResponse with _$DeletePhotoResponse {
10
+
const factory DeletePhotoResponse({required bool success}) = _DeletePhotoResponse;
11
+
12
+
factory DeletePhotoResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$DeletePhotoResponseFromJson(json);
14
+
}
+171
lib/models/procedures/delete_photo_response.freezed.dart
+171
lib/models/procedures/delete_photo_response.freezed.dart
···
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 'delete_photo_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
+
DeletePhotoResponse _$DeletePhotoResponseFromJson(Map<String, dynamic> json) {
19
+
return _DeletePhotoResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$DeletePhotoResponse {
24
+
bool get success => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this DeletePhotoResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of DeletePhotoResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$DeletePhotoResponseCopyWith<DeletePhotoResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $DeletePhotoResponseCopyWith<$Res> {
38
+
factory $DeletePhotoResponseCopyWith(
39
+
DeletePhotoResponse value,
40
+
$Res Function(DeletePhotoResponse) then,
41
+
) = _$DeletePhotoResponseCopyWithImpl<$Res, DeletePhotoResponse>;
42
+
@useResult
43
+
$Res call({bool success});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$DeletePhotoResponseCopyWithImpl<$Res, $Val extends DeletePhotoResponse>
48
+
implements $DeletePhotoResponseCopyWith<$Res> {
49
+
_$DeletePhotoResponseCopyWithImpl(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 DeletePhotoResponse
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 _$$DeletePhotoResponseImplCopyWith<$Res>
75
+
implements $DeletePhotoResponseCopyWith<$Res> {
76
+
factory _$$DeletePhotoResponseImplCopyWith(
77
+
_$DeletePhotoResponseImpl value,
78
+
$Res Function(_$DeletePhotoResponseImpl) then,
79
+
) = __$$DeletePhotoResponseImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({bool success});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$DeletePhotoResponseImplCopyWithImpl<$Res>
87
+
extends _$DeletePhotoResponseCopyWithImpl<$Res, _$DeletePhotoResponseImpl>
88
+
implements _$$DeletePhotoResponseImplCopyWith<$Res> {
89
+
__$$DeletePhotoResponseImplCopyWithImpl(
90
+
_$DeletePhotoResponseImpl _value,
91
+
$Res Function(_$DeletePhotoResponseImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of DeletePhotoResponse
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
+
_$DeletePhotoResponseImpl(
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 _$DeletePhotoResponseImpl implements _DeletePhotoResponse {
113
+
const _$DeletePhotoResponseImpl({required this.success});
114
+
115
+
factory _$DeletePhotoResponseImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$DeletePhotoResponseImplFromJson(json);
117
+
118
+
@override
119
+
final bool success;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'DeletePhotoResponse(success: $success)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$DeletePhotoResponseImpl &&
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 DeletePhotoResponse
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
+
_$$DeletePhotoResponseImplCopyWith<_$DeletePhotoResponseImpl> get copyWith =>
144
+
__$$DeletePhotoResponseImplCopyWithImpl<_$DeletePhotoResponseImpl>(
145
+
this,
146
+
_$identity,
147
+
);
148
+
149
+
@override
150
+
Map<String, dynamic> toJson() {
151
+
return _$$DeletePhotoResponseImplToJson(this);
152
+
}
153
+
}
154
+
155
+
abstract class _DeletePhotoResponse implements DeletePhotoResponse {
156
+
const factory _DeletePhotoResponse({required final bool success}) =
157
+
_$DeletePhotoResponseImpl;
158
+
159
+
factory _DeletePhotoResponse.fromJson(Map<String, dynamic> json) =
160
+
_$DeletePhotoResponseImpl.fromJson;
161
+
162
+
@override
163
+
bool get success;
164
+
165
+
/// Create a copy of DeletePhotoResponse
166
+
/// with the given fields replaced by the non-null parameter values.
167
+
@override
168
+
@JsonKey(includeFromJson: false, includeToJson: false)
169
+
_$$DeletePhotoResponseImplCopyWith<_$DeletePhotoResponseImpl> get copyWith =>
170
+
throw _privateConstructorUsedError;
171
+
}
+15
lib/models/procedures/delete_photo_response.g.dart
+15
lib/models/procedures/delete_photo_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'delete_photo_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$DeletePhotoResponseImpl _$$DeletePhotoResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$DeletePhotoResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$DeletePhotoResponseImplToJson(
14
+
_$DeletePhotoResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+34
lib/models/procedures/procedures.dart
+34
lib/models/procedures/procedures.dart
···
1
+
export 'apply_alts_request.dart';
2
+
export 'apply_alts_response.dart';
3
+
export 'apply_sort_request.dart';
4
+
export 'apply_sort_response.dart';
5
+
export 'create_comment_request.dart';
6
+
export 'create_comment_response.dart';
7
+
export 'create_exif_request.dart';
8
+
export 'create_exif_response.dart';
9
+
export 'create_favorite_request.dart';
10
+
export 'create_favorite_response.dart';
11
+
export 'create_follow_request.dart';
12
+
export 'create_follow_response.dart';
13
+
export 'create_gallery_item_request.dart';
14
+
export 'create_gallery_item_response.dart';
15
+
export 'create_gallery_request.dart';
16
+
export 'create_gallery_response.dart';
17
+
export 'delete_comment_request.dart';
18
+
export 'delete_comment_response.dart';
19
+
export 'delete_favorite_request.dart';
20
+
export 'delete_favorite_response.dart';
21
+
export 'delete_follow_request.dart';
22
+
export 'delete_follow_response.dart';
23
+
export 'delete_gallery_item_request.dart';
24
+
export 'delete_gallery_item_response.dart';
25
+
export 'delete_gallery_request.dart';
26
+
export 'delete_gallery_response.dart';
27
+
export 'delete_photo_request.dart';
28
+
export 'delete_photo_response.dart';
29
+
export 'update_avatar_response.dart';
30
+
export 'update_gallery_request.dart';
31
+
export 'update_gallery_response.dart';
32
+
export 'update_profile_request.dart';
33
+
export 'update_profile_response.dart';
34
+
export 'upload_photo_response.dart';
+15
lib/models/procedures/update_avatar_response.dart
+15
lib/models/procedures/update_avatar_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'update_avatar_response.freezed.dart';
4
+
part 'update_avatar_response.g.dart';
5
+
6
+
/// Response model for updating an actor's avatar image.
7
+
///
8
+
/// [success] - Indicates if the update was successful.
9
+
@freezed
10
+
class UpdateAvatarResponse with _$UpdateAvatarResponse {
11
+
const factory UpdateAvatarResponse({required bool success}) = _UpdateAvatarResponse;
12
+
13
+
factory UpdateAvatarResponse.fromJson(Map<String, dynamic> json) =>
14
+
_$UpdateAvatarResponseFromJson(json);
15
+
}
+175
lib/models/procedures/update_avatar_response.freezed.dart
+175
lib/models/procedures/update_avatar_response.freezed.dart
···
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 'update_avatar_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
+
UpdateAvatarResponse _$UpdateAvatarResponseFromJson(Map<String, dynamic> json) {
19
+
return _UpdateAvatarResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$UpdateAvatarResponse {
24
+
bool get success => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this UpdateAvatarResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of UpdateAvatarResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$UpdateAvatarResponseCopyWith<UpdateAvatarResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $UpdateAvatarResponseCopyWith<$Res> {
38
+
factory $UpdateAvatarResponseCopyWith(
39
+
UpdateAvatarResponse value,
40
+
$Res Function(UpdateAvatarResponse) then,
41
+
) = _$UpdateAvatarResponseCopyWithImpl<$Res, UpdateAvatarResponse>;
42
+
@useResult
43
+
$Res call({bool success});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$UpdateAvatarResponseCopyWithImpl<
48
+
$Res,
49
+
$Val extends UpdateAvatarResponse
50
+
>
51
+
implements $UpdateAvatarResponseCopyWith<$Res> {
52
+
_$UpdateAvatarResponseCopyWithImpl(this._value, this._then);
53
+
54
+
// ignore: unused_field
55
+
final $Val _value;
56
+
// ignore: unused_field
57
+
final $Res Function($Val) _then;
58
+
59
+
/// Create a copy of UpdateAvatarResponse
60
+
/// with the given fields replaced by the non-null parameter values.
61
+
@pragma('vm:prefer-inline')
62
+
@override
63
+
$Res call({Object? success = null}) {
64
+
return _then(
65
+
_value.copyWith(
66
+
success: null == success
67
+
? _value.success
68
+
: success // ignore: cast_nullable_to_non_nullable
69
+
as bool,
70
+
)
71
+
as $Val,
72
+
);
73
+
}
74
+
}
75
+
76
+
/// @nodoc
77
+
abstract class _$$UpdateAvatarResponseImplCopyWith<$Res>
78
+
implements $UpdateAvatarResponseCopyWith<$Res> {
79
+
factory _$$UpdateAvatarResponseImplCopyWith(
80
+
_$UpdateAvatarResponseImpl value,
81
+
$Res Function(_$UpdateAvatarResponseImpl) then,
82
+
) = __$$UpdateAvatarResponseImplCopyWithImpl<$Res>;
83
+
@override
84
+
@useResult
85
+
$Res call({bool success});
86
+
}
87
+
88
+
/// @nodoc
89
+
class __$$UpdateAvatarResponseImplCopyWithImpl<$Res>
90
+
extends _$UpdateAvatarResponseCopyWithImpl<$Res, _$UpdateAvatarResponseImpl>
91
+
implements _$$UpdateAvatarResponseImplCopyWith<$Res> {
92
+
__$$UpdateAvatarResponseImplCopyWithImpl(
93
+
_$UpdateAvatarResponseImpl _value,
94
+
$Res Function(_$UpdateAvatarResponseImpl) _then,
95
+
) : super(_value, _then);
96
+
97
+
/// Create a copy of UpdateAvatarResponse
98
+
/// with the given fields replaced by the non-null parameter values.
99
+
@pragma('vm:prefer-inline')
100
+
@override
101
+
$Res call({Object? success = null}) {
102
+
return _then(
103
+
_$UpdateAvatarResponseImpl(
104
+
success: null == success
105
+
? _value.success
106
+
: success // ignore: cast_nullable_to_non_nullable
107
+
as bool,
108
+
),
109
+
);
110
+
}
111
+
}
112
+
113
+
/// @nodoc
114
+
@JsonSerializable()
115
+
class _$UpdateAvatarResponseImpl implements _UpdateAvatarResponse {
116
+
const _$UpdateAvatarResponseImpl({required this.success});
117
+
118
+
factory _$UpdateAvatarResponseImpl.fromJson(Map<String, dynamic> json) =>
119
+
_$$UpdateAvatarResponseImplFromJson(json);
120
+
121
+
@override
122
+
final bool success;
123
+
124
+
@override
125
+
String toString() {
126
+
return 'UpdateAvatarResponse(success: $success)';
127
+
}
128
+
129
+
@override
130
+
bool operator ==(Object other) {
131
+
return identical(this, other) ||
132
+
(other.runtimeType == runtimeType &&
133
+
other is _$UpdateAvatarResponseImpl &&
134
+
(identical(other.success, success) || other.success == success));
135
+
}
136
+
137
+
@JsonKey(includeFromJson: false, includeToJson: false)
138
+
@override
139
+
int get hashCode => Object.hash(runtimeType, success);
140
+
141
+
/// Create a copy of UpdateAvatarResponse
142
+
/// with the given fields replaced by the non-null parameter values.
143
+
@JsonKey(includeFromJson: false, includeToJson: false)
144
+
@override
145
+
@pragma('vm:prefer-inline')
146
+
_$$UpdateAvatarResponseImplCopyWith<_$UpdateAvatarResponseImpl>
147
+
get copyWith =>
148
+
__$$UpdateAvatarResponseImplCopyWithImpl<_$UpdateAvatarResponseImpl>(
149
+
this,
150
+
_$identity,
151
+
);
152
+
153
+
@override
154
+
Map<String, dynamic> toJson() {
155
+
return _$$UpdateAvatarResponseImplToJson(this);
156
+
}
157
+
}
158
+
159
+
abstract class _UpdateAvatarResponse implements UpdateAvatarResponse {
160
+
const factory _UpdateAvatarResponse({required final bool success}) =
161
+
_$UpdateAvatarResponseImpl;
162
+
163
+
factory _UpdateAvatarResponse.fromJson(Map<String, dynamic> json) =
164
+
_$UpdateAvatarResponseImpl.fromJson;
165
+
166
+
@override
167
+
bool get success;
168
+
169
+
/// Create a copy of UpdateAvatarResponse
170
+
/// with the given fields replaced by the non-null parameter values.
171
+
@override
172
+
@JsonKey(includeFromJson: false, includeToJson: false)
173
+
_$$UpdateAvatarResponseImplCopyWith<_$UpdateAvatarResponseImpl>
174
+
get copyWith => throw _privateConstructorUsedError;
175
+
}
+15
lib/models/procedures/update_avatar_response.g.dart
+15
lib/models/procedures/update_avatar_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'update_avatar_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UpdateAvatarResponseImpl _$$UpdateAvatarResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UpdateAvatarResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$UpdateAvatarResponseImplToJson(
14
+
_$UpdateAvatarResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+18
lib/models/procedures/update_gallery_request.dart
+18
lib/models/procedures/update_gallery_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'update_gallery_request.freezed.dart';
4
+
part 'update_gallery_request.g.dart';
5
+
6
+
/// Request model for updating a gallery.
7
+
/// See lexicon: social.grain.gallery.updateGallery
8
+
@freezed
9
+
class UpdateGalleryRequest with _$UpdateGalleryRequest {
10
+
const factory UpdateGalleryRequest({
11
+
required String galleryUri,
12
+
required String title,
13
+
String? description,
14
+
}) = _UpdateGalleryRequest;
15
+
16
+
factory UpdateGalleryRequest.fromJson(Map<String, dynamic> json) =>
17
+
_$UpdateGalleryRequestFromJson(json);
18
+
}
+220
lib/models/procedures/update_gallery_request.freezed.dart
+220
lib/models/procedures/update_gallery_request.freezed.dart
···
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 'update_gallery_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
+
UpdateGalleryRequest _$UpdateGalleryRequestFromJson(Map<String, dynamic> json) {
19
+
return _UpdateGalleryRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$UpdateGalleryRequest {
24
+
String get galleryUri => throw _privateConstructorUsedError;
25
+
String get title => throw _privateConstructorUsedError;
26
+
String? get description => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this UpdateGalleryRequest to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of UpdateGalleryRequest
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$UpdateGalleryRequestCopyWith<UpdateGalleryRequest> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $UpdateGalleryRequestCopyWith<$Res> {
40
+
factory $UpdateGalleryRequestCopyWith(
41
+
UpdateGalleryRequest value,
42
+
$Res Function(UpdateGalleryRequest) then,
43
+
) = _$UpdateGalleryRequestCopyWithImpl<$Res, UpdateGalleryRequest>;
44
+
@useResult
45
+
$Res call({String galleryUri, String title, String? description});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$UpdateGalleryRequestCopyWithImpl<
50
+
$Res,
51
+
$Val extends UpdateGalleryRequest
52
+
>
53
+
implements $UpdateGalleryRequestCopyWith<$Res> {
54
+
_$UpdateGalleryRequestCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of UpdateGalleryRequest
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({
66
+
Object? galleryUri = null,
67
+
Object? title = null,
68
+
Object? description = freezed,
69
+
}) {
70
+
return _then(
71
+
_value.copyWith(
72
+
galleryUri: null == galleryUri
73
+
? _value.galleryUri
74
+
: galleryUri // ignore: cast_nullable_to_non_nullable
75
+
as String,
76
+
title: null == title
77
+
? _value.title
78
+
: title // ignore: cast_nullable_to_non_nullable
79
+
as String,
80
+
description: freezed == description
81
+
? _value.description
82
+
: description // ignore: cast_nullable_to_non_nullable
83
+
as String?,
84
+
)
85
+
as $Val,
86
+
);
87
+
}
88
+
}
89
+
90
+
/// @nodoc
91
+
abstract class _$$UpdateGalleryRequestImplCopyWith<$Res>
92
+
implements $UpdateGalleryRequestCopyWith<$Res> {
93
+
factory _$$UpdateGalleryRequestImplCopyWith(
94
+
_$UpdateGalleryRequestImpl value,
95
+
$Res Function(_$UpdateGalleryRequestImpl) then,
96
+
) = __$$UpdateGalleryRequestImplCopyWithImpl<$Res>;
97
+
@override
98
+
@useResult
99
+
$Res call({String galleryUri, String title, String? description});
100
+
}
101
+
102
+
/// @nodoc
103
+
class __$$UpdateGalleryRequestImplCopyWithImpl<$Res>
104
+
extends _$UpdateGalleryRequestCopyWithImpl<$Res, _$UpdateGalleryRequestImpl>
105
+
implements _$$UpdateGalleryRequestImplCopyWith<$Res> {
106
+
__$$UpdateGalleryRequestImplCopyWithImpl(
107
+
_$UpdateGalleryRequestImpl _value,
108
+
$Res Function(_$UpdateGalleryRequestImpl) _then,
109
+
) : super(_value, _then);
110
+
111
+
/// Create a copy of UpdateGalleryRequest
112
+
/// with the given fields replaced by the non-null parameter values.
113
+
@pragma('vm:prefer-inline')
114
+
@override
115
+
$Res call({
116
+
Object? galleryUri = null,
117
+
Object? title = null,
118
+
Object? description = freezed,
119
+
}) {
120
+
return _then(
121
+
_$UpdateGalleryRequestImpl(
122
+
galleryUri: null == galleryUri
123
+
? _value.galleryUri
124
+
: galleryUri // ignore: cast_nullable_to_non_nullable
125
+
as String,
126
+
title: null == title
127
+
? _value.title
128
+
: title // ignore: cast_nullable_to_non_nullable
129
+
as String,
130
+
description: freezed == description
131
+
? _value.description
132
+
: description // ignore: cast_nullable_to_non_nullable
133
+
as String?,
134
+
),
135
+
);
136
+
}
137
+
}
138
+
139
+
/// @nodoc
140
+
@JsonSerializable()
141
+
class _$UpdateGalleryRequestImpl implements _UpdateGalleryRequest {
142
+
const _$UpdateGalleryRequestImpl({
143
+
required this.galleryUri,
144
+
required this.title,
145
+
this.description,
146
+
});
147
+
148
+
factory _$UpdateGalleryRequestImpl.fromJson(Map<String, dynamic> json) =>
149
+
_$$UpdateGalleryRequestImplFromJson(json);
150
+
151
+
@override
152
+
final String galleryUri;
153
+
@override
154
+
final String title;
155
+
@override
156
+
final String? description;
157
+
158
+
@override
159
+
String toString() {
160
+
return 'UpdateGalleryRequest(galleryUri: $galleryUri, title: $title, description: $description)';
161
+
}
162
+
163
+
@override
164
+
bool operator ==(Object other) {
165
+
return identical(this, other) ||
166
+
(other.runtimeType == runtimeType &&
167
+
other is _$UpdateGalleryRequestImpl &&
168
+
(identical(other.galleryUri, galleryUri) ||
169
+
other.galleryUri == galleryUri) &&
170
+
(identical(other.title, title) || other.title == title) &&
171
+
(identical(other.description, description) ||
172
+
other.description == description));
173
+
}
174
+
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
@override
177
+
int get hashCode => Object.hash(runtimeType, galleryUri, title, description);
178
+
179
+
/// Create a copy of UpdateGalleryRequest
180
+
/// with the given fields replaced by the non-null parameter values.
181
+
@JsonKey(includeFromJson: false, includeToJson: false)
182
+
@override
183
+
@pragma('vm:prefer-inline')
184
+
_$$UpdateGalleryRequestImplCopyWith<_$UpdateGalleryRequestImpl>
185
+
get copyWith =>
186
+
__$$UpdateGalleryRequestImplCopyWithImpl<_$UpdateGalleryRequestImpl>(
187
+
this,
188
+
_$identity,
189
+
);
190
+
191
+
@override
192
+
Map<String, dynamic> toJson() {
193
+
return _$$UpdateGalleryRequestImplToJson(this);
194
+
}
195
+
}
196
+
197
+
abstract class _UpdateGalleryRequest implements UpdateGalleryRequest {
198
+
const factory _UpdateGalleryRequest({
199
+
required final String galleryUri,
200
+
required final String title,
201
+
final String? description,
202
+
}) = _$UpdateGalleryRequestImpl;
203
+
204
+
factory _UpdateGalleryRequest.fromJson(Map<String, dynamic> json) =
205
+
_$UpdateGalleryRequestImpl.fromJson;
206
+
207
+
@override
208
+
String get galleryUri;
209
+
@override
210
+
String get title;
211
+
@override
212
+
String? get description;
213
+
214
+
/// Create a copy of UpdateGalleryRequest
215
+
/// with the given fields replaced by the non-null parameter values.
216
+
@override
217
+
@JsonKey(includeFromJson: false, includeToJson: false)
218
+
_$$UpdateGalleryRequestImplCopyWith<_$UpdateGalleryRequestImpl>
219
+
get copyWith => throw _privateConstructorUsedError;
220
+
}
+23
lib/models/procedures/update_gallery_request.g.dart
+23
lib/models/procedures/update_gallery_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'update_gallery_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UpdateGalleryRequestImpl _$$UpdateGalleryRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UpdateGalleryRequestImpl(
12
+
galleryUri: json['galleryUri'] as String,
13
+
title: json['title'] as String,
14
+
description: json['description'] as String?,
15
+
);
16
+
17
+
Map<String, dynamic> _$$UpdateGalleryRequestImplToJson(
18
+
_$UpdateGalleryRequestImpl instance,
19
+
) => <String, dynamic>{
20
+
'galleryUri': instance.galleryUri,
21
+
'title': instance.title,
22
+
'description': instance.description,
23
+
};
+14
lib/models/procedures/update_gallery_response.dart
+14
lib/models/procedures/update_gallery_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'update_gallery_response.freezed.dart';
4
+
part 'update_gallery_response.g.dart';
5
+
6
+
/// Response model for updating a gallery.
7
+
/// See lexicon: social.grain.gallery.updateGallery
8
+
@freezed
9
+
class UpdateGalleryResponse with _$UpdateGalleryResponse {
10
+
const factory UpdateGalleryResponse({required bool success}) = _UpdateGalleryResponse;
11
+
12
+
factory UpdateGalleryResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$UpdateGalleryResponseFromJson(json);
14
+
}
+178
lib/models/procedures/update_gallery_response.freezed.dart
+178
lib/models/procedures/update_gallery_response.freezed.dart
···
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 'update_gallery_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
+
UpdateGalleryResponse _$UpdateGalleryResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _UpdateGalleryResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$UpdateGalleryResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this UpdateGalleryResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of UpdateGalleryResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$UpdateGalleryResponseCopyWith<UpdateGalleryResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $UpdateGalleryResponseCopyWith<$Res> {
40
+
factory $UpdateGalleryResponseCopyWith(
41
+
UpdateGalleryResponse value,
42
+
$Res Function(UpdateGalleryResponse) then,
43
+
) = _$UpdateGalleryResponseCopyWithImpl<$Res, UpdateGalleryResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$UpdateGalleryResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends UpdateGalleryResponse
52
+
>
53
+
implements $UpdateGalleryResponseCopyWith<$Res> {
54
+
_$UpdateGalleryResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of UpdateGalleryResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$UpdateGalleryResponseImplCopyWith<$Res>
80
+
implements $UpdateGalleryResponseCopyWith<$Res> {
81
+
factory _$$UpdateGalleryResponseImplCopyWith(
82
+
_$UpdateGalleryResponseImpl value,
83
+
$Res Function(_$UpdateGalleryResponseImpl) then,
84
+
) = __$$UpdateGalleryResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$UpdateGalleryResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$UpdateGalleryResponseCopyWithImpl<$Res, _$UpdateGalleryResponseImpl>
94
+
implements _$$UpdateGalleryResponseImplCopyWith<$Res> {
95
+
__$$UpdateGalleryResponseImplCopyWithImpl(
96
+
_$UpdateGalleryResponseImpl _value,
97
+
$Res Function(_$UpdateGalleryResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of UpdateGalleryResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? success = null}) {
105
+
return _then(
106
+
_$UpdateGalleryResponseImpl(
107
+
success: null == success
108
+
? _value.success
109
+
: success // ignore: cast_nullable_to_non_nullable
110
+
as bool,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$UpdateGalleryResponseImpl implements _UpdateGalleryResponse {
119
+
const _$UpdateGalleryResponseImpl({required this.success});
120
+
121
+
factory _$UpdateGalleryResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$UpdateGalleryResponseImplFromJson(json);
123
+
124
+
@override
125
+
final bool success;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'UpdateGalleryResponse(success: $success)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$UpdateGalleryResponseImpl &&
137
+
(identical(other.success, success) || other.success == success));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, success);
143
+
144
+
/// Create a copy of UpdateGalleryResponse
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$UpdateGalleryResponseImplCopyWith<_$UpdateGalleryResponseImpl>
150
+
get copyWith =>
151
+
__$$UpdateGalleryResponseImplCopyWithImpl<_$UpdateGalleryResponseImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$UpdateGalleryResponseImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _UpdateGalleryResponse implements UpdateGalleryResponse {
163
+
const factory _UpdateGalleryResponse({required final bool success}) =
164
+
_$UpdateGalleryResponseImpl;
165
+
166
+
factory _UpdateGalleryResponse.fromJson(Map<String, dynamic> json) =
167
+
_$UpdateGalleryResponseImpl.fromJson;
168
+
169
+
@override
170
+
bool get success;
171
+
172
+
/// Create a copy of UpdateGalleryResponse
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$UpdateGalleryResponseImplCopyWith<_$UpdateGalleryResponseImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/update_gallery_response.g.dart
+15
lib/models/procedures/update_gallery_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'update_gallery_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UpdateGalleryResponseImpl _$$UpdateGalleryResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UpdateGalleryResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$UpdateGalleryResponseImplToJson(
14
+
_$UpdateGalleryResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+17
lib/models/procedures/update_profile_request.dart
+17
lib/models/procedures/update_profile_request.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'update_profile_request.freezed.dart';
4
+
part 'update_profile_request.g.dart';
5
+
6
+
/// Request model for updating an actor's profile information.
7
+
///
8
+
/// [displayName] - The display name (optional).
9
+
/// [description] - The profile description (optional).
10
+
@freezed
11
+
class UpdateProfileRequest with _$UpdateProfileRequest {
12
+
const factory UpdateProfileRequest({String? displayName, String? description}) =
13
+
_UpdateProfileRequest;
14
+
15
+
factory UpdateProfileRequest.fromJson(Map<String, dynamic> json) =>
16
+
_$UpdateProfileRequestFromJson(json);
17
+
}
+193
lib/models/procedures/update_profile_request.freezed.dart
+193
lib/models/procedures/update_profile_request.freezed.dart
···
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 'update_profile_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
+
UpdateProfileRequest _$UpdateProfileRequestFromJson(Map<String, dynamic> json) {
19
+
return _UpdateProfileRequest.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$UpdateProfileRequest {
24
+
String? get displayName => throw _privateConstructorUsedError;
25
+
String? get description => throw _privateConstructorUsedError;
26
+
27
+
/// Serializes this UpdateProfileRequest to a JSON map.
28
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
29
+
30
+
/// Create a copy of UpdateProfileRequest
31
+
/// with the given fields replaced by the non-null parameter values.
32
+
@JsonKey(includeFromJson: false, includeToJson: false)
33
+
$UpdateProfileRequestCopyWith<UpdateProfileRequest> get copyWith =>
34
+
throw _privateConstructorUsedError;
35
+
}
36
+
37
+
/// @nodoc
38
+
abstract class $UpdateProfileRequestCopyWith<$Res> {
39
+
factory $UpdateProfileRequestCopyWith(
40
+
UpdateProfileRequest value,
41
+
$Res Function(UpdateProfileRequest) then,
42
+
) = _$UpdateProfileRequestCopyWithImpl<$Res, UpdateProfileRequest>;
43
+
@useResult
44
+
$Res call({String? displayName, String? description});
45
+
}
46
+
47
+
/// @nodoc
48
+
class _$UpdateProfileRequestCopyWithImpl<
49
+
$Res,
50
+
$Val extends UpdateProfileRequest
51
+
>
52
+
implements $UpdateProfileRequestCopyWith<$Res> {
53
+
_$UpdateProfileRequestCopyWithImpl(this._value, this._then);
54
+
55
+
// ignore: unused_field
56
+
final $Val _value;
57
+
// ignore: unused_field
58
+
final $Res Function($Val) _then;
59
+
60
+
/// Create a copy of UpdateProfileRequest
61
+
/// with the given fields replaced by the non-null parameter values.
62
+
@pragma('vm:prefer-inline')
63
+
@override
64
+
$Res call({Object? displayName = freezed, Object? description = freezed}) {
65
+
return _then(
66
+
_value.copyWith(
67
+
displayName: freezed == displayName
68
+
? _value.displayName
69
+
: displayName // ignore: cast_nullable_to_non_nullable
70
+
as String?,
71
+
description: freezed == description
72
+
? _value.description
73
+
: description // ignore: cast_nullable_to_non_nullable
74
+
as String?,
75
+
)
76
+
as $Val,
77
+
);
78
+
}
79
+
}
80
+
81
+
/// @nodoc
82
+
abstract class _$$UpdateProfileRequestImplCopyWith<$Res>
83
+
implements $UpdateProfileRequestCopyWith<$Res> {
84
+
factory _$$UpdateProfileRequestImplCopyWith(
85
+
_$UpdateProfileRequestImpl value,
86
+
$Res Function(_$UpdateProfileRequestImpl) then,
87
+
) = __$$UpdateProfileRequestImplCopyWithImpl<$Res>;
88
+
@override
89
+
@useResult
90
+
$Res call({String? displayName, String? description});
91
+
}
92
+
93
+
/// @nodoc
94
+
class __$$UpdateProfileRequestImplCopyWithImpl<$Res>
95
+
extends _$UpdateProfileRequestCopyWithImpl<$Res, _$UpdateProfileRequestImpl>
96
+
implements _$$UpdateProfileRequestImplCopyWith<$Res> {
97
+
__$$UpdateProfileRequestImplCopyWithImpl(
98
+
_$UpdateProfileRequestImpl _value,
99
+
$Res Function(_$UpdateProfileRequestImpl) _then,
100
+
) : super(_value, _then);
101
+
102
+
/// Create a copy of UpdateProfileRequest
103
+
/// with the given fields replaced by the non-null parameter values.
104
+
@pragma('vm:prefer-inline')
105
+
@override
106
+
$Res call({Object? displayName = freezed, Object? description = freezed}) {
107
+
return _then(
108
+
_$UpdateProfileRequestImpl(
109
+
displayName: freezed == displayName
110
+
? _value.displayName
111
+
: displayName // ignore: cast_nullable_to_non_nullable
112
+
as String?,
113
+
description: freezed == description
114
+
? _value.description
115
+
: description // ignore: cast_nullable_to_non_nullable
116
+
as String?,
117
+
),
118
+
);
119
+
}
120
+
}
121
+
122
+
/// @nodoc
123
+
@JsonSerializable()
124
+
class _$UpdateProfileRequestImpl implements _UpdateProfileRequest {
125
+
const _$UpdateProfileRequestImpl({this.displayName, this.description});
126
+
127
+
factory _$UpdateProfileRequestImpl.fromJson(Map<String, dynamic> json) =>
128
+
_$$UpdateProfileRequestImplFromJson(json);
129
+
130
+
@override
131
+
final String? displayName;
132
+
@override
133
+
final String? description;
134
+
135
+
@override
136
+
String toString() {
137
+
return 'UpdateProfileRequest(displayName: $displayName, description: $description)';
138
+
}
139
+
140
+
@override
141
+
bool operator ==(Object other) {
142
+
return identical(this, other) ||
143
+
(other.runtimeType == runtimeType &&
144
+
other is _$UpdateProfileRequestImpl &&
145
+
(identical(other.displayName, displayName) ||
146
+
other.displayName == displayName) &&
147
+
(identical(other.description, description) ||
148
+
other.description == description));
149
+
}
150
+
151
+
@JsonKey(includeFromJson: false, includeToJson: false)
152
+
@override
153
+
int get hashCode => Object.hash(runtimeType, displayName, description);
154
+
155
+
/// Create a copy of UpdateProfileRequest
156
+
/// with the given fields replaced by the non-null parameter values.
157
+
@JsonKey(includeFromJson: false, includeToJson: false)
158
+
@override
159
+
@pragma('vm:prefer-inline')
160
+
_$$UpdateProfileRequestImplCopyWith<_$UpdateProfileRequestImpl>
161
+
get copyWith =>
162
+
__$$UpdateProfileRequestImplCopyWithImpl<_$UpdateProfileRequestImpl>(
163
+
this,
164
+
_$identity,
165
+
);
166
+
167
+
@override
168
+
Map<String, dynamic> toJson() {
169
+
return _$$UpdateProfileRequestImplToJson(this);
170
+
}
171
+
}
172
+
173
+
abstract class _UpdateProfileRequest implements UpdateProfileRequest {
174
+
const factory _UpdateProfileRequest({
175
+
final String? displayName,
176
+
final String? description,
177
+
}) = _$UpdateProfileRequestImpl;
178
+
179
+
factory _UpdateProfileRequest.fromJson(Map<String, dynamic> json) =
180
+
_$UpdateProfileRequestImpl.fromJson;
181
+
182
+
@override
183
+
String? get displayName;
184
+
@override
185
+
String? get description;
186
+
187
+
/// Create a copy of UpdateProfileRequest
188
+
/// with the given fields replaced by the non-null parameter values.
189
+
@override
190
+
@JsonKey(includeFromJson: false, includeToJson: false)
191
+
_$$UpdateProfileRequestImplCopyWith<_$UpdateProfileRequestImpl>
192
+
get copyWith => throw _privateConstructorUsedError;
193
+
}
+21
lib/models/procedures/update_profile_request.g.dart
+21
lib/models/procedures/update_profile_request.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'update_profile_request.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UpdateProfileRequestImpl _$$UpdateProfileRequestImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UpdateProfileRequestImpl(
12
+
displayName: json['displayName'] as String?,
13
+
description: json['description'] as String?,
14
+
);
15
+
16
+
Map<String, dynamic> _$$UpdateProfileRequestImplToJson(
17
+
_$UpdateProfileRequestImpl instance,
18
+
) => <String, dynamic>{
19
+
'displayName': instance.displayName,
20
+
'description': instance.description,
21
+
};
+15
lib/models/procedures/update_profile_response.dart
+15
lib/models/procedures/update_profile_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'update_profile_response.freezed.dart';
4
+
part 'update_profile_response.g.dart';
5
+
6
+
/// Response model for updating an actor's profile information.
7
+
///
8
+
/// [success] - Indicates if the update was successful.
9
+
@freezed
10
+
class UpdateProfileResponse with _$UpdateProfileResponse {
11
+
const factory UpdateProfileResponse({required bool success}) = _UpdateProfileResponse;
12
+
13
+
factory UpdateProfileResponse.fromJson(Map<String, dynamic> json) =>
14
+
_$UpdateProfileResponseFromJson(json);
15
+
}
+178
lib/models/procedures/update_profile_response.freezed.dart
+178
lib/models/procedures/update_profile_response.freezed.dart
···
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 'update_profile_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
+
UpdateProfileResponse _$UpdateProfileResponseFromJson(
19
+
Map<String, dynamic> json,
20
+
) {
21
+
return _UpdateProfileResponse.fromJson(json);
22
+
}
23
+
24
+
/// @nodoc
25
+
mixin _$UpdateProfileResponse {
26
+
bool get success => throw _privateConstructorUsedError;
27
+
28
+
/// Serializes this UpdateProfileResponse to a JSON map.
29
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
30
+
31
+
/// Create a copy of UpdateProfileResponse
32
+
/// with the given fields replaced by the non-null parameter values.
33
+
@JsonKey(includeFromJson: false, includeToJson: false)
34
+
$UpdateProfileResponseCopyWith<UpdateProfileResponse> get copyWith =>
35
+
throw _privateConstructorUsedError;
36
+
}
37
+
38
+
/// @nodoc
39
+
abstract class $UpdateProfileResponseCopyWith<$Res> {
40
+
factory $UpdateProfileResponseCopyWith(
41
+
UpdateProfileResponse value,
42
+
$Res Function(UpdateProfileResponse) then,
43
+
) = _$UpdateProfileResponseCopyWithImpl<$Res, UpdateProfileResponse>;
44
+
@useResult
45
+
$Res call({bool success});
46
+
}
47
+
48
+
/// @nodoc
49
+
class _$UpdateProfileResponseCopyWithImpl<
50
+
$Res,
51
+
$Val extends UpdateProfileResponse
52
+
>
53
+
implements $UpdateProfileResponseCopyWith<$Res> {
54
+
_$UpdateProfileResponseCopyWithImpl(this._value, this._then);
55
+
56
+
// ignore: unused_field
57
+
final $Val _value;
58
+
// ignore: unused_field
59
+
final $Res Function($Val) _then;
60
+
61
+
/// Create a copy of UpdateProfileResponse
62
+
/// with the given fields replaced by the non-null parameter values.
63
+
@pragma('vm:prefer-inline')
64
+
@override
65
+
$Res call({Object? success = null}) {
66
+
return _then(
67
+
_value.copyWith(
68
+
success: null == success
69
+
? _value.success
70
+
: success // ignore: cast_nullable_to_non_nullable
71
+
as bool,
72
+
)
73
+
as $Val,
74
+
);
75
+
}
76
+
}
77
+
78
+
/// @nodoc
79
+
abstract class _$$UpdateProfileResponseImplCopyWith<$Res>
80
+
implements $UpdateProfileResponseCopyWith<$Res> {
81
+
factory _$$UpdateProfileResponseImplCopyWith(
82
+
_$UpdateProfileResponseImpl value,
83
+
$Res Function(_$UpdateProfileResponseImpl) then,
84
+
) = __$$UpdateProfileResponseImplCopyWithImpl<$Res>;
85
+
@override
86
+
@useResult
87
+
$Res call({bool success});
88
+
}
89
+
90
+
/// @nodoc
91
+
class __$$UpdateProfileResponseImplCopyWithImpl<$Res>
92
+
extends
93
+
_$UpdateProfileResponseCopyWithImpl<$Res, _$UpdateProfileResponseImpl>
94
+
implements _$$UpdateProfileResponseImplCopyWith<$Res> {
95
+
__$$UpdateProfileResponseImplCopyWithImpl(
96
+
_$UpdateProfileResponseImpl _value,
97
+
$Res Function(_$UpdateProfileResponseImpl) _then,
98
+
) : super(_value, _then);
99
+
100
+
/// Create a copy of UpdateProfileResponse
101
+
/// with the given fields replaced by the non-null parameter values.
102
+
@pragma('vm:prefer-inline')
103
+
@override
104
+
$Res call({Object? success = null}) {
105
+
return _then(
106
+
_$UpdateProfileResponseImpl(
107
+
success: null == success
108
+
? _value.success
109
+
: success // ignore: cast_nullable_to_non_nullable
110
+
as bool,
111
+
),
112
+
);
113
+
}
114
+
}
115
+
116
+
/// @nodoc
117
+
@JsonSerializable()
118
+
class _$UpdateProfileResponseImpl implements _UpdateProfileResponse {
119
+
const _$UpdateProfileResponseImpl({required this.success});
120
+
121
+
factory _$UpdateProfileResponseImpl.fromJson(Map<String, dynamic> json) =>
122
+
_$$UpdateProfileResponseImplFromJson(json);
123
+
124
+
@override
125
+
final bool success;
126
+
127
+
@override
128
+
String toString() {
129
+
return 'UpdateProfileResponse(success: $success)';
130
+
}
131
+
132
+
@override
133
+
bool operator ==(Object other) {
134
+
return identical(this, other) ||
135
+
(other.runtimeType == runtimeType &&
136
+
other is _$UpdateProfileResponseImpl &&
137
+
(identical(other.success, success) || other.success == success));
138
+
}
139
+
140
+
@JsonKey(includeFromJson: false, includeToJson: false)
141
+
@override
142
+
int get hashCode => Object.hash(runtimeType, success);
143
+
144
+
/// Create a copy of UpdateProfileResponse
145
+
/// with the given fields replaced by the non-null parameter values.
146
+
@JsonKey(includeFromJson: false, includeToJson: false)
147
+
@override
148
+
@pragma('vm:prefer-inline')
149
+
_$$UpdateProfileResponseImplCopyWith<_$UpdateProfileResponseImpl>
150
+
get copyWith =>
151
+
__$$UpdateProfileResponseImplCopyWithImpl<_$UpdateProfileResponseImpl>(
152
+
this,
153
+
_$identity,
154
+
);
155
+
156
+
@override
157
+
Map<String, dynamic> toJson() {
158
+
return _$$UpdateProfileResponseImplToJson(this);
159
+
}
160
+
}
161
+
162
+
abstract class _UpdateProfileResponse implements UpdateProfileResponse {
163
+
const factory _UpdateProfileResponse({required final bool success}) =
164
+
_$UpdateProfileResponseImpl;
165
+
166
+
factory _UpdateProfileResponse.fromJson(Map<String, dynamic> json) =
167
+
_$UpdateProfileResponseImpl.fromJson;
168
+
169
+
@override
170
+
bool get success;
171
+
172
+
/// Create a copy of UpdateProfileResponse
173
+
/// with the given fields replaced by the non-null parameter values.
174
+
@override
175
+
@JsonKey(includeFromJson: false, includeToJson: false)
176
+
_$$UpdateProfileResponseImplCopyWith<_$UpdateProfileResponseImpl>
177
+
get copyWith => throw _privateConstructorUsedError;
178
+
}
+15
lib/models/procedures/update_profile_response.g.dart
+15
lib/models/procedures/update_profile_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'update_profile_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UpdateProfileResponseImpl _$$UpdateProfileResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UpdateProfileResponseImpl(success: json['success'] as bool);
12
+
13
+
Map<String, dynamic> _$$UpdateProfileResponseImplToJson(
14
+
_$UpdateProfileResponseImpl instance,
15
+
) => <String, dynamic>{'success': instance.success};
+14
lib/models/procedures/upload_photo_response.dart
+14
lib/models/procedures/upload_photo_response.dart
···
1
+
import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+
part 'upload_photo_response.freezed.dart';
4
+
part 'upload_photo_response.g.dart';
5
+
6
+
/// Response model for uploading a photo.
7
+
/// See lexicon: social.grain.photo.uploadPhoto
8
+
@freezed
9
+
class UploadPhotoResponse with _$UploadPhotoResponse {
10
+
const factory UploadPhotoResponse({required String photoUri}) = _UploadPhotoResponse;
11
+
12
+
factory UploadPhotoResponse.fromJson(Map<String, dynamic> json) =>
13
+
_$UploadPhotoResponseFromJson(json);
14
+
}
+172
lib/models/procedures/upload_photo_response.freezed.dart
+172
lib/models/procedures/upload_photo_response.freezed.dart
···
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 'upload_photo_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
+
UploadPhotoResponse _$UploadPhotoResponseFromJson(Map<String, dynamic> json) {
19
+
return _UploadPhotoResponse.fromJson(json);
20
+
}
21
+
22
+
/// @nodoc
23
+
mixin _$UploadPhotoResponse {
24
+
String get photoUri => throw _privateConstructorUsedError;
25
+
26
+
/// Serializes this UploadPhotoResponse to a JSON map.
27
+
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
28
+
29
+
/// Create a copy of UploadPhotoResponse
30
+
/// with the given fields replaced by the non-null parameter values.
31
+
@JsonKey(includeFromJson: false, includeToJson: false)
32
+
$UploadPhotoResponseCopyWith<UploadPhotoResponse> get copyWith =>
33
+
throw _privateConstructorUsedError;
34
+
}
35
+
36
+
/// @nodoc
37
+
abstract class $UploadPhotoResponseCopyWith<$Res> {
38
+
factory $UploadPhotoResponseCopyWith(
39
+
UploadPhotoResponse value,
40
+
$Res Function(UploadPhotoResponse) then,
41
+
) = _$UploadPhotoResponseCopyWithImpl<$Res, UploadPhotoResponse>;
42
+
@useResult
43
+
$Res call({String photoUri});
44
+
}
45
+
46
+
/// @nodoc
47
+
class _$UploadPhotoResponseCopyWithImpl<$Res, $Val extends UploadPhotoResponse>
48
+
implements $UploadPhotoResponseCopyWith<$Res> {
49
+
_$UploadPhotoResponseCopyWithImpl(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 UploadPhotoResponse
57
+
/// with the given fields replaced by the non-null parameter values.
58
+
@pragma('vm:prefer-inline')
59
+
@override
60
+
$Res call({Object? photoUri = null}) {
61
+
return _then(
62
+
_value.copyWith(
63
+
photoUri: null == photoUri
64
+
? _value.photoUri
65
+
: photoUri // ignore: cast_nullable_to_non_nullable
66
+
as String,
67
+
)
68
+
as $Val,
69
+
);
70
+
}
71
+
}
72
+
73
+
/// @nodoc
74
+
abstract class _$$UploadPhotoResponseImplCopyWith<$Res>
75
+
implements $UploadPhotoResponseCopyWith<$Res> {
76
+
factory _$$UploadPhotoResponseImplCopyWith(
77
+
_$UploadPhotoResponseImpl value,
78
+
$Res Function(_$UploadPhotoResponseImpl) then,
79
+
) = __$$UploadPhotoResponseImplCopyWithImpl<$Res>;
80
+
@override
81
+
@useResult
82
+
$Res call({String photoUri});
83
+
}
84
+
85
+
/// @nodoc
86
+
class __$$UploadPhotoResponseImplCopyWithImpl<$Res>
87
+
extends _$UploadPhotoResponseCopyWithImpl<$Res, _$UploadPhotoResponseImpl>
88
+
implements _$$UploadPhotoResponseImplCopyWith<$Res> {
89
+
__$$UploadPhotoResponseImplCopyWithImpl(
90
+
_$UploadPhotoResponseImpl _value,
91
+
$Res Function(_$UploadPhotoResponseImpl) _then,
92
+
) : super(_value, _then);
93
+
94
+
/// Create a copy of UploadPhotoResponse
95
+
/// with the given fields replaced by the non-null parameter values.
96
+
@pragma('vm:prefer-inline')
97
+
@override
98
+
$Res call({Object? photoUri = null}) {
99
+
return _then(
100
+
_$UploadPhotoResponseImpl(
101
+
photoUri: null == photoUri
102
+
? _value.photoUri
103
+
: photoUri // ignore: cast_nullable_to_non_nullable
104
+
as String,
105
+
),
106
+
);
107
+
}
108
+
}
109
+
110
+
/// @nodoc
111
+
@JsonSerializable()
112
+
class _$UploadPhotoResponseImpl implements _UploadPhotoResponse {
113
+
const _$UploadPhotoResponseImpl({required this.photoUri});
114
+
115
+
factory _$UploadPhotoResponseImpl.fromJson(Map<String, dynamic> json) =>
116
+
_$$UploadPhotoResponseImplFromJson(json);
117
+
118
+
@override
119
+
final String photoUri;
120
+
121
+
@override
122
+
String toString() {
123
+
return 'UploadPhotoResponse(photoUri: $photoUri)';
124
+
}
125
+
126
+
@override
127
+
bool operator ==(Object other) {
128
+
return identical(this, other) ||
129
+
(other.runtimeType == runtimeType &&
130
+
other is _$UploadPhotoResponseImpl &&
131
+
(identical(other.photoUri, photoUri) ||
132
+
other.photoUri == photoUri));
133
+
}
134
+
135
+
@JsonKey(includeFromJson: false, includeToJson: false)
136
+
@override
137
+
int get hashCode => Object.hash(runtimeType, photoUri);
138
+
139
+
/// Create a copy of UploadPhotoResponse
140
+
/// with the given fields replaced by the non-null parameter values.
141
+
@JsonKey(includeFromJson: false, includeToJson: false)
142
+
@override
143
+
@pragma('vm:prefer-inline')
144
+
_$$UploadPhotoResponseImplCopyWith<_$UploadPhotoResponseImpl> get copyWith =>
145
+
__$$UploadPhotoResponseImplCopyWithImpl<_$UploadPhotoResponseImpl>(
146
+
this,
147
+
_$identity,
148
+
);
149
+
150
+
@override
151
+
Map<String, dynamic> toJson() {
152
+
return _$$UploadPhotoResponseImplToJson(this);
153
+
}
154
+
}
155
+
156
+
abstract class _UploadPhotoResponse implements UploadPhotoResponse {
157
+
const factory _UploadPhotoResponse({required final String photoUri}) =
158
+
_$UploadPhotoResponseImpl;
159
+
160
+
factory _UploadPhotoResponse.fromJson(Map<String, dynamic> json) =
161
+
_$UploadPhotoResponseImpl.fromJson;
162
+
163
+
@override
164
+
String get photoUri;
165
+
166
+
/// Create a copy of UploadPhotoResponse
167
+
/// with the given fields replaced by the non-null parameter values.
168
+
@override
169
+
@JsonKey(includeFromJson: false, includeToJson: false)
170
+
_$$UploadPhotoResponseImplCopyWith<_$UploadPhotoResponseImpl> get copyWith =>
171
+
throw _privateConstructorUsedError;
172
+
}
+15
lib/models/procedures/upload_photo_response.g.dart
+15
lib/models/procedures/upload_photo_response.g.dart
···
1
+
// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+
part of 'upload_photo_response.dart';
4
+
5
+
// **************************************************************************
6
+
// JsonSerializableGenerator
7
+
// **************************************************************************
8
+
9
+
_$UploadPhotoResponseImpl _$$UploadPhotoResponseImplFromJson(
10
+
Map<String, dynamic> json,
11
+
) => _$UploadPhotoResponseImpl(photoUri: json['photoUri'] as String);
12
+
13
+
Map<String, dynamic> _$$UploadPhotoResponseImplToJson(
14
+
_$UploadPhotoResponseImpl instance,
15
+
) => <String, dynamic>{'photoUri': instance.photoUri};
+6
-3
lib/models/session.dart
+6
-3
lib/models/session.dart
···
1
1
import 'package:freezed_annotation/freezed_annotation.dart';
2
2
3
-
import 'atproto_session.dart';
4
-
5
3
part 'session.freezed.dart';
6
4
part 'session.g.dart';
7
5
8
6
@freezed
9
7
class Session with _$Session {
10
-
const factory Session({required AtprotoSession session, required String token}) = _Session;
8
+
const factory Session({
9
+
required String token,
10
+
required String refreshToken,
11
+
required DateTime expiresAt,
12
+
required String did,
13
+
}) = _Session;
11
14
12
15
factory Session.fromJson(Map<String, dynamic> json) => _$SessionFromJson(json);
13
16
}
+81
-38
lib/models/session.freezed.dart
+81
-38
lib/models/session.freezed.dart
···
21
21
22
22
/// @nodoc
23
23
mixin _$Session {
24
-
AtprotoSession get session => throw _privateConstructorUsedError;
25
24
String get token => throw _privateConstructorUsedError;
25
+
String get refreshToken => throw _privateConstructorUsedError;
26
+
DateTime get expiresAt => throw _privateConstructorUsedError;
27
+
String get did => throw _privateConstructorUsedError;
26
28
27
29
/// Serializes this Session to a JSON map.
28
30
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
···
38
40
factory $SessionCopyWith(Session value, $Res Function(Session) then) =
39
41
_$SessionCopyWithImpl<$Res, Session>;
40
42
@useResult
41
-
$Res call({AtprotoSession session, String token});
42
-
43
-
$AtprotoSessionCopyWith<$Res> get session;
43
+
$Res call({
44
+
String token,
45
+
String refreshToken,
46
+
DateTime expiresAt,
47
+
String did,
48
+
});
44
49
}
45
50
46
51
/// @nodoc
···
57
62
/// with the given fields replaced by the non-null parameter values.
58
63
@pragma('vm:prefer-inline')
59
64
@override
60
-
$Res call({Object? session = null, Object? token = null}) {
65
+
$Res call({
66
+
Object? token = null,
67
+
Object? refreshToken = null,
68
+
Object? expiresAt = null,
69
+
Object? did = null,
70
+
}) {
61
71
return _then(
62
72
_value.copyWith(
63
-
session: null == session
64
-
? _value.session
65
-
: session // ignore: cast_nullable_to_non_nullable
66
-
as AtprotoSession,
67
73
token: null == token
68
74
? _value.token
69
75
: token // ignore: cast_nullable_to_non_nullable
70
76
as String,
77
+
refreshToken: null == refreshToken
78
+
? _value.refreshToken
79
+
: refreshToken // ignore: cast_nullable_to_non_nullable
80
+
as String,
81
+
expiresAt: null == expiresAt
82
+
? _value.expiresAt
83
+
: expiresAt // ignore: cast_nullable_to_non_nullable
84
+
as DateTime,
85
+
did: null == did
86
+
? _value.did
87
+
: did // ignore: cast_nullable_to_non_nullable
88
+
as String,
71
89
)
72
90
as $Val,
73
91
);
74
92
}
75
-
76
-
/// Create a copy of Session
77
-
/// with the given fields replaced by the non-null parameter values.
78
-
@override
79
-
@pragma('vm:prefer-inline')
80
-
$AtprotoSessionCopyWith<$Res> get session {
81
-
return $AtprotoSessionCopyWith<$Res>(_value.session, (value) {
82
-
return _then(_value.copyWith(session: value) as $Val);
83
-
});
84
-
}
85
93
}
86
94
87
95
/// @nodoc
···
92
100
) = __$$SessionImplCopyWithImpl<$Res>;
93
101
@override
94
102
@useResult
95
-
$Res call({AtprotoSession session, String token});
96
-
97
-
@override
98
-
$AtprotoSessionCopyWith<$Res> get session;
103
+
$Res call({
104
+
String token,
105
+
String refreshToken,
106
+
DateTime expiresAt,
107
+
String did,
108
+
});
99
109
}
100
110
101
111
/// @nodoc
···
111
121
/// with the given fields replaced by the non-null parameter values.
112
122
@pragma('vm:prefer-inline')
113
123
@override
114
-
$Res call({Object? session = null, Object? token = null}) {
124
+
$Res call({
125
+
Object? token = null,
126
+
Object? refreshToken = null,
127
+
Object? expiresAt = null,
128
+
Object? did = null,
129
+
}) {
115
130
return _then(
116
131
_$SessionImpl(
117
-
session: null == session
118
-
? _value.session
119
-
: session // ignore: cast_nullable_to_non_nullable
120
-
as AtprotoSession,
121
132
token: null == token
122
133
? _value.token
123
134
: token // ignore: cast_nullable_to_non_nullable
124
135
as String,
136
+
refreshToken: null == refreshToken
137
+
? _value.refreshToken
138
+
: refreshToken // ignore: cast_nullable_to_non_nullable
139
+
as String,
140
+
expiresAt: null == expiresAt
141
+
? _value.expiresAt
142
+
: expiresAt // ignore: cast_nullable_to_non_nullable
143
+
as DateTime,
144
+
did: null == did
145
+
? _value.did
146
+
: did // ignore: cast_nullable_to_non_nullable
147
+
as String,
125
148
),
126
149
);
127
150
}
···
130
153
/// @nodoc
131
154
@JsonSerializable()
132
155
class _$SessionImpl implements _Session {
133
-
const _$SessionImpl({required this.session, required this.token});
156
+
const _$SessionImpl({
157
+
required this.token,
158
+
required this.refreshToken,
159
+
required this.expiresAt,
160
+
required this.did,
161
+
});
134
162
135
163
factory _$SessionImpl.fromJson(Map<String, dynamic> json) =>
136
164
_$$SessionImplFromJson(json);
137
165
138
166
@override
139
-
final AtprotoSession session;
167
+
final String token;
168
+
@override
169
+
final String refreshToken;
170
+
@override
171
+
final DateTime expiresAt;
140
172
@override
141
-
final String token;
173
+
final String did;
142
174
143
175
@override
144
176
String toString() {
145
-
return 'Session(session: $session, token: $token)';
177
+
return 'Session(token: $token, refreshToken: $refreshToken, expiresAt: $expiresAt, did: $did)';
146
178
}
147
179
148
180
@override
···
150
182
return identical(this, other) ||
151
183
(other.runtimeType == runtimeType &&
152
184
other is _$SessionImpl &&
153
-
(identical(other.session, session) || other.session == session) &&
154
-
(identical(other.token, token) || other.token == token));
185
+
(identical(other.token, token) || other.token == token) &&
186
+
(identical(other.refreshToken, refreshToken) ||
187
+
other.refreshToken == refreshToken) &&
188
+
(identical(other.expiresAt, expiresAt) ||
189
+
other.expiresAt == expiresAt) &&
190
+
(identical(other.did, did) || other.did == did));
155
191
}
156
192
157
193
@JsonKey(includeFromJson: false, includeToJson: false)
158
194
@override
159
-
int get hashCode => Object.hash(runtimeType, session, token);
195
+
int get hashCode =>
196
+
Object.hash(runtimeType, token, refreshToken, expiresAt, did);
160
197
161
198
/// Create a copy of Session
162
199
/// with the given fields replaced by the non-null parameter values.
···
174
211
175
212
abstract class _Session implements Session {
176
213
const factory _Session({
177
-
required final AtprotoSession session,
178
214
required final String token,
215
+
required final String refreshToken,
216
+
required final DateTime expiresAt,
217
+
required final String did,
179
218
}) = _$SessionImpl;
180
219
181
220
factory _Session.fromJson(Map<String, dynamic> json) = _$SessionImpl.fromJson;
182
221
183
-
@override
184
-
AtprotoSession get session;
185
222
@override
186
223
String get token;
224
+
@override
225
+
String get refreshToken;
226
+
@override
227
+
DateTime get expiresAt;
228
+
@override
229
+
String get did;
187
230
188
231
/// Create a copy of Session
189
232
/// with the given fields replaced by the non-null parameter values.
+9
-2
lib/models/session.g.dart
+9
-2
lib/models/session.g.dart
···
8
8
9
9
_$SessionImpl _$$SessionImplFromJson(Map<String, dynamic> json) =>
10
10
_$SessionImpl(
11
-
session: AtprotoSession.fromJson(json['session'] as Map<String, dynamic>),
12
11
token: json['token'] as String,
12
+
refreshToken: json['refreshToken'] as String,
13
+
expiresAt: DateTime.parse(json['expiresAt'] as String),
14
+
did: json['did'] as String,
13
15
);
14
16
15
17
Map<String, dynamic> _$$SessionImplToJson(_$SessionImpl instance) =>
16
-
<String, dynamic>{'session': instance.session, 'token': instance.token};
18
+
<String, dynamic>{
19
+
'token': instance.token,
20
+
'refreshToken': instance.refreshToken,
21
+
'expiresAt': instance.expiresAt.toIso8601String(),
22
+
'did': instance.did,
23
+
};
+22
lib/providers/actor_search_provider.dart
+22
lib/providers/actor_search_provider.dart
···
1
+
import 'package:flutter_riverpod/flutter_riverpod.dart';
2
+
3
+
import '../api.dart';
4
+
import '../models/profile.dart';
5
+
6
+
final actorSearchProvider = StateNotifierProvider<ActorSearchNotifier, Map<String, List<Profile>>>(
7
+
(ref) => ActorSearchNotifier(),
8
+
);
9
+
10
+
class ActorSearchNotifier extends StateNotifier<Map<String, List<Profile>>> {
11
+
ActorSearchNotifier() : super({});
12
+
13
+
Future<List<Profile>> search(String query) async {
14
+
if (query.isEmpty) return [];
15
+
if (state.containsKey(query)) {
16
+
return state[query]!;
17
+
}
18
+
final results = await apiService.searchActors(query);
19
+
state = {...state, query: results};
20
+
return results;
21
+
}
22
+
}
+116
-120
lib/providers/gallery_cache_provider.dart
+116
-120
lib/providers/gallery_cache_provider.dart
···
1
1
import 'dart:async';
2
2
import 'dart:io';
3
-
import 'dart:ui' as ui;
4
3
5
-
import 'package:bluesky_text/bluesky_text.dart';
6
4
import 'package:flutter/foundation.dart';
7
5
import 'package:grain/models/gallery_photo.dart';
6
+
import 'package:grain/models/procedures/apply_alts_update.dart';
7
+
import 'package:grain/models/procedures/procedures.dart';
8
+
import 'package:grain/providers/profile_provider.dart';
8
9
import 'package:image_picker/image_picker.dart';
9
10
import 'package:riverpod_annotation/riverpod_annotation.dart';
10
11
11
12
import '../api.dart';
13
+
import '../app_logger.dart';
12
14
import '../models/gallery.dart';
13
15
import '../models/gallery_item.dart';
14
16
import '../photo_manip.dart';
···
40
42
41
43
void setGalleriesForActor(String did, List<Gallery> galleries) {
42
44
setGalleries(galleries);
43
-
// Optionally, you could keep a mapping of actor DID to gallery URIs if needed
44
-
}
45
-
46
-
Future<List<Map<String, dynamic>>> _extractFacets(String text) async {
47
-
final blueskyText = BlueskyText(text);
48
-
final entities = blueskyText.entities;
49
-
final facets = await entities.toFacets();
50
-
return List<Map<String, dynamic>>.from(facets);
51
45
}
52
46
53
47
Future<void> toggleFavorite(String uri) async {
···
59
53
bool success = false;
60
54
String? newFavUri;
61
55
if (isFav) {
62
-
newFavUri = await apiService.createFavorite(galleryUri: uri);
63
-
success = newFavUri != null;
56
+
final response = await apiService.createFavorite(
57
+
request: CreateFavoriteRequest(subject: latestGallery.uri),
58
+
);
59
+
newFavUri = response.favoriteUri;
60
+
success = true;
64
61
} else {
65
-
success = await apiService.deleteRecord(latestGallery.viewer?.fav ?? uri);
62
+
final deleteResponse = await apiService.deleteFavorite(
63
+
request: DeleteFavoriteRequest(uri: latestGallery.viewer?.fav ?? uri),
64
+
);
65
+
success = deleteResponse.success;
66
66
newFavUri = null;
67
67
}
68
68
if (success) {
69
69
final newCount = (latestGallery.favCount ?? 0) + (isFav ? 1 : -1);
70
70
final updatedViewer = latestGallery.viewer?.copyWith(fav: newFavUri);
71
-
state = {...state, uri: latestGallery.copyWith(favCount: newCount, viewer: updatedViewer)};
71
+
final updatedGallery = latestGallery.copyWith(favCount: newCount, viewer: updatedViewer);
72
+
state = {...state, uri: updatedGallery};
73
+
74
+
// Push favorite change to profile provider favs
75
+
final profileProvider = ref.read(
76
+
profileNotifierProvider(apiService.currentUser!.did).notifier,
77
+
);
78
+
if (isFav) {
79
+
profileProvider.addFavorite(updatedGallery);
80
+
} else {
81
+
profileProvider.removeFavorite(updatedGallery.uri);
82
+
}
72
83
}
73
84
}
74
85
···
77
88
final gallery = state[galleryUri];
78
89
if (gallery == null) return;
79
90
// Call backend to delete the gallery item
80
-
await apiService.deleteRecord(galleryItemUri);
91
+
await apiService.deleteGalleryItem(request: DeleteGalleryItemRequest(uri: galleryItemUri));
81
92
// Remove by gallery item record URI, not photo URI
82
93
final updatedItems = gallery.items.where((p) => p.gallery?.item != galleryItemUri).toList();
83
94
final updatedGallery = gallery.copyWith(items: updatedItems);
84
95
state = {...state, galleryUri: updatedGallery};
85
96
}
86
97
87
-
/// Uploads multiple photos, gets their dimensions, resizes them, creates the photos, and adds them as gallery items.
88
-
/// At the end, polls for the updated gallery items and updates the cache.
89
-
/// Returns the list of new photoUris if successful, or empty list otherwise.
90
98
Future<List<String>> uploadAndAddPhotosToGallery({
91
99
required String galleryUri,
92
100
required List<XFile> xfiles,
93
101
int? startPosition,
94
102
bool includeExif = true,
103
+
void Function(int imageIndex, double progress)? onProgress,
95
104
}) async {
96
105
// Fetch the latest gallery from the API to avoid stale state
97
106
final latestGallery = await apiService.getGallery(uri: galleryUri);
···
103
112
final int positionOffset = startPosition ?? initialCount;
104
113
final List<String> photoUris = [];
105
114
int position = positionOffset;
106
-
for (final xfile in xfiles) {
115
+
for (int i = 0; i < xfiles.length; i++) {
116
+
final xfile = xfiles[i];
117
+
// Report progress if callback is provided
118
+
onProgress?.call(i, 0.0);
119
+
107
120
final file = File(xfile.path);
108
121
// Parse EXIF if requested
109
122
final exif = includeExif ? await parseAndNormalizeExif(file: file) : null;
123
+
124
+
// Simulate progress steps
125
+
for (int p = 1; p <= 10; p++) {
126
+
await Future.delayed(const Duration(milliseconds: 30));
127
+
onProgress?.call(i, p / 10.0);
128
+
}
129
+
110
130
// Resize the image
111
131
final resizedResult = await compute<File, ResizeResult>((f) => resizeImage(file: f), file);
112
132
// Upload the blob
113
-
final blobResult = await apiService.uploadBlob(resizedResult.file);
114
-
if (blobResult == null) continue;
115
-
// Get image dimensions
116
-
final bytes = await xfile.readAsBytes();
117
-
final completer = Completer<Map<String, int>>();
118
-
ui.decodeImageFromList(bytes, (image) {
119
-
completer.complete({'width': image.width, 'height': image.height});
120
-
});
121
-
final dims = await completer.future;
122
-
// Create the photo
123
-
final photoUri = await apiService.createPhoto(
124
-
blob: blobResult,
125
-
width: dims['width']!,
126
-
height: dims['height']!,
127
-
);
128
-
if (photoUri == null) continue;
129
-
133
+
final res = await apiService.uploadPhoto(resizedResult.file);
134
+
if (res.photoUri.isEmpty) continue;
130
135
// If EXIF data was found, create photo exif record
131
136
if (exif != null) {
132
-
await apiService.createPhotoExif(
133
-
photo: photoUri,
134
-
dateTimeOriginal: exif['dateTimeOriginal'] as String?,
135
-
exposureTime: exif['exposureTime'] as int?,
136
-
fNumber: exif['fNumber'] as int?,
137
-
flash: exif['flash'] as String?,
138
-
focalLengthIn35mmFormat: exif['focalLengthIn35mmFilm'] as int?,
139
-
iSO: exif['iSOSpeedRatings'] as int?,
140
-
lensMake: exif['lensMake'] as String?,
141
-
lensModel: exif['lensModel'] as String?,
142
-
make: exif['make'] as String?,
143
-
model: exif['model'] as String?,
137
+
await apiService.createExif(
138
+
request: CreateExifRequest(
139
+
photo: res.photoUri,
140
+
dateTimeOriginal: exif['dateTimeOriginal'],
141
+
exposureTime: exif['exposureTime'],
142
+
fNumber: exif['fNumber'],
143
+
flash: exif['flash'],
144
+
focalLengthIn35mmFormat: exif['focalLengthIn35mmFilm'],
145
+
iSO: exif['iSOSpeedRatings'],
146
+
lensMake: exif['lensMake'],
147
+
lensModel: exif['lensModel'],
148
+
make: exif['make'],
149
+
model: exif['model'],
150
+
),
144
151
);
145
152
}
146
153
147
154
// Create the gallery item
148
155
await apiService.createGalleryItem(
149
-
galleryUri: galleryUri,
150
-
photoUri: photoUri,
151
-
position: position,
156
+
request: CreateGalleryItemRequest(
157
+
galleryUri: galleryUri,
158
+
photoUri: res.photoUri,
159
+
position: position,
160
+
),
152
161
);
153
-
photoUris.add(photoUri);
162
+
photoUris.add(res.photoUri);
154
163
position++;
155
164
}
156
-
// Poll for updated gallery items
157
-
final expectedCount = (gallery?.items.length ?? 0) + photoUris.length;
158
-
await apiService.pollGalleryItems(galleryUri: galleryUri, expectedCount: expectedCount);
159
165
// Fetch the updated gallery and update the cache
160
166
final updatedGallery = await apiService.getGallery(uri: galleryUri);
161
167
if (updatedGallery != null) {
···
171
177
required String description,
172
178
required List<XFile> xfiles,
173
179
bool includeExif = true,
180
+
void Function(int imageIndex, double progress)? onProgress,
174
181
}) async {
175
-
// Extract facets from description
176
-
final facetsList = await _extractFacets(description);
177
-
final facets = facetsList.isEmpty ? null : facetsList;
178
-
// Create the gallery with facets
179
-
final galleryUri = await apiService.createGallery(
180
-
title: title,
181
-
description: description,
182
-
facets: facets,
182
+
final res = await apiService.createGallery(
183
+
request: CreateGalleryRequest(title: title, description: description),
183
184
);
184
-
if (galleryUri == null) return (null, <String>[]);
185
185
// Upload and add photos
186
186
final photoUris = await uploadAndAddPhotosToGallery(
187
-
galleryUri: galleryUri,
187
+
galleryUri: res.galleryUri,
188
188
xfiles: xfiles,
189
189
includeExif: includeExif,
190
+
onProgress: onProgress,
190
191
);
191
-
return (galleryUri, photoUris);
192
+
return (res.galleryUri, photoUris);
192
193
}
193
194
194
-
/// Creates gallery items for existing photoUris, polls for updated gallery items, and updates the cache.
195
+
/// Creates gallery items for existing photoUris and updates the cache.
195
196
/// Returns the list of new gallery item URIs if successful, or empty list otherwise.
196
197
Future<List<String>> addGalleryItemsToGallery({
197
198
required String galleryUri,
···
210
211
int position = positionOffset;
211
212
for (final photoUri in photoUris) {
212
213
// Create the gallery item
213
-
final itemUri = await apiService.createGalleryItem(
214
-
galleryUri: galleryUri,
215
-
photoUri: photoUri,
216
-
position: position,
214
+
final res = await apiService.createGalleryItem(
215
+
request: CreateGalleryItemRequest(
216
+
galleryUri: galleryUri,
217
+
photoUri: photoUri,
218
+
position: position,
219
+
),
217
220
);
218
-
if (itemUri != null) {
219
-
galleryItemUris.add(itemUri);
221
+
if (res.itemUri.isNotEmpty) {
222
+
galleryItemUris.add(res.itemUri);
220
223
position++;
221
224
}
222
225
}
223
-
// Poll for updated gallery items
224
-
final expectedCount = (gallery?.items.length ?? 0) + galleryItemUris.length;
225
-
await apiService.pollGalleryItems(galleryUri: galleryUri, expectedCount: expectedCount);
226
226
// Fetch the updated gallery and update the cache
227
227
final updatedGallery = await apiService.getGallery(uri: galleryUri);
228
228
if (updatedGallery != null) {
···
233
233
234
234
/// Deletes a gallery from the backend and removes it from the cache.
235
235
Future<void> deleteGallery(String uri) async {
236
-
// Fetch the latest gallery from backend to ensure all items are deleted
237
-
final gallery = await apiService.getGallery(uri: uri);
238
-
if (gallery != null) {
239
-
// Delete all gallery item records
240
-
for (final item in gallery.items) {
241
-
final itemUri = item.gallery?.item;
242
-
if (itemUri != null && itemUri.isNotEmpty) {
243
-
await apiService.deleteRecord(itemUri);
244
-
}
245
-
}
246
-
}
247
-
await apiService.deleteRecord(uri);
236
+
await apiService.deleteGallery(request: DeleteGalleryRequest(uri: uri));
248
237
removeGallery(uri);
249
238
}
250
239
···
269
258
for (int i = 0; i < orderedItems.length; i++) {
270
259
orderedItems[i] = orderedItems[i].copyWith(position: i);
271
260
}
272
-
await apiService.updateGallerySortOrder(galleryUri: galleryUri, orderedItems: orderedItems);
261
+
final res = await apiService.applySort(
262
+
request: ApplySortRequest(
263
+
writes: orderedItems
264
+
.map((item) => ApplySortUpdate(itemUri: item.uri, position: item.position))
265
+
.toList(),
266
+
),
267
+
);
268
+
if (!res.success) {
269
+
appLogger.w('Failed to reorder gallery items for $galleryUri');
270
+
return;
271
+
}
273
272
// Update cache with new order
274
273
final updatedPhotos = orderedItems
275
274
.where((item) => gallery.items.any((p) => p.uri == item.item))
···
282
281
state = {...state, galleryUri: updatedGallery};
283
282
}
284
283
285
-
/// Updates gallery details (title, description), polls for cid change, and updates cache.
284
+
/// Updates gallery details (title, description) and updates cache.
286
285
Future<bool> updateGalleryDetails({
287
286
required String galleryUri,
288
287
required String title,
289
288
required String description,
290
289
required String createdAt,
291
290
}) async {
292
-
final prevGallery = state[galleryUri];
293
-
final prevCid = prevGallery?.cid;
294
-
// Extract facets from description
295
-
final facetsList = await _extractFacets(description);
296
-
final facets = facetsList.isEmpty ? null : facetsList;
297
-
final success = await apiService.updateGallery(
298
-
galleryUri: galleryUri,
299
-
title: title,
300
-
description: description,
301
-
createdAt: createdAt,
302
-
facets: facets,
303
-
);
304
-
if (success) {
305
-
final start = DateTime.now();
306
-
const timeout = Duration(seconds: 20);
307
-
const pollInterval = Duration(milliseconds: 1000);
308
-
Gallery? updatedGallery;
309
-
while (DateTime.now().difference(start) < timeout) {
310
-
updatedGallery = await apiService.getGallery(uri: galleryUri);
311
-
if (updatedGallery != null && updatedGallery.cid != prevCid) {
312
-
break;
313
-
}
314
-
await Future.delayed(pollInterval);
315
-
}
316
-
if (updatedGallery != null) {
317
-
state = {...state, galleryUri: updatedGallery};
318
-
}
291
+
try {
292
+
await apiService.updateGallery(
293
+
request: UpdateGalleryRequest(
294
+
galleryUri: galleryUri,
295
+
title: title,
296
+
description: description,
297
+
),
298
+
);
299
+
} catch (e, st) {
300
+
appLogger.e('Failed to update gallery details: $e', stackTrace: st);
301
+
return false;
302
+
}
303
+
final updatedGallery = await apiService.getGallery(uri: galleryUri);
304
+
if (updatedGallery != null) {
305
+
state = {...state, galleryUri: updatedGallery};
319
306
}
320
-
return success;
307
+
return true;
321
308
}
322
309
323
310
/// Fetches timeline galleries from the API and updates the cache.
···
335
322
required String galleryUri,
336
323
required List<Map<String, dynamic>> altUpdates,
337
324
}) async {
338
-
final success = await apiService.updatePhotos(altUpdates);
339
-
if (!success) return false;
325
+
final res = await apiService.applyAlts(
326
+
request: ApplyAltsRequest(
327
+
writes: altUpdates.map((update) {
328
+
return ApplyAltsUpdate(
329
+
photoUri: update['photoUri'] as String,
330
+
alt: update['alt'] as String,
331
+
);
332
+
}).toList(),
333
+
),
334
+
);
335
+
if (!res.success) return false;
340
336
341
337
// Update the gallery photos' alt text in the cache manually
342
338
final gallery = state[galleryUri];
+1
-1
lib/providers/gallery_cache_provider.g.dart
+1
-1
lib/providers/gallery_cache_provider.g.dart
···
6
6
// RiverpodGenerator
7
7
// **************************************************************************
8
8
9
-
String _$galleryCacheHash() => r'cd0665a1f246bd700195cf5ce50893ba73b878f9';
9
+
String _$galleryCacheHash() => r'd604bfc71f008251a36d7943b99294728c31de1f';
10
10
11
11
/// Holds a cache of galleries by URI.
12
12
///
+10
-24
lib/providers/gallery_thread_cache_provider.dart
+10
-24
lib/providers/gallery_thread_cache_provider.dart
···
1
-
import 'package:bluesky_text/bluesky_text.dart';
2
1
import 'package:grain/api.dart';
3
2
import 'package:grain/models/comment.dart';
4
3
import 'package:grain/models/gallery.dart';
4
+
import 'package:grain/models/procedures/create_comment_request.dart';
5
+
import 'package:grain/models/procedures/delete_comment_request.dart';
5
6
import 'package:grain/providers/gallery_cache_provider.dart';
6
7
import 'package:riverpod_annotation/riverpod_annotation.dart';
7
8
···
65
66
}
66
67
}
67
68
68
-
Future<List<Map<String, dynamic>>> _extractFacets(String text) async {
69
-
final blueskyText = BlueskyText(text);
70
-
final entities = blueskyText.entities;
71
-
final facets = await entities.toFacets();
72
-
return List<Map<String, dynamic>>.from(facets);
73
-
}
74
-
75
69
Future<bool> createComment({required String text, String? replyTo, String? focus}) async {
76
70
try {
77
-
final facetsList = await _extractFacets(text);
78
-
final facets = facetsList.isEmpty ? null : facetsList;
79
-
final uri = await apiService.createComment(
71
+
final request = CreateCommentRequest(
80
72
text: text,
81
73
subject: galleryUri,
82
74
replyTo: replyTo,
83
-
facets: facets,
84
75
focus: focus,
85
76
);
86
-
if (uri != null) {
87
-
final thread = await apiService.pollGalleryThreadComments(
88
-
galleryUri: galleryUri,
89
-
expectedCount: state.comments.length + 1,
90
-
);
77
+
final res = await apiService.createComment(request: request);
78
+
if (res.commentUri.isNotEmpty) {
79
+
final thread = await apiService.getGalleryThread(uri: galleryUri);
91
80
if (thread != null) {
92
81
state = state.copyWith(gallery: thread.gallery, comments: thread.comments);
93
82
// Update the gallery cache with the latest gallery
···
102
91
}
103
92
104
93
Future<bool> deleteComment(Comment comment) async {
105
-
final deleted = await apiService.deleteRecord(comment.uri);
106
-
if (!deleted) return false;
107
-
final expectedCount = state.comments.length - 1;
108
-
final thread = await apiService.pollGalleryThreadComments(
109
-
galleryUri: galleryUri,
110
-
expectedCount: expectedCount,
111
-
);
94
+
final request = DeleteCommentRequest(uri: comment.uri);
95
+
final res = await apiService.deleteComment(request: request);
96
+
if (!res.success) return false;
97
+
final thread = await apiService.getGalleryThread(uri: galleryUri);
112
98
if (thread != null) {
113
99
state = state.copyWith(gallery: thread.gallery, comments: thread.comments);
114
100
// Update the gallery cache with the latest gallery
+1
-1
lib/providers/gallery_thread_cache_provider.g.dart
+1
-1
lib/providers/gallery_thread_cache_provider.g.dart
···
6
6
// RiverpodGenerator
7
7
// **************************************************************************
8
8
9
-
String _$galleryThreadHash() => r'fa270baa7dd229fdd6b4e2610cf232aed53ed3db';
9
+
String _$galleryThreadHash() => r'80fa9b4e19b9d7606654fff8549516d4654dfa87';
10
10
11
11
/// Copied from Dart SDK
12
12
class _SystemHash {
+60
-70
lib/providers/profile_provider.dart
+60
-70
lib/providers/profile_provider.dart
···
1
1
import 'dart:io';
2
2
3
3
import 'package:bluesky_text/bluesky_text.dart';
4
+
import 'package:flutter/foundation.dart';
4
5
import 'package:grain/api.dart';
5
6
import 'package:grain/models/gallery.dart';
6
-
import 'package:grain/models/profile.dart';
7
+
import 'package:grain/models/procedures/create_follow_request.dart';
8
+
import 'package:grain/models/procedures/delete_follow_request.dart';
9
+
import 'package:grain/models/procedures/update_profile_request.dart';
7
10
import 'package:grain/models/profile_with_galleries.dart';
11
+
import 'package:grain/photo_manip.dart';
8
12
import 'package:grain/providers/gallery_cache_provider.dart';
9
13
import 'package:image_picker/image_picker.dart';
10
14
import 'package:riverpod_annotation/riverpod_annotation.dart';
···
18
22
return _fetchProfile(did);
19
23
}
20
24
21
-
// @TODO: Facets don't always render correctly.
22
-
List<Map<String, dynamic>>? _filterValidFacets(
23
-
List<Map<String, dynamic>>? computedFacets,
24
-
String desc,
25
-
) {
26
-
if (computedFacets == null) return null;
27
-
return computedFacets.where((facet) {
28
-
final index = facet['index'];
29
-
if (index is Map) {
30
-
final start = index['byteStart'] ?? 0;
31
-
final end = index['byteEnd'] ?? 0;
32
-
return start is int && end is int && start >= 0 && end > start && end <= desc.length;
33
-
}
34
-
final start = facet['index'] ?? facet['offset'] ?? 0;
35
-
final end = facet['end'];
36
-
final length = facet['length'];
37
-
if (end is int && start is int) {
38
-
return start >= 0 && end > start && end <= desc.length;
39
-
} else if (length is int && start is int) {
40
-
return start >= 0 && length > 0 && start + length <= desc.length;
41
-
}
42
-
return false;
43
-
}).toList();
44
-
}
45
-
46
-
// Extract facet computation and filtering for reuse
47
-
Future<List<Map<String, dynamic>>?> computeAndFilterFacets(String? description) async {
25
+
// Extract facets
26
+
Future<List<Map<String, dynamic>>?> _extractFacets(String? description) async {
48
27
final desc = description ?? '';
49
28
if (desc.isEmpty) return null;
50
29
try {
51
30
final blueskyText = BlueskyText(desc);
52
31
final entities = blueskyText.entities;
53
-
final computedFacets = await entities.toFacets();
54
-
return _filterValidFacets(computedFacets, desc);
32
+
return entities.toFacets();
55
33
} catch (_) {
56
34
return null;
57
35
}
···
62
40
final galleries = await apiService.fetchActorGalleries(did: did);
63
41
final favs = await apiService.getActorFavs(did: did);
64
42
if (profile != null) {
65
-
final facets = await computeAndFilterFacets(profile.description);
43
+
final facets = await _extractFacets(profile.description);
66
44
return ProfileWithGalleries(
67
45
profile: profile.copyWith(descriptionFacets: facets),
68
46
galleries: galleries,
···
82
60
required String description,
83
61
dynamic avatarFile,
84
62
}) async {
85
-
final currentProfile = state.value?.profile;
86
-
final isUnchanged =
87
-
currentProfile != null &&
88
-
currentProfile.displayName == displayName &&
89
-
currentProfile.description == description &&
90
-
avatarFile == null;
91
-
if (isUnchanged) {
92
-
// No changes, skip API call
93
-
return true;
94
-
}
95
63
File? file;
96
64
if (avatarFile is XFile) {
97
65
file = File(avatarFile.path);
···
100
68
} else {
101
69
file = null;
102
70
}
103
-
final success = await apiService.updateProfile(
104
-
displayName: displayName,
105
-
description: description,
106
-
avatarFile: file,
71
+
final profileRes = await apiService.updateProfile(
72
+
request: UpdateProfileRequest(displayName: displayName, description: description),
107
73
);
108
-
if (success) {
109
-
final start = DateTime.now();
110
-
const timeout = Duration(seconds: 20);
111
-
const pollInterval = Duration(milliseconds: 1000);
112
-
Profile? updated;
113
-
final prevCid = state.value?.profile.cid;
114
-
state = const AsyncValue.loading(); // Force UI to show loading and rebuild
115
-
while (DateTime.now().difference(start) < timeout) {
116
-
updated = await apiService.fetchProfile(did: did);
117
-
if (updated != null && updated.cid != prevCid) {
118
-
break;
119
-
}
120
-
await Future.delayed(pollInterval);
121
-
}
122
-
// Always assign a new instance to state
74
+
bool avatarSuccess = true;
75
+
if (file != null) {
76
+
final resizedResult = await compute<File, ResizeResult>((f) => resizeImage(file: f), file);
77
+
final avatarRes = await apiService.updateAvatar(avatarFile: resizedResult.file);
78
+
avatarSuccess = avatarRes.success;
79
+
}
80
+
// Refetch updated profile if update succeeded
81
+
if (profileRes.success || avatarSuccess) {
82
+
final updated = await apiService.fetchProfile(did: did);
123
83
if (updated != null) {
124
84
final galleries = await apiService.fetchActorGalleries(did: did);
125
-
final facets = await computeAndFilterFacets(updated.description);
126
-
// Update the gallery cache provider
85
+
final facets = await _extractFacets(updated.description);
127
86
ref.read(galleryCacheProvider.notifier).setGalleriesForActor(did, galleries);
128
87
state = AsyncValue.data(
129
88
ProfileWithGalleries(
···
134
93
);
135
94
} else {
136
95
state = const AsyncValue.data(null);
137
-
}
138
-
if (updated == null) {
139
96
await refresh();
140
97
}
98
+
return true;
99
+
} else {
100
+
await refresh();
101
+
return false;
141
102
}
142
-
return success;
143
103
}
144
104
145
105
Future<void> toggleFollow(String? followerDid) async {
···
150
110
final followUri = viewer?.following;
151
111
if (followUri != null && followUri.isNotEmpty) {
152
112
// Unfollow
153
-
final success = await apiService.deleteRecord(followUri);
154
-
if (success) {
113
+
final res = await apiService.deleteFollow(request: DeleteFollowRequest(uri: followUri));
114
+
if (res.success) {
155
115
final updatedProfile = profile.copyWith(
156
116
viewer: viewer?.copyWith(following: null),
157
117
followersCount: (profile.followersCount ?? 1) - 1,
···
166
126
}
167
127
} else {
168
128
// Follow
169
-
final newFollowUri = await apiService.createFollow(followeeDid: did);
170
-
if (newFollowUri != null) {
129
+
final res = await apiService.createFollow(request: CreateFollowRequest(subject: followerDid));
130
+
if (res.followUri.isNotEmpty) {
171
131
final updatedProfile = profile.copyWith(
172
-
viewer: viewer?.copyWith(following: newFollowUri),
132
+
viewer: viewer?.copyWith(following: res.followUri),
173
133
followersCount: (profile.followersCount ?? 0) + 1,
174
134
);
175
135
state = AsyncValue.data(
···
212
172
profile: updatedProfile,
213
173
galleries: updatedGalleries,
214
174
favs: currentProfile.favs,
175
+
),
176
+
);
177
+
}
178
+
}
179
+
180
+
/// Adds a gallery to the user's favorites in the profile state.
181
+
void addFavorite(Gallery gallery) {
182
+
final currentProfile = state.value;
183
+
if (currentProfile != null) {
184
+
final updatedFavs = [gallery, ...?currentProfile.favs];
185
+
state = AsyncValue.data(
186
+
ProfileWithGalleries(
187
+
profile: currentProfile.profile,
188
+
galleries: currentProfile.galleries,
189
+
favs: updatedFavs,
190
+
),
191
+
);
192
+
}
193
+
}
194
+
195
+
/// Removes a gallery from the user's favorites in the profile state by URI.
196
+
void removeFavorite(String galleryUri) {
197
+
final currentProfile = state.value;
198
+
if (currentProfile != null) {
199
+
final updatedFavs = (currentProfile.favs ?? []).where((g) => g.uri != galleryUri).toList();
200
+
state = AsyncValue.data(
201
+
ProfileWithGalleries(
202
+
profile: currentProfile.profile,
203
+
galleries: currentProfile.galleries,
204
+
favs: updatedFavs,
215
205
),
216
206
);
217
207
}
+1
-1
lib/providers/profile_provider.g.dart
+1
-1
lib/providers/profile_provider.g.dart
···
6
6
// RiverpodGenerator
7
7
// **************************************************************************
8
8
9
-
String _$profileNotifierHash() => r'2ec9237c3a60bff58175d2d39f37b050eecdba78';
9
+
String _$profileNotifierHash() => r'4b8e3a8d4363beb885ead4ae7ce9c52101a6bf96';
10
10
11
11
/// Copied from Dart SDK
12
12
class _SystemHash {
+393
-198
lib/screens/create_gallery_page.dart
+393
-198
lib/screens/create_gallery_page.dart
···
11
11
import 'package:grain/models/gallery.dart';
12
12
import 'package:grain/providers/profile_provider.dart';
13
13
import 'package:grain/widgets/app_button.dart';
14
+
import 'package:grain/widgets/faceted_text_field.dart';
14
15
import 'package:grain/widgets/plain_text_field.dart';
16
+
import 'package:grain/widgets/upload_progress_overlay.dart';
15
17
import 'package:image_picker/image_picker.dart';
16
18
17
19
import '../providers/gallery_cache_provider.dart';
···
34
36
}
35
37
36
38
class _CreateGalleryPageState extends State<CreateGalleryPage> {
39
+
bool isValidGraphemeLength(String input, int maxLength) {
40
+
return input.characters.length <= maxLength;
41
+
}
42
+
37
43
final _titleController = TextEditingController();
38
44
final _descController = TextEditingController();
39
45
final List<GalleryImage> _images = [];
40
46
bool _submitting = false;
41
47
bool _includeExif = true;
42
48
49
+
// Upload progress state
50
+
bool _showUploadOverlay = false;
51
+
int _currentUploadIndex = 0;
52
+
double _currentUploadProgress = 0.0;
53
+
43
54
@override
44
55
void initState() {
45
56
super.initState();
···
50
61
_titleController.addListener(() {
51
62
setState(() {});
52
63
});
64
+
_descController.addListener(() {
65
+
setState(() {});
66
+
});
67
+
}
68
+
69
+
@override
70
+
void dispose() {
71
+
_titleController.dispose();
72
+
_descController.dispose();
73
+
super.dispose();
53
74
}
54
75
55
76
Future<String> _computeMd5(XFile xfile) async {
···
59
80
60
81
Future<void> _pickImages() async {
61
82
if (widget.gallery != null) return; // Only allow picking on create
83
+
84
+
final remainingSlots = 10 - _images.length;
85
+
if (remainingSlots <= 0) {
86
+
if (mounted) {
87
+
ScaffoldMessenger.of(context).showSnackBar(
88
+
const SnackBar(
89
+
content: Text('You\'ve already added the maximum of 10 photos.'),
90
+
duration: Duration(seconds: 2),
91
+
),
92
+
);
93
+
}
94
+
return;
95
+
}
96
+
62
97
final picker = ImagePicker();
63
98
final picked = await picker.pickMultiImage(imageQuality: 85);
64
99
if (picked.isNotEmpty) {
···
68
103
final hash = await _computeMd5(img.file);
69
104
existingHashes.add(hash);
70
105
}
106
+
71
107
final newImages = <GalleryImage>[];
72
108
int skipped = 0;
109
+
int limitReached = 0;
110
+
73
111
for (final xfile in picked) {
112
+
// Check if we've reached the limit
113
+
if (_images.length + newImages.length >= 10) {
114
+
limitReached = picked.length - picked.indexOf(xfile);
115
+
break;
116
+
}
117
+
74
118
final hash = await _computeMd5(xfile);
75
119
if (!existingHashes.contains(hash)) {
76
120
newImages.add(GalleryImage(file: xfile, isExisting: false));
···
79
123
skipped++;
80
124
}
81
125
}
126
+
82
127
if (newImages.isNotEmpty) {
83
128
setState(() {
84
129
_images.addAll(newImages);
85
130
});
86
131
}
87
-
if (skipped > 0 && mounted) {
88
-
ScaffoldMessenger.of(context).showSnackBar(
89
-
SnackBar(
90
-
content: Text('Some images were skipped (duplicates).'),
91
-
duration: const Duration(seconds: 2),
92
-
),
93
-
);
132
+
133
+
// Show appropriate feedback messages
134
+
if (mounted) {
135
+
String message = '';
136
+
if (limitReached > 0 && skipped > 0) {
137
+
message =
138
+
'Added ${newImages.length} photos. $skipped duplicates and $limitReached photos skipped (10 photo limit).';
139
+
} else if (limitReached > 0) {
140
+
message =
141
+
'Added ${newImages.length} photos. $limitReached photos skipped (10 photo limit).';
142
+
} else if (skipped > 0) {
143
+
message = 'Added ${newImages.length} photos. $skipped duplicates skipped.';
144
+
}
145
+
146
+
if (message.isNotEmpty) {
147
+
ScaffoldMessenger.of(
148
+
context,
149
+
).showSnackBar(SnackBar(content: Text(message), duration: const Duration(seconds: 3)));
150
+
}
94
151
}
95
152
}
96
153
}
···
102
159
}
103
160
104
161
Future<void> _submit() async {
162
+
FocusScope.of(context).unfocus();
163
+
164
+
final titleGraphemes = _titleController.text.characters.length;
165
+
final descGraphemes = _descController.text.characters.length;
166
+
if (titleGraphemes > 100 || descGraphemes > 1000) {
167
+
if (mounted) {
168
+
await showDialog(
169
+
context: context,
170
+
builder: (context) => AlertDialog(
171
+
title: const Text('Character Limit Exceeded'),
172
+
content: Text(
173
+
titleGraphemes > 100
174
+
? 'Title must be 100 characters or fewer.'
175
+
: 'Description must be 1000 characters or fewer.',
176
+
),
177
+
actions: [
178
+
TextButton(child: const Text('OK'), onPressed: () => Navigator.of(context).pop()),
179
+
],
180
+
),
181
+
);
182
+
}
183
+
return;
184
+
}
105
185
if (widget.gallery == null && _images.length > 10) {
106
186
if (mounted) {
107
187
await showDialog(
···
109
189
builder: (context) => AlertDialog(
110
190
title: const Text('Photo Limit'),
111
191
content: const Text(
112
-
'You can only add up to 10 photos on initial create but can add more later on.',
192
+
'You can only add up to 10 photos initially but you can add more later on.',
113
193
),
114
194
actions: [
115
195
TextButton(child: const Text('OK'), onPressed: () => Navigator.of(context).pop()),
···
122
202
setState(() => _submitting = true);
123
203
String? galleryUri;
124
204
final container = ProviderScope.containerOf(context, listen: false);
125
-
if (widget.gallery == null) {
126
-
// Use provider to create gallery and add photos
127
-
final newImages = _images.where((img) => !img.isExisting).toList();
128
-
final galleryCache = container.read(galleryCacheProvider.notifier);
129
-
final (createdUri, newPhotoUris) = await galleryCache.createGalleryAndAddPhotos(
130
-
title: _titleController.text.trim(),
131
-
description: _descController.text.trim(),
132
-
xfiles: newImages.map((img) => img.file).toList(),
133
-
includeExif: _includeExif,
134
-
);
135
-
galleryUri = createdUri;
136
-
// Update profile provider state to include new gallery
137
-
if (galleryUri != null && mounted) {
138
-
final newGallery = container.read(galleryCacheProvider)[galleryUri];
139
-
final profileNotifier = container.read(
140
-
profileNotifierProvider(apiService.currentUser!.did).notifier,
205
+
try {
206
+
if (widget.gallery == null) {
207
+
final newImages = _images.where((img) => !img.isExisting).toList();
208
+
final galleryCache = container.read(galleryCacheProvider.notifier);
209
+
if (newImages.isNotEmpty) {
210
+
setState(() {
211
+
_showUploadOverlay = true;
212
+
_currentUploadIndex = 0;
213
+
_currentUploadProgress = 0.0;
214
+
});
215
+
}
216
+
List<XFile> xfiles = newImages.map((img) => img.file).toList();
217
+
String? createdUri;
218
+
final (uri, photoUris) = await galleryCache.createGalleryAndAddPhotos(
219
+
title: _titleController.text.trim(),
220
+
description: _descController.text.trim(),
221
+
xfiles: xfiles,
222
+
includeExif: _includeExif,
223
+
onProgress: (int idx, double prog) {
224
+
setState(() {
225
+
_currentUploadIndex = idx;
226
+
_currentUploadProgress = prog;
227
+
});
228
+
},
141
229
);
142
-
if (newGallery != null) {
143
-
profileNotifier.addGalleryToProfile(newGallery);
230
+
createdUri = uri;
231
+
setState(() {
232
+
_showUploadOverlay = false;
233
+
});
234
+
galleryUri = createdUri;
235
+
// Update profile provider state to include new gallery
236
+
if (galleryUri != null && mounted) {
237
+
final newGallery = container.read(galleryCacheProvider)[galleryUri];
238
+
final profileNotifier = container.read(
239
+
profileNotifierProvider(apiService.currentUser!.did).notifier,
240
+
);
241
+
if (newGallery != null) {
242
+
profileNotifier.addGalleryToProfile(newGallery);
243
+
}
144
244
}
245
+
} else {
246
+
galleryUri = widget.gallery!.uri;
247
+
final galleryCache = container.read(galleryCacheProvider.notifier);
248
+
await galleryCache.updateGalleryDetails(
249
+
galleryUri: galleryUri,
250
+
title: _titleController.text.trim(),
251
+
description: _descController.text.trim(),
252
+
createdAt: widget.gallery!.createdAt ?? DateTime.now().toUtc().toIso8601String(),
253
+
);
145
254
}
146
-
} else {
147
-
galleryUri = widget.gallery!.uri;
148
-
final galleryCache = container.read(galleryCacheProvider.notifier);
149
-
await galleryCache.updateGalleryDetails(
150
-
galleryUri: galleryUri,
151
-
title: _titleController.text.trim(),
152
-
description: _descController.text.trim(),
153
-
createdAt: widget.gallery!.createdAt ?? DateTime.now().toUtc().toIso8601String(),
154
-
);
155
-
}
156
-
setState(() => _submitting = false);
157
-
if (mounted && galleryUri != null) {
158
-
FocusScope.of(context).unfocus(); // Force keyboard to close
159
-
Navigator.of(context).pop(galleryUri); // Pop with galleryUri if created
160
-
if (widget.gallery == null) {
161
-
Navigator.of(context).push(
162
-
MaterialPageRoute(
163
-
builder: (context) =>
164
-
GalleryPage(uri: galleryUri!, currentUserDid: apiService.currentUser?.did),
255
+
setState(() => _submitting = false);
256
+
if (mounted && galleryUri != null) {
257
+
FocusScope.of(context).unfocus(); // Force keyboard to close
258
+
Navigator.of(context).pop(galleryUri); // Pop with galleryUri if created
259
+
if (widget.gallery == null) {
260
+
Navigator.of(context).push(
261
+
MaterialPageRoute(
262
+
builder: (context) =>
263
+
GalleryPage(uri: galleryUri!, currentUserDid: apiService.currentUser?.did),
264
+
),
265
+
);
266
+
}
267
+
} else if (mounted) {
268
+
FocusScope.of(context).unfocus(); // Force keyboard to close
269
+
Navigator.of(context).pop();
270
+
}
271
+
} catch (e) {
272
+
setState(() {
273
+
_submitting = false;
274
+
_showUploadOverlay = false;
275
+
});
276
+
if (mounted) {
277
+
await showDialog(
278
+
context: context,
279
+
builder: (context) => AlertDialog(
280
+
title: const Text('Upload Failed'),
281
+
content: Text('An error occurred while uploading:\n\n${e.toString()}'),
282
+
actions: [
283
+
TextButton(child: const Text('OK'), onPressed: () => Navigator.of(context).pop()),
284
+
],
165
285
),
166
286
);
167
287
}
168
-
} else if (mounted) {
169
-
FocusScope.of(context).unfocus(); // Force keyboard to close
170
-
Navigator.of(context).pop();
171
288
}
172
289
}
173
290
···
175
292
Widget build(BuildContext context) {
176
293
final theme = Theme.of(context);
177
294
178
-
return CupertinoPageScaffold(
179
-
backgroundColor: theme.colorScheme.surface,
180
-
navigationBar: CupertinoNavigationBar(
181
-
backgroundColor: theme.colorScheme.surface,
182
-
border: Border(bottom: BorderSide(color: theme.dividerColor, width: 1)),
183
-
middle: Text(
184
-
widget.gallery == null ? 'New Gallery' : 'Edit Gallery',
185
-
style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
186
-
),
187
-
leading: CupertinoButton(
188
-
padding: EdgeInsets.zero,
189
-
onPressed: _submitting ? null : () => Navigator.of(context).pop(),
190
-
child: Text(
191
-
'Cancel',
192
-
style: TextStyle(color: theme.colorScheme.primary, fontWeight: FontWeight.w600),
193
-
),
194
-
),
195
-
trailing: CupertinoButton(
196
-
padding: EdgeInsets.zero,
197
-
onPressed: _submitting || _titleController.text.trim().isEmpty ? null : _submit,
198
-
child: Row(
199
-
mainAxisSize: MainAxisSize.min,
200
-
children: [
201
-
Text(
202
-
widget.gallery == null ? 'Create' : 'Save',
203
-
style: TextStyle(
204
-
color: (_submitting || _titleController.text.trim().isEmpty)
205
-
? theme.disabledColor
206
-
: theme.colorScheme.primary,
207
-
fontWeight: FontWeight.w600,
208
-
),
295
+
return Stack(
296
+
children: [
297
+
Positioned.fill(
298
+
child: CupertinoPageScaffold(
299
+
backgroundColor: theme.colorScheme.surface,
300
+
navigationBar: CupertinoNavigationBar(
301
+
backgroundColor: theme.colorScheme.surface,
302
+
border: Border(bottom: BorderSide(color: theme.dividerColor, width: 1)),
303
+
middle: Text(
304
+
widget.gallery == null ? 'New Gallery' : 'Edit Gallery',
305
+
style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
209
306
),
210
-
if (_submitting) ...[
211
-
const SizedBox(width: 8),
212
-
SizedBox(
213
-
width: 16,
214
-
height: 16,
215
-
child: CircularProgressIndicator(
216
-
strokeWidth: 2,
217
-
valueColor: AlwaysStoppedAnimation<Color>(theme.colorScheme.primary),
218
-
semanticsLabel: widget.gallery == null ? 'Creating' : 'Saving',
219
-
),
307
+
leading: CupertinoButton(
308
+
padding: EdgeInsets.zero,
309
+
onPressed: _submitting
310
+
? null
311
+
: () {
312
+
FocusScope.of(context).unfocus(); // Force keyboard to close
313
+
Navigator.of(context).pop();
314
+
},
315
+
child: Text(
316
+
'Cancel',
317
+
style: TextStyle(color: theme.colorScheme.primary, fontWeight: FontWeight.w600),
220
318
),
221
-
],
222
-
],
223
-
),
224
-
),
225
-
),
226
-
child: SafeArea(
227
-
bottom: true,
228
-
child: SingleChildScrollView(
229
-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
230
-
child: Column(
231
-
crossAxisAlignment: CrossAxisAlignment.start,
232
-
mainAxisSize: MainAxisSize.min,
233
-
children: [
234
-
PlainTextField(
235
-
label: 'Title',
236
-
controller: _titleController,
237
-
hintText: 'Enter a title',
238
319
),
239
-
const SizedBox(height: 16),
240
-
PlainTextField(
241
-
label: 'Description',
242
-
controller: _descController,
243
-
maxLines: 6,
244
-
hintText: 'Enter a description',
245
-
),
246
-
const SizedBox(height: 16),
247
-
if (widget.gallery == null)
248
-
Row(
320
+
trailing: CupertinoButton(
321
+
padding: EdgeInsets.zero,
322
+
onPressed: _submitting || _titleController.text.trim().isEmpty ? null : _submit,
323
+
child: Row(
324
+
mainAxisSize: MainAxisSize.min,
249
325
children: [
250
-
Expanded(
251
-
child: Text(
252
-
'Include image metadata (EXIF)',
253
-
style: theme.textTheme.bodyMedium,
326
+
Text(
327
+
widget.gallery == null ? 'Create' : 'Save',
328
+
style: TextStyle(
329
+
color: (_submitting || _titleController.text.trim().isEmpty)
330
+
? theme.disabledColor
331
+
: theme.colorScheme.primary,
332
+
fontWeight: FontWeight.w600,
254
333
),
255
334
),
256
-
Switch(
257
-
value: _includeExif,
258
-
onChanged: (val) {
259
-
setState(() {
260
-
_includeExif = val;
261
-
});
262
-
},
263
-
),
264
-
],
265
-
),
266
-
const SizedBox(height: 16),
267
-
if (widget.gallery == null)
268
-
Row(
269
-
children: [
270
-
Expanded(
271
-
child: AppButton(
272
-
label: 'Upload photos',
273
-
onPressed: _pickImages,
274
-
icon: AppIcons.photoLibrary,
275
-
variant: AppButtonVariant.primary,
276
-
height: 40,
277
-
fontSize: 15,
278
-
borderRadius: 6,
335
+
if (_submitting) ...[
336
+
const SizedBox(width: 8),
337
+
SizedBox(
338
+
width: 16,
339
+
height: 16,
340
+
child: CircularProgressIndicator(
341
+
strokeWidth: 2,
342
+
valueColor: AlwaysStoppedAnimation<Color>(theme.colorScheme.primary),
343
+
semanticsLabel: widget.gallery == null ? 'Creating' : 'Saving',
344
+
),
279
345
),
280
-
),
346
+
],
281
347
],
282
348
),
283
-
if (_images.isNotEmpty) ...[
284
-
const SizedBox(height: 16),
285
-
GridView.builder(
286
-
shrinkWrap: true,
287
-
physics: const NeverScrollableScrollPhysics(),
288
-
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
289
-
crossAxisCount: 3,
290
-
crossAxisSpacing: 8,
291
-
mainAxisSpacing: 8,
292
-
),
293
-
itemCount: _images.length,
294
-
itemBuilder: (context, index) {
295
-
final galleryImage = _images[index];
296
-
return Stack(
297
-
children: [
298
-
Positioned.fill(
299
-
child: Container(
300
-
decoration: BoxDecoration(
301
-
color: theme.colorScheme.surfaceContainerHighest,
302
-
borderRadius: BorderRadius.circular(8),
349
+
),
350
+
),
351
+
child: SafeArea(
352
+
bottom: true,
353
+
child: GestureDetector(
354
+
behavior: HitTestBehavior.translucent,
355
+
onTap: () => FocusScope.of(context).unfocus(),
356
+
child: SingleChildScrollView(
357
+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
358
+
child: Column(
359
+
crossAxisAlignment: CrossAxisAlignment.start,
360
+
mainAxisSize: MainAxisSize.min,
361
+
children: [
362
+
PlainTextField(
363
+
label: 'Title',
364
+
controller: _titleController,
365
+
hintText: 'Enter a title',
366
+
),
367
+
Padding(
368
+
padding: const EdgeInsets.only(top: 4),
369
+
child: Row(
370
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
371
+
children: [
372
+
const SizedBox(),
373
+
Text(
374
+
'${_titleController.text.characters.length}/100',
375
+
style: theme.textTheme.bodySmall?.copyWith(
376
+
color: _titleController.text.characters.length > 100
377
+
? theme.colorScheme.error
378
+
: theme.textTheme.bodySmall?.color,
379
+
),
303
380
),
304
-
child: ClipRRect(
305
-
borderRadius: BorderRadius.circular(8),
306
-
child: Image.file(File(galleryImage.file.path), fit: BoxFit.cover),
381
+
],
382
+
),
383
+
),
384
+
const SizedBox(height: 16),
385
+
FacetedTextField(
386
+
label: 'Description',
387
+
controller: _descController,
388
+
maxLines: 6,
389
+
hintText: 'Enter a description',
390
+
),
391
+
Padding(
392
+
padding: const EdgeInsets.only(top: 4),
393
+
child: Row(
394
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
395
+
children: [
396
+
const SizedBox(),
397
+
Text(
398
+
'${_descController.text.characters.length}/1000',
399
+
style: theme.textTheme.bodySmall?.copyWith(
400
+
color: _descController.text.characters.length > 1000
401
+
? theme.colorScheme.error
402
+
: theme.textTheme.bodySmall?.color,
403
+
),
307
404
),
308
-
),
405
+
],
309
406
),
310
-
if (galleryImage.isExisting)
311
-
Positioned(
312
-
left: 2,
313
-
top: 2,
314
-
child: Container(
315
-
padding: const EdgeInsets.all(2),
316
-
decoration: BoxDecoration(
317
-
color: theme.colorScheme.secondary.withOpacity(0.7),
318
-
borderRadius: BorderRadius.circular(4),
407
+
),
408
+
const SizedBox(height: 16),
409
+
if (widget.gallery == null)
410
+
Row(
411
+
children: [
412
+
Expanded(
413
+
child: Text(
414
+
'Include image metadata (EXIF)',
415
+
style: theme.textTheme.bodyMedium,
319
416
),
320
-
child: Icon(
321
-
AppIcons.checkCircle,
322
-
color: theme.colorScheme.onSecondary,
323
-
size: 16,
324
-
),
417
+
),
418
+
Switch(
419
+
value: _includeExif,
420
+
onChanged: (val) {
421
+
setState(() {
422
+
_includeExif = val;
423
+
});
424
+
},
325
425
),
426
+
],
427
+
),
428
+
const SizedBox(height: 16),
429
+
if (widget.gallery == null) ...[
430
+
Padding(
431
+
padding: const EdgeInsets.only(bottom: 8.0),
432
+
child: Text(
433
+
"You can add up to 10 photos when initially creating a gallery, but you can add more later on. Galleries can capture a moment in time or evolve as an ongoing collection.",
434
+
style: theme.textTheme.bodySmall?.copyWith(color: theme.hintColor),
326
435
),
327
-
Positioned(
328
-
top: 2,
329
-
right: 2,
330
-
child: GestureDetector(
331
-
onTap: () => _removeImage(index),
332
-
child: Container(
333
-
decoration: BoxDecoration(
334
-
color: Colors.grey.withOpacity(0.7),
335
-
shape: BoxShape.circle,
436
+
),
437
+
Row(
438
+
children: [
439
+
Expanded(
440
+
child: AppButton(
441
+
label: _images.length >= 10
442
+
? 'Photos limit reached (10/10)'
443
+
: 'Add photos (${_images.length}/10)',
444
+
onPressed: _images.length >= 10 ? null : _pickImages,
445
+
icon: AppIcons.photoLibrary,
446
+
variant: AppButtonVariant.primary,
447
+
height: 40,
448
+
fontSize: 15,
449
+
borderRadius: 6,
336
450
),
337
-
padding: const EdgeInsets.all(4),
338
-
child: const Icon(AppIcons.close, color: Colors.white, size: 20),
339
451
),
452
+
],
453
+
),
454
+
],
455
+
if (_images.isNotEmpty) ...[
456
+
const SizedBox(height: 16),
457
+
GridView.builder(
458
+
shrinkWrap: true,
459
+
physics: const NeverScrollableScrollPhysics(),
460
+
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
461
+
crossAxisCount: 3,
462
+
crossAxisSpacing: 8,
463
+
mainAxisSpacing: 8,
340
464
),
465
+
itemCount: _images.length,
466
+
itemBuilder: (context, index) {
467
+
final galleryImage = _images[index];
468
+
return Stack(
469
+
children: [
470
+
Positioned.fill(
471
+
child: Container(
472
+
decoration: BoxDecoration(
473
+
color: theme.colorScheme.surfaceContainerHighest,
474
+
borderRadius: BorderRadius.circular(8),
475
+
),
476
+
child: ClipRRect(
477
+
borderRadius: BorderRadius.circular(8),
478
+
child: Image.file(
479
+
File(galleryImage.file.path),
480
+
fit: BoxFit.cover,
481
+
),
482
+
),
483
+
),
484
+
),
485
+
if (galleryImage.isExisting)
486
+
Positioned(
487
+
left: 2,
488
+
top: 2,
489
+
child: Container(
490
+
padding: const EdgeInsets.all(2),
491
+
decoration: BoxDecoration(
492
+
color: theme.colorScheme.secondary.withOpacity(0.7),
493
+
borderRadius: BorderRadius.circular(4),
494
+
),
495
+
child: Icon(
496
+
AppIcons.checkCircle,
497
+
color: theme.colorScheme.onSecondary,
498
+
size: 16,
499
+
),
500
+
),
501
+
),
502
+
Positioned(
503
+
top: 2,
504
+
right: 2,
505
+
child: GestureDetector(
506
+
onTap: () => _removeImage(index),
507
+
child: Container(
508
+
decoration: BoxDecoration(
509
+
color: Colors.grey.withOpacity(0.7),
510
+
shape: BoxShape.circle,
511
+
),
512
+
padding: const EdgeInsets.all(4),
513
+
child: const Icon(
514
+
AppIcons.close,
515
+
color: Colors.white,
516
+
size: 20,
517
+
),
518
+
),
519
+
),
520
+
),
521
+
],
522
+
);
523
+
},
341
524
),
342
525
],
343
-
);
344
-
},
526
+
],
527
+
),
345
528
),
346
-
],
347
-
],
529
+
),
530
+
),
348
531
),
349
532
),
350
-
),
533
+
if (_showUploadOverlay && widget.gallery == null) ...[
534
+
UploadProgressOverlay(
535
+
images: _images.where((img) => !img.isExisting).toList(),
536
+
currentIndex: _currentUploadIndex,
537
+
progress: _currentUploadProgress,
538
+
visible: _showUploadOverlay,
539
+
),
540
+
],
541
+
],
351
542
);
352
543
}
353
544
}
354
545
355
546
Future<String?> showCreateGallerySheet(BuildContext context, {Gallery? gallery}) async {
356
547
final theme = Theme.of(context);
548
+
549
+
FocusScope.of(context).unfocus();
550
+
357
551
final result = await showCupertinoSheet(
358
552
context: context,
359
553
useNestedNavigation: false,
···
362
556
child: CreateGalleryPage(gallery: gallery),
363
557
),
364
558
);
559
+
365
560
// Restore status bar style or any other cleanup
366
561
SystemChrome.setSystemUIOverlayStyle(
367
562
theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
+11
-4
lib/screens/gallery_edit_photos_sheet.dart
+11
-4
lib/screens/gallery_edit_photos_sheet.dart
···
222
222
context,
223
223
actorDid: actorDid,
224
224
galleryUri: widget.galleryUri,
225
-
onSelect: (photos) {
226
-
setState(() {
227
-
_photos.addAll(photos);
228
-
});
225
+
onSelect: (photos) async {
226
+
// Wait for provider to update after adding
227
+
await Future.delayed(const Duration(milliseconds: 100));
228
+
final updatedGallery = ref.read(
229
+
galleryCacheProvider,
230
+
)[widget.galleryUri];
231
+
if (updatedGallery != null && mounted) {
232
+
setState(() {
233
+
_photos = List.from(updatedGallery.items);
234
+
});
235
+
}
229
236
},
230
237
);
231
238
},
+8
-10
lib/screens/gallery_page.dart
+8
-10
lib/screens/gallery_page.dart
···
273
273
);
274
274
}
275
275
: null,
276
-
child: Row(
277
-
crossAxisAlignment: CrossAxisAlignment.center,
276
+
child: Column(
277
+
crossAxisAlignment: CrossAxisAlignment.start,
278
278
children: [
279
279
Text(
280
280
gallery.creator?.displayName ?? '',
···
282
282
fontWeight: FontWeight.w600,
283
283
),
284
284
),
285
-
if ((gallery.creator?.displayName ?? '').isNotEmpty &&
286
-
(gallery.creator?.handle ?? '').isNotEmpty)
287
-
const SizedBox(width: 8),
288
-
Text(
289
-
'@${gallery.creator?.handle ?? ''}',
290
-
style: theme.textTheme.bodyMedium?.copyWith(
291
-
color: theme.hintColor,
285
+
if ((gallery.creator?.handle ?? '').isNotEmpty)
286
+
Text(
287
+
'@${gallery.creator?.handle ?? ''}',
288
+
style: theme.textTheme.bodyMedium?.copyWith(
289
+
color: theme.hintColor,
290
+
),
292
291
),
293
-
),
294
292
],
295
293
),
296
294
),
+6
-1
lib/screens/library_photos_select_sheet.dart
+6
-1
lib/screens/library_photos_select_sheet.dart
···
40
40
Future<void> _fetchPhotos() async {
41
41
setState(() => _loading = true);
42
42
final photos = await apiService.fetchActorPhotos(did: widget.actorDid);
43
+
// Get gallery items from provider
44
+
final galleryItems = ref.read(galleryCacheProvider)[widget.galleryUri]?.items ?? [];
45
+
final galleryUris = galleryItems.map((item) => item.uri).toSet();
46
+
// Filter out photos already in gallery
47
+
final filteredPhotos = photos.where((photo) => !galleryUris.contains(photo.uri)).toList();
43
48
if (mounted) {
44
49
setState(() {
45
-
_photos = photos;
50
+
_photos = filteredPhotos;
46
51
_loading = false;
47
52
});
48
53
}
+601
lib/screens/photo_library_page.dart
+601
lib/screens/photo_library_page.dart
···
1
+
import 'package:flutter/material.dart';
2
+
import 'package:grain/api.dart';
3
+
import 'package:grain/app_icons.dart';
4
+
import 'package:grain/models/gallery_photo.dart';
5
+
import 'package:grain/widgets/app_image.dart';
6
+
import 'package:grain/widgets/gallery_photo_view.dart';
7
+
8
+
class PhotoGroup {
9
+
final String title;
10
+
final List<GalleryPhoto> photos;
11
+
final DateTime? sortDate;
12
+
13
+
PhotoGroup({required this.title, required this.photos, this.sortDate});
14
+
}
15
+
16
+
class PhotoLibraryPage extends StatefulWidget {
17
+
const PhotoLibraryPage({super.key});
18
+
19
+
@override
20
+
State<PhotoLibraryPage> createState() => _PhotoLibraryPageState();
21
+
}
22
+
23
+
class _PhotoLibraryPageState extends State<PhotoLibraryPage> {
24
+
List<GalleryPhoto> _photos = [];
25
+
List<PhotoGroup> _photoGroups = [];
26
+
bool _isLoading = true;
27
+
String? _error;
28
+
final ScrollController _scrollController = ScrollController();
29
+
double _scrollPosition = 0.0;
30
+
31
+
@override
32
+
void initState() {
33
+
super.initState();
34
+
_loadPhotos();
35
+
_scrollController.addListener(_onScroll);
36
+
}
37
+
38
+
@override
39
+
void dispose() {
40
+
_scrollController.removeListener(_onScroll);
41
+
_scrollController.dispose();
42
+
super.dispose();
43
+
}
44
+
45
+
void _onScroll() {
46
+
if (_scrollController.hasClients) {
47
+
setState(() {
48
+
_scrollPosition = _scrollController.offset;
49
+
});
50
+
}
51
+
}
52
+
53
+
// Calculate which group is currently in view based on scroll position
54
+
int _getCurrentGroupIndex() {
55
+
if (!_scrollController.hasClients || _photoGroups.isEmpty) return 0;
56
+
57
+
final scrollOffset = _scrollController.offset;
58
+
final padding = 16.0; // ListView padding
59
+
double currentOffset = padding;
60
+
61
+
for (int i = 0; i < _photoGroups.length; i++) {
62
+
final group = _photoGroups[i];
63
+
64
+
// Add space for group title
65
+
final titleHeight = 24.0 + 12.0 + (i == 0 ? 0 : 24.0); // title + padding + top margin
66
+
currentOffset += titleHeight;
67
+
68
+
// Calculate grid height for this group
69
+
final photos = group.photos;
70
+
final crossAxisCount = photos.length == 1 ? 1 : (photos.length == 2 ? 2 : 3);
71
+
final aspectRatio = photos.length <= 2 ? 1.5 : 1.0;
72
+
final rows = (photos.length / crossAxisCount).ceil();
73
+
74
+
// Estimate grid item size based on screen width
75
+
final screenWidth = MediaQuery.of(context).size.width;
76
+
final gridPadding = 30.0 + 32.0; // right padding + left/right margins
77
+
final availableWidth = screenWidth - gridPadding;
78
+
final itemWidth = (availableWidth - (crossAxisCount - 1) * 4) / crossAxisCount;
79
+
final itemHeight = itemWidth / aspectRatio;
80
+
final gridHeight = rows * itemHeight + (rows - 1) * 4; // include spacing
81
+
82
+
currentOffset += gridHeight;
83
+
84
+
// Check if we're currently viewing this group
85
+
if (scrollOffset < currentOffset) {
86
+
return i;
87
+
}
88
+
}
89
+
90
+
return _photoGroups.length - 1; // Return last group if we're at the bottom
91
+
}
92
+
93
+
Future<void> _loadPhotos() async {
94
+
setState(() {
95
+
_isLoading = true;
96
+
_error = null;
97
+
});
98
+
99
+
try {
100
+
final currentUser = apiService.currentUser;
101
+
if (currentUser == null || currentUser.did.isEmpty) {
102
+
setState(() {
103
+
_error = 'No current user found';
104
+
_isLoading = false;
105
+
});
106
+
return;
107
+
}
108
+
109
+
final photos = await apiService.fetchActorPhotos(did: currentUser.did);
110
+
111
+
if (mounted) {
112
+
setState(() {
113
+
_photos = photos;
114
+
_photoGroups = _groupPhotosByDate(photos);
115
+
_isLoading = false;
116
+
});
117
+
118
+
// Force update scroll indicator after layout is complete
119
+
WidgetsBinding.instance.addPostFrameCallback((_) {
120
+
if (_scrollController.hasClients && mounted) {
121
+
setState(() {
122
+
_scrollPosition = _scrollController.offset;
123
+
});
124
+
}
125
+
});
126
+
}
127
+
} catch (e) {
128
+
if (mounted) {
129
+
setState(() {
130
+
_error = 'Failed to load photos: $e';
131
+
_isLoading = false;
132
+
});
133
+
}
134
+
}
135
+
}
136
+
137
+
List<PhotoGroup> _groupPhotosByDate(List<GalleryPhoto> photos) {
138
+
final now = DateTime.now();
139
+
final today = DateTime(now.year, now.month, now.day);
140
+
final yesterday = today.subtract(const Duration(days: 1));
141
+
142
+
final Map<String, List<GalleryPhoto>> groupedPhotos = {};
143
+
final List<GalleryPhoto> noExifPhotos = [];
144
+
145
+
for (final photo in photos) {
146
+
DateTime? photoDate;
147
+
// Try to parse the dateTimeOriginal from EXIF record data
148
+
if (photo.exif?.record?['dateTimeOriginal'] != null) {
149
+
try {
150
+
final dateTimeOriginal = photo.exif!.record!['dateTimeOriginal'] as String;
151
+
photoDate = DateTime.parse(dateTimeOriginal);
152
+
} catch (e) {
153
+
// If parsing fails, add to no EXIF group
154
+
noExifPhotos.add(photo);
155
+
continue;
156
+
}
157
+
} else {
158
+
noExifPhotos.add(photo);
159
+
continue;
160
+
}
161
+
162
+
final photoDay = DateTime(photoDate.year, photoDate.month, photoDate.day);
163
+
String groupKey;
164
+
165
+
if (photoDay.isAtSameMomentAs(today)) {
166
+
groupKey = 'Today';
167
+
} else if (photoDay.isAtSameMomentAs(yesterday)) {
168
+
groupKey = 'Yesterday';
169
+
} else {
170
+
final daysDifference = today.difference(photoDay).inDays;
171
+
172
+
if (daysDifference <= 30) {
173
+
// Group by week for last 30 days
174
+
final weekStart = photoDay.subtract(Duration(days: photoDay.weekday - 1));
175
+
groupKey = 'Week of ${_formatDate(weekStart)}';
176
+
} else {
177
+
// Group by month for older photos
178
+
groupKey = '${_getMonthName(photoDate.month)} ${photoDate.year}';
179
+
}
180
+
}
181
+
182
+
groupedPhotos.putIfAbsent(groupKey, () => []).add(photo);
183
+
}
184
+
185
+
final List<PhotoGroup> groups = [];
186
+
187
+
// Sort and create PhotoGroup objects
188
+
final sortedEntries = groupedPhotos.entries.toList()
189
+
..sort((a, b) {
190
+
final aDate = _getGroupSortDate(a.key, a.value);
191
+
final bDate = _getGroupSortDate(b.key, b.value);
192
+
return bDate.compareTo(aDate); // Most recent first
193
+
});
194
+
195
+
for (final entry in sortedEntries) {
196
+
final sortedPhotos = entry.value
197
+
..sort((a, b) {
198
+
final aDate = _getPhotoDate(a);
199
+
final bDate = _getPhotoDate(b);
200
+
return bDate.compareTo(aDate); // Most recent first within group
201
+
});
202
+
203
+
groups.add(
204
+
PhotoGroup(
205
+
title: entry.key,
206
+
photos: sortedPhotos,
207
+
sortDate: _getGroupSortDate(entry.key, entry.value),
208
+
),
209
+
);
210
+
}
211
+
212
+
// Add photos without EXIF data at the end
213
+
if (noExifPhotos.isNotEmpty) {
214
+
groups.add(
215
+
PhotoGroup(
216
+
title: 'Photos without date info',
217
+
photos: noExifPhotos,
218
+
sortDate: DateTime(1970), // Very old date to sort at bottom
219
+
),
220
+
);
221
+
}
222
+
223
+
return groups;
224
+
}
225
+
226
+
DateTime _getGroupSortDate(String groupKey, List<GalleryPhoto> photos) {
227
+
if (groupKey == 'Today') return DateTime.now();
228
+
if (groupKey == 'Yesterday') return DateTime.now().subtract(const Duration(days: 1));
229
+
230
+
// For other groups, use the most recent photo date in the group
231
+
DateTime? latestDate;
232
+
for (final photo in photos) {
233
+
final photoDate = _getPhotoDate(photo);
234
+
if (latestDate == null || photoDate.isAfter(latestDate)) {
235
+
latestDate = photoDate;
236
+
}
237
+
}
238
+
return latestDate ?? DateTime(1970);
239
+
}
240
+
241
+
DateTime _getPhotoDate(GalleryPhoto photo) {
242
+
if (photo.exif?.record?['dateTimeOriginal'] != null) {
243
+
try {
244
+
final dateTimeOriginal = photo.exif!.record!['dateTimeOriginal'] as String;
245
+
return DateTime.parse(dateTimeOriginal);
246
+
} catch (e) {
247
+
// Fall back to a very old date if parsing fails
248
+
return DateTime(1970);
249
+
}
250
+
}
251
+
return DateTime(1970);
252
+
}
253
+
254
+
String _formatDate(DateTime date) {
255
+
const months = [
256
+
'Jan',
257
+
'Feb',
258
+
'Mar',
259
+
'Apr',
260
+
'May',
261
+
'Jun',
262
+
'Jul',
263
+
'Aug',
264
+
'Sep',
265
+
'Oct',
266
+
'Nov',
267
+
'Dec',
268
+
];
269
+
return '${months[date.month - 1]} ${date.day}';
270
+
}
271
+
272
+
String _getMonthName(int month) {
273
+
const months = [
274
+
'January',
275
+
'February',
276
+
'March',
277
+
'April',
278
+
'May',
279
+
'June',
280
+
'July',
281
+
'August',
282
+
'September',
283
+
'October',
284
+
'November',
285
+
'December',
286
+
];
287
+
return months[month - 1];
288
+
}
289
+
290
+
Future<void> _onRefresh() async {
291
+
await _loadPhotos();
292
+
}
293
+
294
+
void _showPhotoDetail(GalleryPhoto photo) {
295
+
// Create a flattened list of photos in the same order they appear on the page
296
+
final List<GalleryPhoto> orderedPhotos = [];
297
+
for (final group in _photoGroups) {
298
+
orderedPhotos.addAll(group.photos);
299
+
}
300
+
301
+
// Find the index of the photo in the ordered list
302
+
final photoIndex = orderedPhotos.indexOf(photo);
303
+
if (photoIndex == -1) return; // Photo not found, shouldn't happen
304
+
305
+
Navigator.of(context).push(
306
+
PageRouteBuilder(
307
+
pageBuilder: (context, animation, secondaryAnimation) => GalleryPhotoView(
308
+
photos: orderedPhotos,
309
+
initialIndex: photoIndex,
310
+
showAddCommentButton: false,
311
+
onClose: () => Navigator.of(context).pop(),
312
+
),
313
+
transitionDuration: const Duration(milliseconds: 200),
314
+
reverseTransitionDuration: const Duration(milliseconds: 200),
315
+
transitionsBuilder: (context, animation, secondaryAnimation, child) {
316
+
return FadeTransition(opacity: animation, child: child);
317
+
},
318
+
),
319
+
);
320
+
}
321
+
322
+
@override
323
+
Widget build(BuildContext context) {
324
+
final theme = Theme.of(context);
325
+
326
+
return Scaffold(
327
+
backgroundColor: theme.scaffoldBackgroundColor,
328
+
appBar: AppBar(
329
+
title: const Text('Photo Library'),
330
+
backgroundColor: theme.appBarTheme.backgroundColor,
331
+
surfaceTintColor: theme.appBarTheme.backgroundColor,
332
+
elevation: 0,
333
+
),
334
+
body: RefreshIndicator(onRefresh: _onRefresh, child: _buildBodyWithScrollbar(theme)),
335
+
);
336
+
}
337
+
338
+
Widget _buildBodyWithScrollbar(ThemeData theme) {
339
+
return Stack(
340
+
children: [
341
+
Padding(
342
+
padding: const EdgeInsets.only(right: 30), // Make room for scroll indicator
343
+
child: _buildBody(theme),
344
+
),
345
+
if (!_isLoading && _error == null && _photos.isNotEmpty) _buildScrollIndicator(theme),
346
+
],
347
+
);
348
+
}
349
+
350
+
Widget _buildScrollIndicator(ThemeData theme) {
351
+
return Positioned(
352
+
right: 4,
353
+
top: 0,
354
+
bottom: 0,
355
+
child: GestureDetector(
356
+
onPanUpdate: (details) {
357
+
if (_scrollController.hasClients) {
358
+
final RenderBox renderBox = context.findRenderObject() as RenderBox;
359
+
final localPosition = renderBox.globalToLocal(details.globalPosition);
360
+
final screenHeight = renderBox.size.height;
361
+
final maxScrollExtent = _scrollController.position.maxScrollExtent;
362
+
final relativePosition = (localPosition.dy / screenHeight).clamp(0.0, 1.0);
363
+
final newPosition = relativePosition * maxScrollExtent;
364
+
_scrollController.jumpTo(newPosition.clamp(0.0, maxScrollExtent));
365
+
}
366
+
},
367
+
onTapDown: (details) {
368
+
if (_scrollController.hasClients) {
369
+
final RenderBox renderBox = context.findRenderObject() as RenderBox;
370
+
final localPosition = renderBox.globalToLocal(details.globalPosition);
371
+
final screenHeight = renderBox.size.height;
372
+
final maxScrollExtent = _scrollController.position.maxScrollExtent;
373
+
final relativePosition = (localPosition.dy / screenHeight).clamp(0.0, 1.0);
374
+
final newPosition = relativePosition * maxScrollExtent;
375
+
_scrollController.animateTo(
376
+
newPosition.clamp(0.0, maxScrollExtent),
377
+
duration: const Duration(milliseconds: 200),
378
+
curve: Curves.easeInOut,
379
+
);
380
+
}
381
+
},
382
+
child: Container(
383
+
width: 24,
384
+
decoration: BoxDecoration(
385
+
color: theme.scaffoldBackgroundColor.withValues(alpha: 0.8),
386
+
borderRadius: BorderRadius.circular(12),
387
+
),
388
+
child: CustomPaint(
389
+
painter: ScrollIndicatorPainter(
390
+
scrollPosition: _scrollPosition,
391
+
maxScrollExtent: _scrollController.hasClients
392
+
? _scrollController.position.maxScrollExtent
393
+
: 0,
394
+
viewportHeight: _scrollController.hasClients
395
+
? _scrollController.position.viewportDimension
396
+
: 0,
397
+
color: theme.colorScheme.onSurface.withValues(alpha: 0.4),
398
+
activeColor: theme.colorScheme.primary,
399
+
currentGroupIndex: _getCurrentGroupIndex(),
400
+
totalGroups: _photoGroups.length,
401
+
),
402
+
),
403
+
),
404
+
),
405
+
);
406
+
}
407
+
408
+
Widget _buildBody(ThemeData theme) {
409
+
if (_isLoading) {
410
+
return const Center(child: CircularProgressIndicator());
411
+
}
412
+
413
+
if (_error != null) {
414
+
return Center(
415
+
child: Column(
416
+
mainAxisAlignment: MainAxisAlignment.center,
417
+
children: [
418
+
Icon(AppIcons.brokenImage, size: 64, color: theme.hintColor),
419
+
const SizedBox(height: 16),
420
+
Text(
421
+
_error!,
422
+
style: theme.textTheme.bodyLarge?.copyWith(color: theme.hintColor),
423
+
textAlign: TextAlign.center,
424
+
),
425
+
const SizedBox(height: 16),
426
+
ElevatedButton(onPressed: _loadPhotos, child: const Text('Retry')),
427
+
],
428
+
),
429
+
);
430
+
}
431
+
432
+
if (_photos.isEmpty) {
433
+
return Center(
434
+
child: Column(
435
+
mainAxisAlignment: MainAxisAlignment.center,
436
+
children: [
437
+
Icon(AppIcons.photoLibrary, size: 64, color: theme.hintColor),
438
+
const SizedBox(height: 16),
439
+
Text(
440
+
'No photos yet',
441
+
style: theme.textTheme.headlineSmall?.copyWith(color: theme.hintColor),
442
+
),
443
+
const SizedBox(height: 8),
444
+
Text(
445
+
'Upload some photos to see them here',
446
+
style: theme.textTheme.bodyLarge?.copyWith(color: theme.hintColor),
447
+
textAlign: TextAlign.center,
448
+
),
449
+
],
450
+
),
451
+
);
452
+
}
453
+
454
+
return ListView.builder(
455
+
controller: _scrollController,
456
+
padding: const EdgeInsets.all(16),
457
+
itemCount: _photoGroups.length,
458
+
itemBuilder: (context, index) {
459
+
final group = _photoGroups[index];
460
+
return _buildPhotoGroup(group, theme, index);
461
+
},
462
+
);
463
+
}
464
+
465
+
Widget _buildPhotoGroup(PhotoGroup group, ThemeData theme, int index) {
466
+
return Column(
467
+
crossAxisAlignment: CrossAxisAlignment.start,
468
+
children: [
469
+
Padding(
470
+
padding: EdgeInsets.only(bottom: 12, top: index == 0 ? 0 : 24),
471
+
child: Text(
472
+
group.title,
473
+
style: theme.textTheme.headlineSmall?.copyWith(
474
+
fontWeight: FontWeight.bold,
475
+
color: theme.colorScheme.onSurface,
476
+
),
477
+
),
478
+
),
479
+
_buildPhotoGrid(group.photos, theme),
480
+
],
481
+
);
482
+
}
483
+
484
+
Widget _buildPhotoGrid(List<GalleryPhoto> photos, ThemeData theme) {
485
+
final crossAxisCount = photos.length == 1 ? 1 : (photos.length == 2 ? 2 : 3);
486
+
final aspectRatio = photos.length <= 2 ? 1.5 : 1.0;
487
+
488
+
return GridView.builder(
489
+
shrinkWrap: true,
490
+
physics: const NeverScrollableScrollPhysics(),
491
+
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
492
+
crossAxisCount: crossAxisCount,
493
+
crossAxisSpacing: 4,
494
+
mainAxisSpacing: 4,
495
+
childAspectRatio: aspectRatio,
496
+
),
497
+
itemCount: photos.length,
498
+
itemBuilder: (context, index) {
499
+
final photo = photos[index];
500
+
return _buildPhotoTile(photo, theme);
501
+
},
502
+
);
503
+
}
504
+
505
+
Widget _buildPhotoTile(GalleryPhoto photo, ThemeData theme) {
506
+
return GestureDetector(
507
+
onTap: () => _showPhotoDetail(photo),
508
+
child: Hero(
509
+
tag: 'photo-${photo.uri}',
510
+
child: Container(
511
+
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8), color: theme.cardColor),
512
+
clipBehavior: Clip.antiAlias,
513
+
child: AppImage(
514
+
url: photo.thumb ?? photo.fullsize,
515
+
fit: BoxFit.cover,
516
+
width: double.infinity,
517
+
height: double.infinity,
518
+
placeholder: Container(
519
+
color: theme.hintColor.withValues(alpha: 0.1),
520
+
child: Icon(AppIcons.photo, color: theme.hintColor, size: 32),
521
+
),
522
+
errorWidget: Container(
523
+
color: theme.hintColor.withValues(alpha: 0.1),
524
+
child: Icon(AppIcons.brokenImage, color: theme.hintColor, size: 32),
525
+
),
526
+
),
527
+
),
528
+
),
529
+
);
530
+
}
531
+
}
532
+
533
+
class ScrollIndicatorPainter extends CustomPainter {
534
+
final double scrollPosition;
535
+
final double maxScrollExtent;
536
+
final double viewportHeight;
537
+
final Color color;
538
+
final Color activeColor;
539
+
final int currentGroupIndex;
540
+
final int totalGroups;
541
+
542
+
ScrollIndicatorPainter({
543
+
required this.scrollPosition,
544
+
required this.maxScrollExtent,
545
+
required this.viewportHeight,
546
+
required this.color,
547
+
required this.activeColor,
548
+
required this.currentGroupIndex,
549
+
required this.totalGroups,
550
+
});
551
+
552
+
@override
553
+
void paint(Canvas canvas, Size size) {
554
+
const dashCount = 60; // Number of dashes to show (doubled from 30)
555
+
const dashHeight = 2.0; // Height when vertical (now width)
556
+
const dashWidth = 12.0; // Width when vertical (now height)
557
+
558
+
// Calculate spacing to fill the full height
559
+
final availableHeight = size.height;
560
+
final totalDashHeight = dashCount * dashHeight;
561
+
final totalSpacing = availableHeight - totalDashHeight;
562
+
final dashSpacing = totalSpacing / (dashCount - 1);
563
+
564
+
// Calculate which dash should be active based on current group and total groups
565
+
int activeDashIndex;
566
+
if (totalGroups > 0) {
567
+
// Map current group to dash index (more accurate than scroll position)
568
+
final groupProgress = currentGroupIndex / (totalGroups - 1).clamp(1, totalGroups);
569
+
activeDashIndex = (groupProgress * (dashCount - 1)).round().clamp(0, dashCount - 1);
570
+
} else {
571
+
// Fallback to scroll position if no groups
572
+
final scrollProgress = maxScrollExtent > 0
573
+
? (scrollPosition / maxScrollExtent).clamp(0.0, 1.0)
574
+
: 0.0;
575
+
activeDashIndex = (scrollProgress * (dashCount - 1)).round();
576
+
}
577
+
578
+
for (int i = 0; i < dashCount; i++) {
579
+
final y = i * (dashHeight + dashSpacing);
580
+
final isActive = i == activeDashIndex;
581
+
582
+
final paint = Paint()
583
+
..color = isActive ? activeColor : color
584
+
..style = PaintingStyle.fill;
585
+
586
+
// Create vertical dashes (rotated 90 degrees)
587
+
final rect = Rect.fromLTWH((size.width - dashWidth) / 2, y, dashWidth, dashHeight);
588
+
589
+
canvas.drawRRect(RRect.fromRectAndRadius(rect, const Radius.circular(1)), paint);
590
+
}
591
+
}
592
+
593
+
@override
594
+
bool shouldRepaint(ScrollIndicatorPainter oldDelegate) {
595
+
return scrollPosition != oldDelegate.scrollPosition ||
596
+
maxScrollExtent != oldDelegate.maxScrollExtent ||
597
+
viewportHeight != oldDelegate.viewportHeight ||
598
+
currentGroupIndex != oldDelegate.currentGroupIndex ||
599
+
totalGroups != oldDelegate.totalGroups;
600
+
}
601
+
}
+4
-2
lib/screens/profile_page.dart
+4
-2
lib/screens/profile_page.dart
···
47
47
if (!mounted) return;
48
48
if (success) {
49
49
Navigator.of(context).pop();
50
-
if (mounted) setState(() {}); // Force widget rebuild after modal closes
50
+
if (mounted) {
51
+
setState(() {}); // Force widget rebuild after modal closes
52
+
}
51
53
} else {
52
54
if (!mounted) return;
53
55
ScaffoldMessenger.of(
···
194
196
onPressed: () async {
195
197
await ref
196
198
.read(profileNotifierProvider(profile.did).notifier)
197
-
.toggleFollow(apiService.currentUser?.did);
199
+
.toggleFollow(profile.did);
198
200
},
199
201
label: (profile.viewer?.following?.isNotEmpty == true)
200
202
? 'Following'
+310
lib/utils/facet_utils.dart
+310
lib/utils/facet_utils.dart
···
1
+
import 'package:flutter/gestures.dart';
2
+
import 'package:flutter/material.dart';
3
+
4
+
class FacetRange {
5
+
final int start;
6
+
final int end;
7
+
final String? type;
8
+
final Map<String, dynamic> data;
9
+
10
+
FacetRange({required this.start, required this.end, required this.type, required this.data});
11
+
}
12
+
13
+
class ProcessedSpan {
14
+
final int start;
15
+
final int end;
16
+
final TextSpan span;
17
+
18
+
ProcessedSpan({required this.start, required this.end, required this.span});
19
+
}
20
+
21
+
class FacetUtils {
22
+
/// Processes facets and returns a list of TextSpans with proper highlighting
23
+
static List<TextSpan> processFacets({
24
+
required String text,
25
+
required List<Map<String, dynamic>>? facets,
26
+
required TextStyle? defaultStyle,
27
+
required TextStyle? linkStyle,
28
+
void Function(String did)? onMentionTap,
29
+
void Function(String url)? onLinkTap,
30
+
void Function(String tag)? onTagTap,
31
+
}) {
32
+
if (facets == null || facets.isEmpty) {
33
+
return [TextSpan(text: text, style: defaultStyle)];
34
+
}
35
+
36
+
// Build a list of all ranges (start, end, type, data)
37
+
final List<FacetRange> ranges = facets.map((facet) {
38
+
final feature = facet['features']?[0] ?? {};
39
+
final type = feature['\$type'] ?? feature['type'];
40
+
return FacetRange(
41
+
start: facet['index']?['byteStart'] ?? facet['byteStart'] ?? 0,
42
+
end: facet['index']?['byteEnd'] ?? facet['byteEnd'] ?? 0,
43
+
type: type,
44
+
data: feature,
45
+
);
46
+
}).toList();
47
+
48
+
// Sort ranges by the length of their display text (longest first) to avoid overlap issues
49
+
ranges.sort((a, b) {
50
+
int aLength = a.end - a.start;
51
+
int bLength = b.end - b.start;
52
+
53
+
// For links, use the length of the text that will actually be found
54
+
if (a.type?.contains('link') == true && a.data['uri'] != null) {
55
+
final uri = a.data['uri'] as String;
56
+
final possibleTexts = [_extractDisplayTextFromUri(uri), _extractDomainOnly(uri), uri];
57
+
// Use the longest text that exists in the original text
58
+
for (final testText in possibleTexts) {
59
+
if (text.contains(testText)) {
60
+
aLength = testText.length;
61
+
break;
62
+
}
63
+
}
64
+
}
65
+
66
+
if (b.type?.contains('link') == true && b.data['uri'] != null) {
67
+
final uri = b.data['uri'] as String;
68
+
final possibleTexts = [_extractDisplayTextFromUri(uri), _extractDomainOnly(uri), uri];
69
+
// Use the longest text that exists in the original text
70
+
for (final testText in possibleTexts) {
71
+
if (text.contains(testText)) {
72
+
bLength = testText.length;
73
+
break;
74
+
}
75
+
}
76
+
}
77
+
78
+
// Sort by length descending, then by start position ascending
79
+
final lengthComparison = bLength.compareTo(aLength);
80
+
return lengthComparison != 0 ? lengthComparison : a.start.compareTo(b.start);
81
+
});
82
+
83
+
final List<ProcessedSpan> processedSpans = <ProcessedSpan>[];
84
+
final Set<int> usedPositions = <int>{}; // Track which character positions are already used
85
+
86
+
for (final range in ranges) {
87
+
// For links, we need to find the actual text in the original text
88
+
// since the facet positions might be based on the full URL with protocol
89
+
String? actualContent;
90
+
int actualStart = range.start;
91
+
int actualEnd = range.end;
92
+
93
+
if (range.type?.contains('link') == true && range.data['uri'] != null) {
94
+
final uri = range.data['uri'] as String;
95
+
96
+
// First, try to use the exact facet positions if they seem valid
97
+
if (range.start >= 0 && range.end <= text.length && range.start < range.end) {
98
+
final facetText = text.substring(range.start, range.end);
99
+
100
+
// Check if the facet text matches any of our expected URL formats
101
+
final possibleTexts = [
102
+
_extractDisplayTextFromUri(uri), // Full URL with protocol
103
+
_extractDomainOnly(uri), // Just the domain
104
+
uri, // Original URI as-is
105
+
];
106
+
107
+
bool facetTextMatches = possibleTexts.any(
108
+
(possible) =>
109
+
facetText == possible ||
110
+
facetText.contains(possible) ||
111
+
possible.contains(facetText),
112
+
);
113
+
114
+
if (facetTextMatches) {
115
+
// Check if this range overlaps with used positions
116
+
bool overlaps = false;
117
+
for (int i = range.start; i < range.end; i++) {
118
+
if (usedPositions.contains(i)) {
119
+
overlaps = true;
120
+
break;
121
+
}
122
+
}
123
+
124
+
if (!overlaps) {
125
+
actualStart = range.start;
126
+
actualEnd = range.end;
127
+
actualContent =
128
+
facetText; // Use exactly what's in the original text at facet position
129
+
130
+
// Mark these positions as used
131
+
for (int i = actualStart; i < actualEnd; i++) {
132
+
usedPositions.add(i);
133
+
}
134
+
}
135
+
}
136
+
}
137
+
138
+
// If facet positions didn't work, fall back to searching
139
+
if (actualContent == null) {
140
+
final possibleTexts = [
141
+
_extractDisplayTextFromUri(uri), // Full URL with protocol
142
+
_extractDomainOnly(uri), // Just the domain
143
+
uri, // Original URI as-is
144
+
];
145
+
146
+
int searchIndex = 0;
147
+
bool foundValidMatch = false;
148
+
149
+
// Try each possible text representation
150
+
for (final searchText in possibleTexts) {
151
+
searchIndex = 0;
152
+
while (!foundValidMatch) {
153
+
final globalIndex = text.indexOf(searchText, searchIndex);
154
+
if (globalIndex == -1) break;
155
+
156
+
// Check if this range overlaps with any used positions
157
+
bool overlaps = false;
158
+
for (int i = globalIndex; i < globalIndex + searchText.length; i++) {
159
+
if (usedPositions.contains(i)) {
160
+
overlaps = true;
161
+
break;
162
+
}
163
+
}
164
+
165
+
if (!overlaps) {
166
+
actualStart = globalIndex;
167
+
actualEnd = globalIndex + searchText.length;
168
+
actualContent = searchText; // Use exactly what we found in the text
169
+
foundValidMatch = true;
170
+
171
+
// Mark these positions as used
172
+
for (int i = actualStart; i < actualEnd; i++) {
173
+
usedPositions.add(i);
174
+
}
175
+
break;
176
+
} else {
177
+
searchIndex = globalIndex + 1;
178
+
}
179
+
}
180
+
if (foundValidMatch) break;
181
+
}
182
+
}
183
+
}
184
+
185
+
// Handle other facet types that might have similar issues
186
+
if (actualContent == null) {
187
+
// Verify the range is within bounds
188
+
if (range.start >= 0 && range.end <= text.length && range.start < range.end) {
189
+
actualContent = text.substring(range.start, range.end);
190
+
actualStart = range.start;
191
+
actualEnd = range.end;
192
+
193
+
// Check if this overlaps with used positions
194
+
bool overlaps = false;
195
+
for (int i = actualStart; i < actualEnd; i++) {
196
+
if (usedPositions.contains(i)) {
197
+
overlaps = true;
198
+
break;
199
+
}
200
+
}
201
+
202
+
if (!overlaps) {
203
+
// Mark these positions as used
204
+
for (int i = actualStart; i < actualEnd; i++) {
205
+
usedPositions.add(i);
206
+
}
207
+
} else {
208
+
// Skip overlapping ranges
209
+
actualContent = null;
210
+
}
211
+
} else {
212
+
// Skip invalid ranges
213
+
continue;
214
+
}
215
+
}
216
+
217
+
if (actualContent != null) {
218
+
TextSpan span;
219
+
if (range.type?.contains('mention') == true && range.data['did'] != null) {
220
+
span = TextSpan(
221
+
text: actualContent,
222
+
style: linkStyle,
223
+
recognizer: TapGestureRecognizer()
224
+
..onTap = onMentionTap != null ? () => onMentionTap(range.data['did']) : null,
225
+
);
226
+
} else if (range.type?.contains('link') == true && range.data['uri'] != null) {
227
+
span = TextSpan(
228
+
text: actualContent,
229
+
style: linkStyle,
230
+
recognizer: TapGestureRecognizer()
231
+
..onTap = onLinkTap != null ? () => onLinkTap(range.data['uri']) : null,
232
+
);
233
+
} else if (range.type?.contains('tag') == true && range.data['tag'] != null) {
234
+
span = TextSpan(
235
+
text: '#${range.data['tag']}',
236
+
style: linkStyle,
237
+
recognizer: TapGestureRecognizer()
238
+
..onTap = onTagTap != null ? () => onTagTap(range.data['tag']) : null,
239
+
);
240
+
} else {
241
+
span = TextSpan(text: actualContent, style: defaultStyle);
242
+
}
243
+
244
+
processedSpans.add(ProcessedSpan(start: actualStart, end: actualEnd, span: span));
245
+
}
246
+
}
247
+
248
+
// Sort processed spans by position and build final spans list
249
+
processedSpans.sort((a, b) => a.start.compareTo(b.start));
250
+
int pos = 0;
251
+
final spans = <TextSpan>[];
252
+
253
+
for (final processedSpan in processedSpans) {
254
+
if (processedSpan.start > pos) {
255
+
spans.add(TextSpan(text: text.substring(pos, processedSpan.start), style: defaultStyle));
256
+
}
257
+
spans.add(processedSpan.span);
258
+
pos = processedSpan.end;
259
+
}
260
+
261
+
if (pos < text.length) {
262
+
spans.add(TextSpan(text: text.substring(pos), style: defaultStyle));
263
+
}
264
+
265
+
return spans;
266
+
}
267
+
268
+
/// Extracts the display text from a URI (keeps protocol and domain, removes path)
269
+
static String _extractDisplayTextFromUri(String uri) {
270
+
// Find the first slash after the protocol to remove the path
271
+
String protocolAndDomain = uri;
272
+
if (uri.startsWith('https://')) {
273
+
final pathIndex = uri.indexOf('/', 8); // Start search after "https://"
274
+
if (pathIndex != -1) {
275
+
protocolAndDomain = uri.substring(0, pathIndex);
276
+
}
277
+
} else if (uri.startsWith('http://')) {
278
+
final pathIndex = uri.indexOf('/', 7); // Start search after "http://"
279
+
if (pathIndex != -1) {
280
+
protocolAndDomain = uri.substring(0, pathIndex);
281
+
}
282
+
} else {
283
+
// For URIs without protocol, just remove the path
284
+
final slashIndex = uri.indexOf('/');
285
+
if (slashIndex != -1) {
286
+
protocolAndDomain = uri.substring(0, slashIndex);
287
+
}
288
+
}
289
+
290
+
return protocolAndDomain;
291
+
}
292
+
293
+
/// Extracts just the domain part from a URI (removes protocol and path)
294
+
static String _extractDomainOnly(String uri) {
295
+
String domain = uri;
296
+
if (uri.startsWith('https://')) {
297
+
domain = uri.substring(8);
298
+
} else if (uri.startsWith('http://')) {
299
+
domain = uri.substring(7);
300
+
}
301
+
302
+
// Remove path
303
+
final slashIndex = domain.indexOf('/');
304
+
if (slashIndex != -1) {
305
+
domain = domain.substring(0, slashIndex);
306
+
}
307
+
308
+
return domain;
309
+
}
310
+
}
+12
-14
lib/widgets/add_comment_sheet.dart
+12
-14
lib/widgets/add_comment_sheet.dart
···
5
5
import 'package:grain/app_icons.dart';
6
6
import 'package:grain/widgets/app_image.dart';
7
7
import 'package:grain/widgets/gallery_preview.dart';
8
+
import 'package:grain/widgets/faceted_text_field.dart';
8
9
9
10
Future<void> showAddCommentSheet(
10
11
BuildContext context, {
···
185
186
child: Column(
186
187
crossAxisAlignment: CrossAxisAlignment.start,
187
188
children: [
188
-
Row(
189
+
Column(
190
+
crossAxisAlignment: CrossAxisAlignment.start,
189
191
children: [
190
192
Text(
191
193
creator is Map
···
199
201
? (creator['handle'] ?? '')
200
202
: (creator.handle ?? ''))
201
203
.isNotEmpty) ...[
202
-
const SizedBox(width: 8),
204
+
const SizedBox(height: 1),
203
205
Text(
204
206
'@${creator is Map ? creator['handle'] : creator.handle}',
205
207
style: theme.textTheme.bodySmall?.copyWith(
···
315
317
),
316
318
// Text input
317
319
Expanded(
318
-
child: TextField(
319
-
controller: widget.controller,
320
-
focusNode: _focusNode,
321
-
maxLines: 6,
322
-
minLines: 2,
323
-
style: theme.textTheme.bodyMedium,
324
-
decoration: InputDecoration(
320
+
child: Padding(
321
+
padding: const EdgeInsets.only(left: 10),
322
+
child: FacetedTextField(
323
+
controller: widget.controller,
324
+
maxLines: 6,
325
+
enabled: true,
326
+
keyboardType: TextInputType.multiline,
325
327
hintText: 'Add a comment',
326
-
hintStyle: theme.textTheme.bodyMedium?.copyWith(color: theme.hintColor),
327
-
border: InputBorder.none,
328
-
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
329
-
isDense: true,
330
-
filled: false,
328
+
// The FacetedTextField handles its own style and padding internally
331
329
),
332
330
),
333
331
),
+15
lib/widgets/app_drawer.dart
+15
lib/widgets/app_drawer.dart
···
2
2
import 'package:grain/api.dart';
3
3
import 'package:grain/app_icons.dart';
4
4
import 'package:grain/screens/log_page.dart';
5
+
import 'package:grain/screens/photo_library_page.dart';
5
6
import 'package:grain/widgets/app_version_text.dart';
6
7
7
8
class AppDrawer extends StatelessWidget {
···
176
177
onTap: () {
177
178
Navigator.pop(context);
178
179
onProfile();
180
+
},
181
+
),
182
+
ListTile(
183
+
leading: Icon(
184
+
AppIcons.photoLibrary,
185
+
size: 18,
186
+
color: activeIndex == 4 ? theme.colorScheme.primary : theme.iconTheme.color,
187
+
),
188
+
title: const Text('Photo Library'),
189
+
onTap: () {
190
+
Navigator.pop(context);
191
+
Navigator.of(
192
+
context,
193
+
).push(MaterialPageRoute(builder: (context) => const PhotoLibraryPage()));
179
194
},
180
195
),
181
196
ListTile(
+71
-25
lib/widgets/edit_profile_sheet.dart
+71
-25
lib/widgets/edit_profile_sheet.dart
···
4
4
import 'package:flutter/material.dart';
5
5
import 'package:flutter/services.dart';
6
6
import 'package:grain/app_icons.dart';
7
+
import 'package:grain/widgets/faceted_text_field.dart';
7
8
import 'package:grain/widgets/plain_text_field.dart';
8
9
import 'package:image_picker/image_picker.dart';
9
10
···
61
62
late TextEditingController _descriptionController;
62
63
XFile? _selectedAvatar;
63
64
bool _saving = false;
64
-
bool _hasChanged = false;
65
+
static const int maxDisplayNameGraphemes = 64;
66
+
static const int maxDescriptionGraphemes = 256;
65
67
66
68
@override
67
69
void initState() {
···
69
71
_displayNameController = TextEditingController(text: widget.initialDisplayName ?? '');
70
72
_descriptionController = TextEditingController(text: widget.initialDescription ?? '');
71
73
_displayNameController.addListener(_onInputChanged);
72
-
_descriptionController.addListener(_onInputChanged);
74
+
_descriptionController.addListener(_onDescriptionChanged);
75
+
}
76
+
77
+
void _onDescriptionChanged() {
78
+
setState(() {}); // For character count
73
79
}
74
80
75
81
void _onInputChanged() {
76
-
final displayName = _displayNameController.text.trim();
77
-
final initialDisplayName = widget.initialDisplayName ?? '';
78
-
final displayNameChanged = displayName != initialDisplayName;
79
-
final descriptionChanged =
80
-
_descriptionController.text.trim() != (widget.initialDescription ?? '');
81
-
final avatarChanged = _selectedAvatar != null;
82
-
// Only allow Save if displayName is not empty and at least one field changed
83
-
final changed =
84
-
(displayNameChanged || descriptionChanged || avatarChanged) && displayName.isNotEmpty;
85
-
if (_hasChanged != changed) {
86
-
setState(() {
87
-
_hasChanged = changed;
88
-
});
89
-
}
82
+
setState(() {
83
+
// Trigger rebuild to update character counts
84
+
});
90
85
}
91
86
92
87
@override
93
88
void dispose() {
94
-
_displayNameController.removeListener(_onInputChanged);
95
-
_descriptionController.removeListener(_onInputChanged);
96
89
_displayNameController.dispose();
97
90
_descriptionController.dispose();
98
91
super.dispose();
···
104
97
if (picked != null) {
105
98
setState(() {
106
99
_selectedAvatar = picked;
107
-
_onInputChanged();
108
100
});
109
101
}
110
102
}
···
113
105
Widget build(BuildContext context) {
114
106
final theme = Theme.of(context);
115
107
final avatarRadius = 44.0;
108
+
final displayNameGraphemes = _displayNameController.text.characters.length;
109
+
final descriptionGraphemes = _descriptionController.text.characters.length;
116
110
return CupertinoPageScaffold(
117
111
backgroundColor: theme.colorScheme.surface,
118
112
navigationBar: CupertinoNavigationBar(
···
132
126
),
133
127
trailing: CupertinoButton(
134
128
padding: EdgeInsets.zero,
135
-
onPressed: (!_hasChanged || _saving)
129
+
onPressed: _saving
136
130
? null
137
131
: () async {
132
+
if (displayNameGraphemes > maxDisplayNameGraphemes ||
133
+
descriptionGraphemes > maxDescriptionGraphemes) {
134
+
await showDialog(
135
+
context: context,
136
+
builder: (context) => AlertDialog(
137
+
title: const Text('Character Limit Exceeded'),
138
+
content: Text(
139
+
displayNameGraphemes > maxDisplayNameGraphemes
140
+
? 'Display Name must be $maxDisplayNameGraphemes characters or fewer.'
141
+
: 'Description must be $maxDescriptionGraphemes characters or fewer.',
142
+
),
143
+
actions: [
144
+
TextButton(
145
+
child: const Text('OK'),
146
+
onPressed: () => Navigator.of(context).pop(),
147
+
),
148
+
],
149
+
),
150
+
);
151
+
return;
152
+
}
138
153
if (widget.onSave != null) {
139
154
setState(() {
140
155
_saving = true;
···
155
170
Text(
156
171
'Save',
157
172
style: TextStyle(
158
-
color: (!_hasChanged || _saving)
159
-
? theme.disabledColor
160
-
: theme.colorScheme.primary,
173
+
color: _saving ? theme.disabledColor : theme.colorScheme.primary,
161
174
fontWeight: FontWeight.w600,
162
175
),
163
176
),
···
233
246
controller: _displayNameController,
234
247
maxLines: 1,
235
248
),
249
+
Padding(
250
+
padding: const EdgeInsets.only(top: 4),
251
+
child: Row(
252
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
253
+
children: [
254
+
const SizedBox(),
255
+
Text(
256
+
'$displayNameGraphemes/$maxDisplayNameGraphemes',
257
+
style: theme.textTheme.bodySmall?.copyWith(
258
+
color: displayNameGraphemes > maxDisplayNameGraphemes
259
+
? theme.colorScheme.error
260
+
: theme.textTheme.bodySmall?.color,
261
+
),
262
+
),
263
+
],
264
+
),
265
+
),
236
266
const SizedBox(height: 12),
237
-
PlainTextField(
267
+
FacetedTextField(
238
268
label: 'Description',
239
269
controller: _descriptionController,
240
270
maxLines: 6,
241
271
),
272
+
Padding(
273
+
padding: const EdgeInsets.only(top: 4),
274
+
child: Row(
275
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
276
+
children: [
277
+
const SizedBox(),
278
+
Text(
279
+
'$descriptionGraphemes/$maxDescriptionGraphemes',
280
+
style: theme.textTheme.bodySmall?.copyWith(
281
+
color: descriptionGraphemes > maxDescriptionGraphemes
282
+
? theme.colorScheme.error
283
+
: theme.textTheme.bodySmall?.color,
284
+
),
285
+
),
286
+
],
287
+
),
288
+
),
242
289
],
243
290
),
244
291
),
245
292
),
246
-
const SizedBox(height: 24),
247
293
],
248
294
),
249
295
),
+14
-63
lib/widgets/faceted_text.dart
+14
-63
lib/widgets/faceted_text.dart
···
1
-
import 'package:flutter/gestures.dart';
2
1
import 'package:flutter/material.dart';
2
+
3
+
import '../utils/facet_utils.dart';
3
4
4
5
class FacetedText extends StatelessWidget {
5
6
final String text;
···
32
33
fontWeight: FontWeight.w600,
33
34
decoration: TextDecoration.underline,
34
35
);
36
+
35
37
if (facets == null || facets!.isEmpty) {
36
38
return Text(text, style: defaultStyle);
37
39
}
38
-
// Build a list of all ranges (start, end, type, data)
39
-
final List<_FacetRange> ranges = facets!.map((facet) {
40
-
final feature = facet['features']?[0] ?? {};
41
-
final type = feature['\$type'] ?? feature['type'];
42
-
return _FacetRange(
43
-
start: facet['index']?['byteStart'] ?? facet['byteStart'] ?? 0,
44
-
end: facet['index']?['byteEnd'] ?? facet['byteEnd'] ?? 0,
45
-
type: type,
46
-
data: feature,
47
-
);
48
-
}).toList();
49
-
ranges.sort((a, b) => a.start.compareTo(b.start));
50
-
int pos = 0;
51
-
final spans = <TextSpan>[];
52
-
for (final range in ranges) {
53
-
if (range.start > pos) {
54
-
spans.add(TextSpan(text: text.substring(pos, range.start), style: defaultStyle));
55
-
}
56
-
final content = text.substring(range.start, range.end);
57
-
if (range.type?.contains('mention') == true && range.data['did'] != null) {
58
-
spans.add(
59
-
TextSpan(
60
-
text: content,
61
-
style: defaultLinkStyle,
62
-
recognizer: TapGestureRecognizer()
63
-
..onTap = onMentionTap != null ? () => onMentionTap!(range.data['did']) : null,
64
-
),
65
-
);
66
-
} else if (range.type?.contains('link') == true && range.data['uri'] != null) {
67
-
spans.add(
68
-
TextSpan(
69
-
text: content,
70
-
style: defaultLinkStyle,
71
-
recognizer: TapGestureRecognizer()
72
-
..onTap = onLinkTap != null ? () => onLinkTap!(range.data['uri']) : null,
73
-
),
74
-
);
75
-
} else if (range.type?.contains('tag') == true && range.data['tag'] != null) {
76
-
spans.add(
77
-
TextSpan(
78
-
text: '#${range.data['tag']}',
79
-
style: defaultLinkStyle,
80
-
recognizer: TapGestureRecognizer()
81
-
..onTap = onTagTap != null ? () => onTagTap!(range.data['tag']) : null,
82
-
),
83
-
);
84
-
} else {
85
-
spans.add(TextSpan(text: content, style: defaultStyle));
86
-
}
87
-
pos = range.end;
88
-
}
89
-
if (pos < text.length) {
90
-
spans.add(TextSpan(text: text.substring(pos), style: defaultStyle));
91
-
}
40
+
41
+
final spans = FacetUtils.processFacets(
42
+
text: text,
43
+
facets: facets,
44
+
defaultStyle: defaultStyle,
45
+
linkStyle: defaultLinkStyle,
46
+
onMentionTap: onMentionTap,
47
+
onLinkTap: onLinkTap,
48
+
onTagTap: onTagTap,
49
+
);
50
+
92
51
return RichText(text: TextSpan(children: spans));
93
52
}
94
53
}
95
-
96
-
class _FacetRange {
97
-
final int start;
98
-
final int end;
99
-
final String? type;
100
-
final Map<String, dynamic> data;
101
-
_FacetRange({required this.start, required this.end, required this.type, required this.data});
102
-
}
+473
lib/widgets/faceted_text_field.dart
+473
lib/widgets/faceted_text_field.dart
···
1
+
import 'dart:async';
2
+
3
+
import 'package:bluesky_text/bluesky_text.dart';
4
+
import 'package:flutter/material.dart';
5
+
import 'package:flutter_riverpod/flutter_riverpod.dart';
6
+
7
+
import '../models/profile.dart';
8
+
import '../providers/actor_search_provider.dart';
9
+
import '../utils/facet_utils.dart';
10
+
11
+
class FacetedTextField extends ConsumerStatefulWidget {
12
+
final String? label;
13
+
final TextEditingController controller;
14
+
final int maxLines;
15
+
final bool enabled;
16
+
final TextInputType? keyboardType;
17
+
final String? hintText;
18
+
final void Function(String)? onChanged;
19
+
final Widget? prefixIcon;
20
+
final Widget? suffixIcon;
21
+
final List<Map<String, dynamic>>? facets;
22
+
23
+
const FacetedTextField({
24
+
super.key,
25
+
this.label,
26
+
required this.controller,
27
+
this.maxLines = 1,
28
+
this.enabled = true,
29
+
this.keyboardType,
30
+
this.hintText,
31
+
this.onChanged,
32
+
this.prefixIcon,
33
+
this.suffixIcon,
34
+
this.facets,
35
+
});
36
+
37
+
@override
38
+
ConsumerState<FacetedTextField> createState() => _FacetedTextFieldState();
39
+
}
40
+
41
+
class _FacetedTextFieldState extends ConsumerState<FacetedTextField> {
42
+
// Track which handles have been inserted via overlay selection
43
+
final Set<String> _insertedHandles = {};
44
+
OverlayEntry? _overlayEntry;
45
+
final GlobalKey _fieldKey = GlobalKey();
46
+
List<Profile> _actorResults = [];
47
+
Timer? _debounceTimer;
48
+
49
+
@override
50
+
void initState() {
51
+
super.initState();
52
+
widget.controller.addListener(_onTextChanged);
53
+
}
54
+
55
+
@override
56
+
void dispose() {
57
+
widget.controller.removeListener(_onTextChanged);
58
+
_debounceTimer?.cancel();
59
+
_removeOverlay();
60
+
super.dispose();
61
+
}
62
+
63
+
void _onTextChanged() async {
64
+
final text = widget.controller.text;
65
+
final selection = widget.controller.selection;
66
+
final cursorPos = selection.baseOffset;
67
+
if (cursorPos < 0) {
68
+
_removeOverlay();
69
+
return;
70
+
}
71
+
// If the last character typed is a space, always close overlay
72
+
if (cursorPos > 0 && text[cursorPos - 1] == ' ') {
73
+
_removeOverlay();
74
+
return;
75
+
}
76
+
// Find the @mention match that contains the cursor
77
+
final regex = RegExp(r'@([\w.]+)');
78
+
final matches = regex.allMatches(text);
79
+
String? query;
80
+
for (final match in matches) {
81
+
final start = match.start;
82
+
final end = match.end;
83
+
if (cursorPos > start && cursorPos <= end) {
84
+
query = match.group(1);
85
+
break;
86
+
}
87
+
}
88
+
if (query != null && query.isNotEmpty) {
89
+
_debounceTimer?.cancel();
90
+
_debounceTimer = Timer(const Duration(milliseconds: 500), () async {
91
+
final results = await ref.read(actorSearchProvider.notifier).search(query!);
92
+
if (mounted) {
93
+
setState(() {
94
+
_actorResults = results;
95
+
});
96
+
_showOverlay();
97
+
}
98
+
});
99
+
return;
100
+
}
101
+
_debounceTimer?.cancel();
102
+
_removeOverlay();
103
+
}
104
+
105
+
void _showOverlay() {
106
+
WidgetsBinding.instance.addPostFrameCallback((_) {
107
+
_removeOverlay();
108
+
final overlay = Overlay.of(context);
109
+
final caretOffset = _getCaretPosition();
110
+
if (caretOffset == null) return;
111
+
112
+
// Show only the first 5 results, no scroll, use simple rows
113
+
final double rowHeight = 44.0;
114
+
final int maxItems = 5;
115
+
final resultsToShow = _actorResults.take(maxItems).toList();
116
+
final double overlayHeight = resultsToShow.length * rowHeight;
117
+
final double overlayWidth = 300.0;
118
+
119
+
// Get screen size
120
+
final mediaQuery = MediaQuery.of(context);
121
+
final screenWidth = mediaQuery.size.width;
122
+
123
+
// Default to left of caret, but if it would overflow, switch to right
124
+
double left = caretOffset.dx;
125
+
if (left + overlayWidth > screenWidth - 8) {
126
+
// Try to align right edge of overlay with caret, but don't go off left edge
127
+
left = (caretOffset.dx - overlayWidth).clamp(8.0, screenWidth - overlayWidth - 8.0);
128
+
}
129
+
130
+
_overlayEntry = OverlayEntry(
131
+
builder: (context) => Positioned(
132
+
left: left,
133
+
top: caretOffset.dy,
134
+
width: overlayWidth,
135
+
height: overlayHeight,
136
+
child: Material(
137
+
elevation: 4,
138
+
child: Column(
139
+
mainAxisSize: MainAxisSize.min,
140
+
children: resultsToShow.map((actor) {
141
+
return Material(
142
+
color: Colors.transparent,
143
+
child: InkWell(
144
+
onTap: () => _insertActor(actor.handle),
145
+
child: Container(
146
+
height: rowHeight,
147
+
width: double.infinity,
148
+
alignment: Alignment.centerLeft,
149
+
padding: const EdgeInsets.symmetric(horizontal: 12.0),
150
+
child: Row(
151
+
children: [
152
+
if (actor.avatar != null && actor.avatar!.isNotEmpty)
153
+
CircleAvatar(radius: 16, backgroundImage: NetworkImage(actor.avatar!))
154
+
else
155
+
CircleAvatar(radius: 16, child: Icon(Icons.person, size: 16)),
156
+
const SizedBox(width: 12),
157
+
Expanded(
158
+
child: Text(
159
+
actor.displayName ?? actor.handle,
160
+
style: Theme.of(context).textTheme.bodyMedium,
161
+
overflow: TextOverflow.ellipsis,
162
+
),
163
+
),
164
+
const SizedBox(width: 8),
165
+
Text(
166
+
'@${actor.handle}',
167
+
style: Theme.of(
168
+
context,
169
+
).textTheme.bodySmall?.copyWith(color: Colors.grey[600]),
170
+
overflow: TextOverflow.ellipsis,
171
+
),
172
+
],
173
+
),
174
+
),
175
+
),
176
+
);
177
+
}).toList(),
178
+
),
179
+
),
180
+
),
181
+
);
182
+
overlay.insert(_overlayEntry!);
183
+
});
184
+
}
185
+
186
+
void _removeOverlay() {
187
+
if (_overlayEntry != null) {
188
+
_overlayEntry?.remove();
189
+
_overlayEntry = null;
190
+
}
191
+
}
192
+
193
+
Offset? _getCaretPosition() {
194
+
final renderBox = _fieldKey.currentContext?.findRenderObject() as RenderBox?;
195
+
if (renderBox == null) return null;
196
+
197
+
final controller = widget.controller;
198
+
final selection = controller.selection;
199
+
if (!selection.isValid) return null;
200
+
201
+
// Get the text up to the caret
202
+
final text = controller.text.substring(0, selection.baseOffset);
203
+
final textStyle =
204
+
Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15) ??
205
+
const TextStyle(fontSize: 15);
206
+
final textPainter = TextPainter(
207
+
text: TextSpan(text: text, style: textStyle),
208
+
textDirection: TextDirection.ltr,
209
+
maxLines: widget.maxLines,
210
+
);
211
+
textPainter.layout(minWidth: 0, maxWidth: renderBox.size.width);
212
+
213
+
final caretOffset = textPainter.getOffsetForCaret(TextPosition(offset: text.length), Rect.zero);
214
+
215
+
// Convert caret offset to global coordinates
216
+
final fieldOffset = renderBox.localToGlobal(Offset.zero);
217
+
// Add vertical padding to position below the caret
218
+
return fieldOffset + Offset(caretOffset.dx, caretOffset.dy + textPainter.preferredLineHeight);
219
+
}
220
+
221
+
void _insertActor(String actorName) {
222
+
final text = widget.controller.text;
223
+
final selection = widget.controller.selection;
224
+
final cursorPos = selection.baseOffset;
225
+
// Find the @mention match that contains the cursor (not just before it)
226
+
final regex = RegExp(r'@([\w.]+)');
227
+
final matches = regex.allMatches(text);
228
+
Match? matchToReplace;
229
+
for (final match in matches) {
230
+
if (cursorPos > match.start && cursorPos <= match.end) {
231
+
matchToReplace = match;
232
+
break;
233
+
}
234
+
}
235
+
if (matchToReplace != null) {
236
+
final start = matchToReplace.start;
237
+
final end = matchToReplace.end;
238
+
final newText = text.replaceRange(start, end, '@$actorName ');
239
+
setState(() {
240
+
_insertedHandles.add(actorName);
241
+
});
242
+
widget.controller.value = TextEditingValue(
243
+
text: newText,
244
+
selection: TextSelection.collapsed(offset: start + actorName.length + 2),
245
+
);
246
+
}
247
+
_removeOverlay();
248
+
}
249
+
250
+
@override
251
+
Widget build(BuildContext context) {
252
+
final theme = Theme.of(context);
253
+
return Column(
254
+
crossAxisAlignment: CrossAxisAlignment.start,
255
+
children: [
256
+
if (widget.label != null && widget.label!.isNotEmpty) ...[
257
+
Text(
258
+
widget.label!,
259
+
style: theme.textTheme.bodyMedium?.copyWith(
260
+
fontWeight: FontWeight.w500,
261
+
color: theme.colorScheme.onSurface,
262
+
),
263
+
),
264
+
const SizedBox(height: 6),
265
+
],
266
+
Container(
267
+
decoration: BoxDecoration(
268
+
color: theme.brightness == Brightness.dark ? Colors.grey[850] : Colors.grey[300],
269
+
borderRadius: BorderRadius.circular(8),
270
+
),
271
+
child: Focus(
272
+
child: Builder(
273
+
builder: (context) {
274
+
final isFocused = Focus.of(context).hasFocus;
275
+
return Stack(
276
+
children: [
277
+
_MentionHighlightTextField(
278
+
key: _fieldKey,
279
+
controller: widget.controller,
280
+
maxLines: widget.maxLines,
281
+
enabled: widget.enabled,
282
+
keyboardType: widget.keyboardType,
283
+
onChanged: widget.onChanged,
284
+
hintText: widget.hintText,
285
+
prefixIcon: widget.prefixIcon,
286
+
suffixIcon: widget.suffixIcon,
287
+
insertedHandles: _insertedHandles,
288
+
facets: widget.facets,
289
+
),
290
+
// Border overlay
291
+
Positioned.fill(
292
+
child: IgnorePointer(
293
+
child: AnimatedContainer(
294
+
duration: const Duration(milliseconds: 150),
295
+
decoration: BoxDecoration(
296
+
border: Border.all(
297
+
color: isFocused ? theme.colorScheme.primary : theme.dividerColor,
298
+
width: isFocused ? 2 : 0,
299
+
),
300
+
borderRadius: BorderRadius.circular(8),
301
+
),
302
+
),
303
+
),
304
+
),
305
+
],
306
+
);
307
+
},
308
+
),
309
+
),
310
+
),
311
+
],
312
+
);
313
+
}
314
+
}
315
+
316
+
class _MentionHighlightTextField extends StatefulWidget {
317
+
final Set<String>? insertedHandles;
318
+
final TextEditingController controller;
319
+
final int maxLines;
320
+
final bool enabled;
321
+
final TextInputType? keyboardType;
322
+
final String? hintText;
323
+
final void Function(String)? onChanged;
324
+
final Widget? prefixIcon;
325
+
final Widget? suffixIcon;
326
+
final List<Map<String, dynamic>>? facets;
327
+
328
+
const _MentionHighlightTextField({
329
+
super.key,
330
+
required this.controller,
331
+
required this.maxLines,
332
+
required this.enabled,
333
+
this.keyboardType,
334
+
this.hintText,
335
+
this.onChanged,
336
+
this.prefixIcon,
337
+
this.suffixIcon,
338
+
this.insertedHandles,
339
+
this.facets,
340
+
});
341
+
342
+
@override
343
+
State<_MentionHighlightTextField> createState() => _MentionHighlightTextFieldState();
344
+
}
345
+
346
+
class _MentionHighlightTextFieldState extends State<_MentionHighlightTextField> {
347
+
final ScrollController _richTextScrollController = ScrollController();
348
+
final ScrollController _textFieldScrollController = ScrollController();
349
+
350
+
void _onMentionTap(String did) {
351
+
// Show overlay for this mention (simulate as if user is typing @mention)
352
+
final parent = context.findAncestorStateOfType<_FacetedTextFieldState>();
353
+
if (parent != null) {
354
+
parent._showOverlay();
355
+
}
356
+
}
357
+
358
+
List<Map<String, dynamic>> _parsedFacets = [];
359
+
Timer? _facetDebounce;
360
+
361
+
@override
362
+
void initState() {
363
+
super.initState();
364
+
_parseFacets();
365
+
widget.controller.addListener(_parseFacets);
366
+
367
+
// Sync scroll controllers
368
+
_textFieldScrollController.addListener(() {
369
+
if (_richTextScrollController.hasClients && _textFieldScrollController.hasClients) {
370
+
_richTextScrollController.jumpTo(_textFieldScrollController.offset);
371
+
}
372
+
});
373
+
}
374
+
375
+
@override
376
+
void dispose() {
377
+
widget.controller.removeListener(_parseFacets);
378
+
_facetDebounce?.cancel();
379
+
_richTextScrollController.dispose();
380
+
_textFieldScrollController.dispose();
381
+
super.dispose();
382
+
}
383
+
384
+
void _parseFacets() {
385
+
_facetDebounce?.cancel();
386
+
_facetDebounce = Timer(const Duration(milliseconds: 100), () async {
387
+
final text = widget.controller.text;
388
+
if (widget.facets != null && widget.facets!.isNotEmpty) {
389
+
setState(() => _parsedFacets = widget.facets!);
390
+
} else {
391
+
try {
392
+
final blueskyText = BlueskyText(text);
393
+
final entities = blueskyText.entities;
394
+
final facets = await entities.toFacets();
395
+
if (mounted) setState(() => _parsedFacets = List<Map<String, dynamic>>.from(facets));
396
+
} catch (_) {
397
+
if (mounted) setState(() => _parsedFacets = []);
398
+
}
399
+
}
400
+
});
401
+
}
402
+
403
+
@override
404
+
Widget build(BuildContext context) {
405
+
final theme = Theme.of(context);
406
+
final text = widget.controller.text;
407
+
final baseStyle = theme.textTheme.bodyMedium?.copyWith(fontSize: 15);
408
+
final linkStyle = baseStyle?.copyWith(color: theme.colorScheme.primary);
409
+
410
+
// Use the same facet processing logic as FacetedText
411
+
final spans = FacetUtils.processFacets(
412
+
text: text,
413
+
facets: _parsedFacets,
414
+
defaultStyle: baseStyle,
415
+
linkStyle: linkStyle,
416
+
onMentionTap: _onMentionTap,
417
+
onLinkTap: null, // No link tap in text field
418
+
onTagTap: null, // No tag tap in text field
419
+
);
420
+
return LayoutBuilder(
421
+
builder: (context, constraints) {
422
+
return SizedBox(
423
+
width: double.infinity, // Make it full width
424
+
height: widget.maxLines == 1
425
+
? null
426
+
: (baseStyle?.fontSize ?? 15) * 1.4 * widget.maxLines +
427
+
24, // Line height * maxLines + padding
428
+
child: Stack(
429
+
children: [
430
+
// RichText for highlight wrapped in SingleChildScrollView
431
+
SingleChildScrollView(
432
+
controller: _richTextScrollController,
433
+
physics: const NeverScrollableScrollPhysics(), // Disable direct interaction
434
+
child: Padding(
435
+
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
436
+
child: RichText(
437
+
text: TextSpan(children: spans),
438
+
maxLines: null, // Allow unlimited lines for scrolling
439
+
overflow: TextOverflow.visible,
440
+
),
441
+
),
442
+
),
443
+
// Editable TextField for input, but with transparent text so only RichText is visible
444
+
Positioned.fill(
445
+
child: TextField(
446
+
controller: widget.controller,
447
+
scrollController: _textFieldScrollController,
448
+
maxLines: null, // Allow unlimited lines for scrolling
449
+
enabled: widget.enabled,
450
+
keyboardType: widget.keyboardType,
451
+
onChanged: widget.onChanged,
452
+
style: baseStyle?.copyWith(color: const Color(0x01000000)),
453
+
cursorColor: theme.colorScheme.primary,
454
+
showCursor: true,
455
+
enableInteractiveSelection: true,
456
+
decoration: InputDecoration(
457
+
hintText: widget.hintText,
458
+
hintStyle: baseStyle?.copyWith(color: theme.hintColor),
459
+
border: InputBorder.none,
460
+
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
461
+
isDense: true,
462
+
prefixIcon: widget.prefixIcon,
463
+
suffixIcon: widget.suffixIcon,
464
+
),
465
+
),
466
+
),
467
+
],
468
+
),
469
+
);
470
+
},
471
+
);
472
+
}
473
+
}
+20
-1
lib/widgets/gallery_photo_view.dart
+20
-1
lib/widgets/gallery_photo_view.dart
···
128
128
final gallery = widget.gallery;
129
129
final subject = gallery?.uri;
130
130
final focus = photo.uri;
131
-
if (subject == null || focus == null) {
131
+
if (subject == null) {
132
132
return;
133
133
}
134
134
// Use the provider's createComment method
···
165
165
},
166
166
),
167
167
],
168
+
),
169
+
),
170
+
),
171
+
if (!widget.showAddCommentButton && photo.exif != null)
172
+
SafeArea(
173
+
top: false,
174
+
child: Padding(
175
+
padding: const EdgeInsets.all(16),
176
+
child: Align(
177
+
alignment: Alignment.centerRight,
178
+
child: IconButton(
179
+
icon: Icon(Icons.camera_alt, color: Colors.white),
180
+
onPressed: () {
181
+
showDialog(
182
+
context: context,
183
+
builder: (context) => PhotoExifDialog(exif: photo.exif!),
184
+
);
185
+
},
186
+
),
168
187
),
169
188
),
170
189
),
+44
-23
lib/widgets/timeline_item.dart
+44
-23
lib/widgets/timeline_item.dart
···
8
8
import 'package:grain/widgets/faceted_text.dart';
9
9
import 'package:grain/widgets/gallery_action_buttons.dart';
10
10
import 'package:grain/widgets/gallery_preview.dart';
11
+
import 'package:url_launcher/url_launcher.dart';
11
12
12
13
import '../providers/gallery_cache_provider.dart';
13
14
import '../screens/gallery_page.dart';
···
73
74
mainAxisAlignment: MainAxisAlignment.spaceBetween,
74
75
children: [
75
76
Flexible(
76
-
child: Text.rich(
77
-
TextSpan(
78
-
children: [
79
-
if (actor?.displayName?.isNotEmpty ?? false)
80
-
TextSpan(
81
-
text: actor!.displayName ?? '',
82
-
style: theme.textTheme.titleMedium?.copyWith(
83
-
fontWeight: FontWeight.w600,
84
-
fontSize: 16,
77
+
child: GestureDetector(
78
+
onTap:
79
+
onProfileTap ??
80
+
() {
81
+
if (actor?.did != null) {
82
+
Navigator.of(context).push(
83
+
MaterialPageRoute(
84
+
builder: (context) =>
85
+
ProfilePage(did: actor!.did, showAppBar: true),
86
+
),
87
+
);
88
+
}
89
+
},
90
+
child: Text.rich(
91
+
TextSpan(
92
+
children: [
93
+
if (actor?.displayName?.isNotEmpty ?? false)
94
+
TextSpan(
95
+
text: actor!.displayName ?? '',
96
+
style: theme.textTheme.titleMedium?.copyWith(
97
+
fontWeight: FontWeight.w600,
98
+
fontSize: 16,
99
+
),
85
100
),
86
-
),
87
-
if (actor != null && actor.handle.isNotEmpty)
88
-
TextSpan(
89
-
text: (actor.displayName?.isNotEmpty ?? false)
90
-
? ' @${actor.handle}'
91
-
: '@${actor.handle}',
92
-
style: theme.textTheme.bodySmall?.copyWith(
93
-
fontSize: 14,
94
-
color: theme.colorScheme.onSurfaceVariant,
95
-
fontWeight: FontWeight.normal,
101
+
if (actor != null && actor.handle.isNotEmpty)
102
+
TextSpan(
103
+
text: (actor.displayName?.isNotEmpty ?? false)
104
+
? ' @${actor.handle}'
105
+
: '@${actor.handle}',
106
+
style: theme.textTheme.bodySmall?.copyWith(
107
+
fontSize: 14,
108
+
color: theme.colorScheme.onSurfaceVariant,
109
+
fontWeight: FontWeight.normal,
110
+
),
96
111
),
97
-
),
98
-
],
112
+
],
113
+
),
114
+
overflow: TextOverflow.ellipsis,
115
+
maxLines: 1,
99
116
),
100
-
overflow: TextOverflow.ellipsis,
101
-
maxLines: 1,
102
117
),
103
118
),
104
119
Text(
···
159
174
context,
160
175
MaterialPageRoute(builder: (_) => HashtagPage(hashtag: tag)),
161
176
),
177
+
onLinkTap: (url) async {
178
+
final uri = Uri.parse(url);
179
+
if (!await launchUrl(uri)) {
180
+
throw Exception('Could not launch $url');
181
+
}
182
+
},
162
183
),
163
184
),
164
185
const SizedBox(height: 8),
+104
lib/widgets/upload_progress_overlay.dart
+104
lib/widgets/upload_progress_overlay.dart
···
1
+
import 'dart:io';
2
+
3
+
import 'package:flutter/material.dart';
4
+
5
+
import '../screens/create_gallery_page.dart';
6
+
7
+
class UploadProgressOverlay extends StatelessWidget {
8
+
final List<GalleryImage> images;
9
+
final int currentIndex;
10
+
final double progress; // 0.0 - 1.0
11
+
final bool visible;
12
+
13
+
const UploadProgressOverlay({
14
+
super.key,
15
+
required this.images,
16
+
required this.currentIndex,
17
+
required this.progress,
18
+
this.visible = false,
19
+
});
20
+
21
+
@override
22
+
Widget build(BuildContext context) {
23
+
if (!visible) return const SizedBox.shrink();
24
+
final theme = Theme.of(context);
25
+
26
+
// Get the current image being uploaded
27
+
final currentImage = currentIndex < images.length ? images[currentIndex] : null;
28
+
29
+
// Calculate overall progress: completed images + current image's progress
30
+
double overallProgress = 0.0;
31
+
if (images.isNotEmpty) {
32
+
overallProgress = (currentIndex + progress) / images.length;
33
+
}
34
+
35
+
return Material(
36
+
color: Colors.transparent,
37
+
child: Stack(
38
+
children: [
39
+
Positioned.fill(child: Container(color: Colors.black.withOpacity(0.9))),
40
+
Center(
41
+
child: Padding(
42
+
padding: const EdgeInsets.all(32),
43
+
child: Column(
44
+
mainAxisSize: MainAxisSize.min,
45
+
mainAxisAlignment: MainAxisAlignment.center,
46
+
children: [
47
+
Row(
48
+
mainAxisSize: MainAxisSize.min,
49
+
children: [
50
+
SizedBox(
51
+
width: 24,
52
+
height: 24,
53
+
child: CircularProgressIndicator(
54
+
strokeWidth: 2.5,
55
+
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
56
+
),
57
+
),
58
+
const SizedBox(width: 12),
59
+
Text(
60
+
'Uploading photos...',
61
+
style: theme.textTheme.titleMedium?.copyWith(color: Colors.white),
62
+
),
63
+
],
64
+
),
65
+
const SizedBox(height: 16),
66
+
67
+
// Show current image at true aspect ratio
68
+
if (currentImage != null)
69
+
Container(
70
+
constraints: const BoxConstraints(maxWidth: 300, maxHeight: 300),
71
+
child: Image.file(
72
+
File(currentImage.file.path),
73
+
fit: BoxFit.contain, // Maintain aspect ratio
74
+
),
75
+
),
76
+
77
+
const SizedBox(height: 16),
78
+
79
+
// Progress indicator (overall progress)
80
+
SizedBox(
81
+
width: 300,
82
+
child: LinearProgressIndicator(
83
+
value: overallProgress,
84
+
backgroundColor: theme.colorScheme.surfaceContainerHighest.withOpacity(0.5),
85
+
valueColor: AlwaysStoppedAnimation<Color>(theme.colorScheme.primary),
86
+
),
87
+
),
88
+
89
+
const SizedBox(height: 8),
90
+
91
+
// Position counter and progress percentage
92
+
Text(
93
+
'${currentIndex + 1} of ${images.length} โข ${(overallProgress * 100).toInt()}%',
94
+
style: theme.textTheme.bodyMedium?.copyWith(color: Colors.white70),
95
+
),
96
+
],
97
+
),
98
+
),
99
+
),
100
+
],
101
+
),
102
+
);
103
+
}
104
+
}
+8
-8
pubspec.lock
+8
-8
pubspec.lock
···
149
149
dependency: transitive
150
150
description:
151
151
name: built_value
152
-
sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27"
152
+
sha256: "0b1b12a0a549605e5f04476031cd0bc91ead1d7c8e830773a18ee54179b3cb62"
153
153
url: "https://pub.dev"
154
154
source: hosted
155
-
version: "8.10.1"
155
+
version: "8.11.0"
156
156
cached_network_image:
157
157
dependency: "direct main"
158
158
description:
···
309
309
dependency: transitive
310
310
description:
311
311
name: dart_style
312
-
sha256: "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af"
312
+
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb"
313
313
url: "https://pub.dev"
314
314
source: hosted
315
-
version: "3.1.0"
315
+
version: "3.1.1"
316
316
desktop_webview_window:
317
317
dependency: transitive
318
318
description:
···
620
620
dependency: transitive
621
621
description:
622
622
name: image_picker_android
623
-
sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb"
623
+
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
624
624
url: "https://pub.dev"
625
625
source: hosted
626
-
version: "0.8.12+23"
626
+
version: "0.8.12+24"
627
627
image_picker_for_web:
628
628
dependency: transitive
629
629
description:
···
748
748
dependency: "direct main"
749
749
description:
750
750
name: logger
751
-
sha256: "2621da01aabaf223f8f961e751f2c943dbb374dc3559b982f200ccedadaa6999"
751
+
sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c"
752
752
url: "https://pub.dev"
753
753
source: hosted
754
-
version: "2.6.0"
754
+
version: "2.6.1"
755
755
logging:
756
756
dependency: transitive
757
757
description:
+2
-2
pubspec.yaml
+2
-2
pubspec.yaml
···
1
1
name: grain
2
-
description: "A new Flutter project."
2
+
description: "Grain Social Mobile App"
3
3
# The following line prevents the package from being accidentally published to
4
4
# pub.dev using `flutter pub publish`. This is preferred for private packages.
5
5
publish_to: "none" # Remove this line if you wish to publish to pub.dev
···
16
16
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17
17
# In Windows, build-name is used as the major, minor, and patch parts
18
18
# of the product and file versions while build-number is used as the build suffix.
19
-
version: 1.0.0+15
19
+
version: 1.0.0+24
20
20
21
21
environment:
22
22
sdk: ^3.8.1