From 6008a8782249f3e7644eea5d3761a39fd6ae535e Mon Sep 17 00:00:00 2001 From: myConsciousness Date: Fri, 30 Dec 2022 20:48:24 +0900 Subject: [PATCH 1/3] feat: fixed for the issue (#30) Co-authored-by: myConsciousness --- CHANGELOG.md | 3 + lib/mastodon_api.dart | 2 + lib/src/service/entities/position_marker.dart | 29 +++ .../entities/position_marker.freezed.dart | 207 +++++++++++++++++ .../service/entities/position_marker.g.dart | 34 +++ .../service/entities/timeline_snapshot.dart | 29 +++ .../entities/timeline_snapshot.freezed.dart | 213 ++++++++++++++++++ .../service/entities/timeline_snapshot.g.dart | 45 ++++ .../v1/timelines/timelines_v1_service.dart | 58 +++++ 9 files changed, 620 insertions(+) create mode 100644 lib/src/service/entities/position_marker.dart create mode 100644 lib/src/service/entities/position_marker.freezed.dart create mode 100644 lib/src/service/entities/position_marker.g.dart create mode 100644 lib/src/service/entities/timeline_snapshot.dart create mode 100644 lib/src/service/entities/timeline_snapshot.freezed.dart create mode 100644 lib/src/service/entities/timeline_snapshot.g.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index e22c977..726e6a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ - `GET /api/v1/conversations` - `DELETE /api/v1/conversations/:id` - `POST /api/v1/conversations/:id/read` +- Supported `markers API methods`. ([#30](https://github.com/mastodon-dart/mastodon-api/issues/30)) + - `GET /api/v1/markers` + - `POST /api/v1/markers` ## v0.2.2 diff --git a/lib/mastodon_api.dart b/lib/mastodon_api.dart index 5f80198..e913ae2 100644 --- a/lib/mastodon_api.dart +++ b/lib/mastodon_api.dart @@ -46,6 +46,7 @@ export 'package:mastodon_api/src/service/entities/media_attachment.dart'; export 'package:mastodon_api/src/service/entities/media_attachment_type.dart'; export 'package:mastodon_api/src/service/entities/poll.dart'; export 'package:mastodon_api/src/service/entities/poll_option.dart'; +export 'package:mastodon_api/src/service/entities/position_marker.dart'; export 'package:mastodon_api/src/service/entities/preview_card.dart'; export 'package:mastodon_api/src/service/entities/preview_card_type.dart'; export 'package:mastodon_api/src/service/entities/rate_limit.dart'; @@ -56,6 +57,7 @@ export 'package:mastodon_api/src/service/entities/suggestion.dart'; export 'package:mastodon_api/src/service/entities/tag.dart'; export 'package:mastodon_api/src/service/entities/thumbnail.dart'; export 'package:mastodon_api/src/service/entities/thumbnail_version.dart'; +export 'package:mastodon_api/src/service/entities/timeline_snapshot.dart'; export 'package:mastodon_api/src/service/entities/token.dart'; export 'package:mastodon_api/src/service/entities/usage_statistics.dart'; export 'package:mastodon_api/src/service/mastodon_v1_service.dart'; diff --git a/lib/src/service/entities/position_marker.dart b/lib/src/service/entities/position_marker.dart new file mode 100644 index 0000000..5c9c6c3 --- /dev/null +++ b/lib/src/service/entities/position_marker.dart @@ -0,0 +1,29 @@ +// Copyright 2022 Kato Shinya. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided the conditions. + +// ignore_for_file: invalid_annotation_target + +// πŸ“¦ Package imports: +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'position_marker.freezed.dart'; +part 'position_marker.g.dart'; + +/// Represents the last read position within a user's timelines. +@freezed +class PositionMarker with _$PositionMarker { + const factory PositionMarker({ + /// The ID of the most recently viewed entity. + required String lastReadId, + + /// An incrementing counter, used for locking to prevent write conflicts. + required int version, + + /// The timestamp of when the marker was set. + required DateTime updatedAt, + }) = _PositionMarker; + + factory PositionMarker.fromJson(Map json) => + _$PositionMarkerFromJson(json); +} diff --git a/lib/src/service/entities/position_marker.freezed.dart b/lib/src/service/entities/position_marker.freezed.dart new file mode 100644 index 0000000..5cf9783 --- /dev/null +++ b/lib/src/service/entities/position_marker.freezed.dart @@ -0,0 +1,207 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// 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 + +part of 'position_marker.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + '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#custom-getters-and-methods'); + +PositionMarker _$PositionMarkerFromJson(Map json) { + return _PositionMarker.fromJson(json); +} + +/// @nodoc +mixin _$PositionMarker { + /// The ID of the most recently viewed entity. + String get lastReadId => throw _privateConstructorUsedError; + + /// An incrementing counter, used for locking to prevent write conflicts. + int get version => throw _privateConstructorUsedError; + + /// The timestamp of when the marker was set. + DateTime get updatedAt => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $PositionMarkerCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PositionMarkerCopyWith<$Res> { + factory $PositionMarkerCopyWith( + PositionMarker value, $Res Function(PositionMarker) then) = + _$PositionMarkerCopyWithImpl<$Res, PositionMarker>; + @useResult + $Res call({String lastReadId, int version, DateTime updatedAt}); +} + +/// @nodoc +class _$PositionMarkerCopyWithImpl<$Res, $Val extends PositionMarker> + implements $PositionMarkerCopyWith<$Res> { + _$PositionMarkerCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? lastReadId = null, + Object? version = null, + Object? updatedAt = null, + }) { + return _then(_value.copyWith( + lastReadId: null == lastReadId + ? _value.lastReadId + : lastReadId // ignore: cast_nullable_to_non_nullable + as String, + version: null == version + ? _value.version + : version // ignore: cast_nullable_to_non_nullable + as int, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_PositionMarkerCopyWith<$Res> + implements $PositionMarkerCopyWith<$Res> { + factory _$$_PositionMarkerCopyWith( + _$_PositionMarker value, $Res Function(_$_PositionMarker) then) = + __$$_PositionMarkerCopyWithImpl<$Res>; + @override + @useResult + $Res call({String lastReadId, int version, DateTime updatedAt}); +} + +/// @nodoc +class __$$_PositionMarkerCopyWithImpl<$Res> + extends _$PositionMarkerCopyWithImpl<$Res, _$_PositionMarker> + implements _$$_PositionMarkerCopyWith<$Res> { + __$$_PositionMarkerCopyWithImpl( + _$_PositionMarker _value, $Res Function(_$_PositionMarker) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? lastReadId = null, + Object? version = null, + Object? updatedAt = null, + }) { + return _then(_$_PositionMarker( + lastReadId: null == lastReadId + ? _value.lastReadId + : lastReadId // ignore: cast_nullable_to_non_nullable + as String, + version: null == version + ? _value.version + : version // ignore: cast_nullable_to_non_nullable + as int, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_PositionMarker implements _PositionMarker { + const _$_PositionMarker( + {required this.lastReadId, + required this.version, + required this.updatedAt}); + + factory _$_PositionMarker.fromJson(Map json) => + _$$_PositionMarkerFromJson(json); + + /// The ID of the most recently viewed entity. + @override + final String lastReadId; + + /// An incrementing counter, used for locking to prevent write conflicts. + @override + final int version; + + /// The timestamp of when the marker was set. + @override + final DateTime updatedAt; + + @override + String toString() { + return 'PositionMarker(lastReadId: $lastReadId, version: $version, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_PositionMarker && + (identical(other.lastReadId, lastReadId) || + other.lastReadId == lastReadId) && + (identical(other.version, version) || other.version == version) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, lastReadId, version, updatedAt); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_PositionMarkerCopyWith<_$_PositionMarker> get copyWith => + __$$_PositionMarkerCopyWithImpl<_$_PositionMarker>(this, _$identity); + + @override + Map toJson() { + return _$$_PositionMarkerToJson( + this, + ); + } +} + +abstract class _PositionMarker implements PositionMarker { + const factory _PositionMarker( + {required final String lastReadId, + required final int version, + required final DateTime updatedAt}) = _$_PositionMarker; + + factory _PositionMarker.fromJson(Map json) = + _$_PositionMarker.fromJson; + + @override + + /// The ID of the most recently viewed entity. + String get lastReadId; + @override + + /// An incrementing counter, used for locking to prevent write conflicts. + int get version; + @override + + /// The timestamp of when the marker was set. + DateTime get updatedAt; + @override + @JsonKey(ignore: true) + _$$_PositionMarkerCopyWith<_$_PositionMarker> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/src/service/entities/position_marker.g.dart b/lib/src/service/entities/position_marker.g.dart new file mode 100644 index 0000000..6efe81d --- /dev/null +++ b/lib/src/service/entities/position_marker.g.dart @@ -0,0 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: non_constant_identifier_names + +part of 'position_marker.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_PositionMarker _$$_PositionMarkerFromJson(Map json) => $checkedCreate( + r'_$_PositionMarker', + json, + ($checkedConvert) { + final val = _$_PositionMarker( + lastReadId: $checkedConvert('last_read_id', (v) => v as String), + version: $checkedConvert('version', (v) => v as int), + updatedAt: + $checkedConvert('updated_at', (v) => DateTime.parse(v as String)), + ); + return val; + }, + fieldKeyMap: const { + 'lastReadId': 'last_read_id', + 'updatedAt': 'updated_at' + }, + ); + +Map _$$_PositionMarkerToJson(_$_PositionMarker instance) => + { + 'last_read_id': instance.lastReadId, + 'version': instance.version, + 'updated_at': instance.updatedAt.toIso8601String(), + }; diff --git a/lib/src/service/entities/timeline_snapshot.dart b/lib/src/service/entities/timeline_snapshot.dart new file mode 100644 index 0000000..370844b --- /dev/null +++ b/lib/src/service/entities/timeline_snapshot.dart @@ -0,0 +1,29 @@ +// Copyright 2022 Kato Shinya. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided the conditions. + +// ignore_for_file: invalid_annotation_target + +// πŸ“¦ Package imports: +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'position_marker.dart'; + +part 'timeline_snapshot.freezed.dart'; +part 'timeline_snapshot.g.dart'; + +/// Represents the last read position within a user's timelines. +@freezed +class TimelineSnapshot with _$TimelineSnapshot { + @JsonSerializable(includeIfNull: false) + const factory TimelineSnapshot({ + /// Snapshot for notifications. + PositionMarker? notifications, + + /// Snapshot for home timeline. + PositionMarker? home, + }) = _TimelineSnapshot; + + factory TimelineSnapshot.fromJson(Map json) => + _$TimelineSnapshotFromJson(json); +} diff --git a/lib/src/service/entities/timeline_snapshot.freezed.dart b/lib/src/service/entities/timeline_snapshot.freezed.dart new file mode 100644 index 0000000..7334b7d --- /dev/null +++ b/lib/src/service/entities/timeline_snapshot.freezed.dart @@ -0,0 +1,213 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// 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 + +part of 'timeline_snapshot.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + '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#custom-getters-and-methods'); + +TimelineSnapshot _$TimelineSnapshotFromJson(Map json) { + return _TimelineSnapshot.fromJson(json); +} + +/// @nodoc +mixin _$TimelineSnapshot { + /// Snapshot for notifications. + PositionMarker? get notifications => throw _privateConstructorUsedError; + + /// Snapshot for home timeline. + PositionMarker? get home => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $TimelineSnapshotCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TimelineSnapshotCopyWith<$Res> { + factory $TimelineSnapshotCopyWith( + TimelineSnapshot value, $Res Function(TimelineSnapshot) then) = + _$TimelineSnapshotCopyWithImpl<$Res, TimelineSnapshot>; + @useResult + $Res call({PositionMarker? notifications, PositionMarker? home}); + + $PositionMarkerCopyWith<$Res>? get notifications; + $PositionMarkerCopyWith<$Res>? get home; +} + +/// @nodoc +class _$TimelineSnapshotCopyWithImpl<$Res, $Val extends TimelineSnapshot> + implements $TimelineSnapshotCopyWith<$Res> { + _$TimelineSnapshotCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? notifications = freezed, + Object? home = freezed, + }) { + return _then(_value.copyWith( + notifications: freezed == notifications + ? _value.notifications + : notifications // ignore: cast_nullable_to_non_nullable + as PositionMarker?, + home: freezed == home + ? _value.home + : home // ignore: cast_nullable_to_non_nullable + as PositionMarker?, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $PositionMarkerCopyWith<$Res>? get notifications { + if (_value.notifications == null) { + return null; + } + + return $PositionMarkerCopyWith<$Res>(_value.notifications!, (value) { + return _then(_value.copyWith(notifications: value) as $Val); + }); + } + + @override + @pragma('vm:prefer-inline') + $PositionMarkerCopyWith<$Res>? get home { + if (_value.home == null) { + return null; + } + + return $PositionMarkerCopyWith<$Res>(_value.home!, (value) { + return _then(_value.copyWith(home: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_TimelineSnapshotCopyWith<$Res> + implements $TimelineSnapshotCopyWith<$Res> { + factory _$$_TimelineSnapshotCopyWith( + _$_TimelineSnapshot value, $Res Function(_$_TimelineSnapshot) then) = + __$$_TimelineSnapshotCopyWithImpl<$Res>; + @override + @useResult + $Res call({PositionMarker? notifications, PositionMarker? home}); + + @override + $PositionMarkerCopyWith<$Res>? get notifications; + @override + $PositionMarkerCopyWith<$Res>? get home; +} + +/// @nodoc +class __$$_TimelineSnapshotCopyWithImpl<$Res> + extends _$TimelineSnapshotCopyWithImpl<$Res, _$_TimelineSnapshot> + implements _$$_TimelineSnapshotCopyWith<$Res> { + __$$_TimelineSnapshotCopyWithImpl( + _$_TimelineSnapshot _value, $Res Function(_$_TimelineSnapshot) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? notifications = freezed, + Object? home = freezed, + }) { + return _then(_$_TimelineSnapshot( + notifications: freezed == notifications + ? _value.notifications + : notifications // ignore: cast_nullable_to_non_nullable + as PositionMarker?, + home: freezed == home + ? _value.home + : home // ignore: cast_nullable_to_non_nullable + as PositionMarker?, + )); + } +} + +/// @nodoc + +@JsonSerializable(includeIfNull: false) +class _$_TimelineSnapshot implements _TimelineSnapshot { + const _$_TimelineSnapshot({this.notifications, this.home}); + + factory _$_TimelineSnapshot.fromJson(Map json) => + _$$_TimelineSnapshotFromJson(json); + + /// Snapshot for notifications. + @override + final PositionMarker? notifications; + + /// Snapshot for home timeline. + @override + final PositionMarker? home; + + @override + String toString() { + return 'TimelineSnapshot(notifications: $notifications, home: $home)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_TimelineSnapshot && + (identical(other.notifications, notifications) || + other.notifications == notifications) && + (identical(other.home, home) || other.home == home)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, notifications, home); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_TimelineSnapshotCopyWith<_$_TimelineSnapshot> get copyWith => + __$$_TimelineSnapshotCopyWithImpl<_$_TimelineSnapshot>(this, _$identity); + + @override + Map toJson() { + return _$$_TimelineSnapshotToJson( + this, + ); + } +} + +abstract class _TimelineSnapshot implements TimelineSnapshot { + const factory _TimelineSnapshot( + {final PositionMarker? notifications, + final PositionMarker? home}) = _$_TimelineSnapshot; + + factory _TimelineSnapshot.fromJson(Map json) = + _$_TimelineSnapshot.fromJson; + + @override + + /// Snapshot for notifications. + PositionMarker? get notifications; + @override + + /// Snapshot for home timeline. + PositionMarker? get home; + @override + @JsonKey(ignore: true) + _$$_TimelineSnapshotCopyWith<_$_TimelineSnapshot> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/src/service/entities/timeline_snapshot.g.dart b/lib/src/service/entities/timeline_snapshot.g.dart new file mode 100644 index 0000000..d1a074a --- /dev/null +++ b/lib/src/service/entities/timeline_snapshot.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: non_constant_identifier_names + +part of 'timeline_snapshot.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_TimelineSnapshot _$$_TimelineSnapshotFromJson(Map json) => $checkedCreate( + r'_$_TimelineSnapshot', + json, + ($checkedConvert) { + final val = _$_TimelineSnapshot( + notifications: $checkedConvert( + 'notifications', + (v) => v == null + ? null + : PositionMarker.fromJson( + Map.from(v as Map))), + home: $checkedConvert( + 'home', + (v) => v == null + ? null + : PositionMarker.fromJson( + Map.from(v as Map))), + ); + return val; + }, + ); + +Map _$$_TimelineSnapshotToJson(_$_TimelineSnapshot instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('notifications', instance.notifications?.toJson()); + writeNotNull('home', instance.home?.toJson()); + return val; +} diff --git a/lib/src/service/v1/timelines/timelines_v1_service.dart b/lib/src/service/v1/timelines/timelines_v1_service.dart index 3608c66..7853154 100644 --- a/lib/src/service/v1/timelines/timelines_v1_service.dart +++ b/lib/src/service/v1/timelines/timelines_v1_service.dart @@ -7,7 +7,9 @@ import '../../../core/client/client_context.dart'; import '../../../core/client/user_context.dart'; import '../../base_service.dart'; import '../../entities/conversation.dart'; +import '../../entities/position_marker.dart'; import '../../entities/status.dart'; +import '../../entities/timeline_snapshot.dart'; import '../../response/mastodon_response.dart'; abstract class TimelinesV1Service { @@ -258,6 +260,16 @@ abstract class TimelinesV1Service { Future> createMarkConversationAsRead({ required String conversationId, }); + + Future> lookupSnapshot(); + + Future> createStatusSnapshot({ + required String statusId, + }); + + Future> createNotificationSnapshot({ + required String notificationId, + }); } class _TimelinesV1Service extends BaseService implements TimelinesV1Service { @@ -403,4 +415,50 @@ class _TimelinesV1Service extends BaseService implements TimelinesV1Service { ), dataBuilder: Conversation.fromJson, ); + + @override + Future> lookupSnapshot() async => + super.transformSingleDataResponse( + await super.get( + UserContext.oauth2Only, + '/api/v1/markers?timelines[]=β€œhome”', + ), + dataBuilder: TimelineSnapshot.fromJson, + ); + + @override + Future> createStatusSnapshot({ + required String statusId, + }) async => + super.transformSingleDataResponse( + await super.post( + UserContext.oauth2Only, + '/api/v1/markers', + body: { + 'home': { + 'last_read_id': statusId, + } + }, + checkEntity: true, + ), + dataBuilder: PositionMarker.fromJson, + ); + + @override + Future> createNotificationSnapshot({ + required String notificationId, + }) async => + super.transformSingleDataResponse( + await super.post( + UserContext.oauth2Only, + '/api/v1/markers', + body: { + 'notifications': { + 'last_read_id': notificationId, + } + }, + checkEntity: true, + ), + dataBuilder: PositionMarker.fromJson, + ); } From 90ed93b259a92ede47fc0bc489a961388bd8cbcd Mon Sep 17 00:00:00 2001 From: myConsciousness Date: Sat, 31 Dec 2022 13:41:31 +0900 Subject: [PATCH 2/3] docs: fixed for the issue (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: myConsciousness ” --- lib/mastodon_api.dart | 3 +- ...apshot.dart => notification_snapshot.dart} | 20 +- .../notification_snapshot.freezed.dart | 176 +++++++++++++ .../entities/notification_snapshot.g.dart | 31 +++ lib/src/service/entities/status_snapshot.dart | 25 ++ .../entities/status_snapshot.freezed.dart | 173 ++++++++++++ .../service/entities/status_snapshot.g.dart | 29 ++ .../entities/timeline_snapshot.freezed.dart | 213 --------------- .../service/entities/timeline_snapshot.g.dart | 45 ---- .../v1/timelines/timelines_v1_service.dart | 42 ++- .../data/create_notification_snapshot.json | 7 + .../data/create_status_snapshot.json | 7 + .../data/lookup_notification_snapshot.json | 7 + .../data/lookup_status_snapshot.json | 7 + .../timelines/timelines_v1_service_test.dart | 248 ++++++++++++++++++ 15 files changed, 750 insertions(+), 283 deletions(-) rename lib/src/service/entities/{timeline_snapshot.dart => notification_snapshot.dart} (51%) create mode 100644 lib/src/service/entities/notification_snapshot.freezed.dart create mode 100644 lib/src/service/entities/notification_snapshot.g.dart create mode 100644 lib/src/service/entities/status_snapshot.dart create mode 100644 lib/src/service/entities/status_snapshot.freezed.dart create mode 100644 lib/src/service/entities/status_snapshot.g.dart delete mode 100644 lib/src/service/entities/timeline_snapshot.freezed.dart delete mode 100644 lib/src/service/entities/timeline_snapshot.g.dart create mode 100644 test/src/service/v1/timelines/data/create_notification_snapshot.json create mode 100644 test/src/service/v1/timelines/data/create_status_snapshot.json create mode 100644 test/src/service/v1/timelines/data/lookup_notification_snapshot.json create mode 100644 test/src/service/v1/timelines/data/lookup_status_snapshot.json diff --git a/lib/mastodon_api.dart b/lib/mastodon_api.dart index e913ae2..601f857 100644 --- a/lib/mastodon_api.dart +++ b/lib/mastodon_api.dart @@ -44,6 +44,7 @@ export 'package:mastodon_api/src/service/entities/instance_usage.dart'; export 'package:mastodon_api/src/service/entities/instance_usage_users.dart'; export 'package:mastodon_api/src/service/entities/media_attachment.dart'; export 'package:mastodon_api/src/service/entities/media_attachment_type.dart'; +export 'package:mastodon_api/src/service/entities/notification_snapshot.dart'; export 'package:mastodon_api/src/service/entities/poll.dart'; export 'package:mastodon_api/src/service/entities/poll_option.dart'; export 'package:mastodon_api/src/service/entities/position_marker.dart'; @@ -52,12 +53,12 @@ export 'package:mastodon_api/src/service/entities/preview_card_type.dart'; export 'package:mastodon_api/src/service/entities/rate_limit.dart'; export 'package:mastodon_api/src/service/entities/registered_application.dart'; export 'package:mastodon_api/src/service/entities/status.dart'; +export 'package:mastodon_api/src/service/entities/status_snapshot.dart'; export 'package:mastodon_api/src/service/entities/suggested_reason.dart'; export 'package:mastodon_api/src/service/entities/suggestion.dart'; export 'package:mastodon_api/src/service/entities/tag.dart'; export 'package:mastodon_api/src/service/entities/thumbnail.dart'; export 'package:mastodon_api/src/service/entities/thumbnail_version.dart'; -export 'package:mastodon_api/src/service/entities/timeline_snapshot.dart'; export 'package:mastodon_api/src/service/entities/token.dart'; export 'package:mastodon_api/src/service/entities/usage_statistics.dart'; export 'package:mastodon_api/src/service/mastodon_v1_service.dart'; diff --git a/lib/src/service/entities/timeline_snapshot.dart b/lib/src/service/entities/notification_snapshot.dart similarity index 51% rename from lib/src/service/entities/timeline_snapshot.dart rename to lib/src/service/entities/notification_snapshot.dart index 370844b..0e294d3 100644 --- a/lib/src/service/entities/timeline_snapshot.dart +++ b/lib/src/service/entities/notification_snapshot.dart @@ -9,21 +9,17 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'position_marker.dart'; -part 'timeline_snapshot.freezed.dart'; -part 'timeline_snapshot.g.dart'; +part 'notification_snapshot.freezed.dart'; +part 'notification_snapshot.g.dart'; /// Represents the last read position within a user's timelines. @freezed -class TimelineSnapshot with _$TimelineSnapshot { - @JsonSerializable(includeIfNull: false) - const factory TimelineSnapshot({ +class NotificationSnapshot with _$NotificationSnapshot { + const factory NotificationSnapshot({ /// Snapshot for notifications. - PositionMarker? notifications, + @JsonKey(name: 'notifications') required PositionMarker marker, + }) = _NotificationSnapshot; - /// Snapshot for home timeline. - PositionMarker? home, - }) = _TimelineSnapshot; - - factory TimelineSnapshot.fromJson(Map json) => - _$TimelineSnapshotFromJson(json); + factory NotificationSnapshot.fromJson(Map json) => + _$NotificationSnapshotFromJson(json); } diff --git a/lib/src/service/entities/notification_snapshot.freezed.dart b/lib/src/service/entities/notification_snapshot.freezed.dart new file mode 100644 index 0000000..7736c35 --- /dev/null +++ b/lib/src/service/entities/notification_snapshot.freezed.dart @@ -0,0 +1,176 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// 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 + +part of 'notification_snapshot.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + '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#custom-getters-and-methods'); + +NotificationSnapshot _$NotificationSnapshotFromJson(Map json) { + return _NotificationSnapshot.fromJson(json); +} + +/// @nodoc +mixin _$NotificationSnapshot { + /// Snapshot for notifications. + @JsonKey(name: 'notifications') + PositionMarker get marker => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $NotificationSnapshotCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $NotificationSnapshotCopyWith<$Res> { + factory $NotificationSnapshotCopyWith(NotificationSnapshot value, + $Res Function(NotificationSnapshot) then) = + _$NotificationSnapshotCopyWithImpl<$Res, NotificationSnapshot>; + @useResult + $Res call({@JsonKey(name: 'notifications') PositionMarker marker}); + + $PositionMarkerCopyWith<$Res> get marker; +} + +/// @nodoc +class _$NotificationSnapshotCopyWithImpl<$Res, + $Val extends NotificationSnapshot> + implements $NotificationSnapshotCopyWith<$Res> { + _$NotificationSnapshotCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? marker = null, + }) { + return _then(_value.copyWith( + marker: null == marker + ? _value.marker + : marker // ignore: cast_nullable_to_non_nullable + as PositionMarker, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $PositionMarkerCopyWith<$Res> get marker { + return $PositionMarkerCopyWith<$Res>(_value.marker, (value) { + return _then(_value.copyWith(marker: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_NotificationSnapshotCopyWith<$Res> + implements $NotificationSnapshotCopyWith<$Res> { + factory _$$_NotificationSnapshotCopyWith(_$_NotificationSnapshot value, + $Res Function(_$_NotificationSnapshot) then) = + __$$_NotificationSnapshotCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: 'notifications') PositionMarker marker}); + + @override + $PositionMarkerCopyWith<$Res> get marker; +} + +/// @nodoc +class __$$_NotificationSnapshotCopyWithImpl<$Res> + extends _$NotificationSnapshotCopyWithImpl<$Res, _$_NotificationSnapshot> + implements _$$_NotificationSnapshotCopyWith<$Res> { + __$$_NotificationSnapshotCopyWithImpl(_$_NotificationSnapshot _value, + $Res Function(_$_NotificationSnapshot) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? marker = null, + }) { + return _then(_$_NotificationSnapshot( + marker: null == marker + ? _value.marker + : marker // ignore: cast_nullable_to_non_nullable + as PositionMarker, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_NotificationSnapshot implements _NotificationSnapshot { + const _$_NotificationSnapshot( + {@JsonKey(name: 'notifications') required this.marker}); + + factory _$_NotificationSnapshot.fromJson(Map json) => + _$$_NotificationSnapshotFromJson(json); + + /// Snapshot for notifications. + @override + @JsonKey(name: 'notifications') + final PositionMarker marker; + + @override + String toString() { + return 'NotificationSnapshot(marker: $marker)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_NotificationSnapshot && + (identical(other.marker, marker) || other.marker == marker)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, marker); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_NotificationSnapshotCopyWith<_$_NotificationSnapshot> get copyWith => + __$$_NotificationSnapshotCopyWithImpl<_$_NotificationSnapshot>( + this, _$identity); + + @override + Map toJson() { + return _$$_NotificationSnapshotToJson( + this, + ); + } +} + +abstract class _NotificationSnapshot implements NotificationSnapshot { + const factory _NotificationSnapshot( + {@JsonKey(name: 'notifications') + required final PositionMarker marker}) = _$_NotificationSnapshot; + + factory _NotificationSnapshot.fromJson(Map json) = + _$_NotificationSnapshot.fromJson; + + @override + + /// Snapshot for notifications. + @JsonKey(name: 'notifications') + PositionMarker get marker; + @override + @JsonKey(ignore: true) + _$$_NotificationSnapshotCopyWith<_$_NotificationSnapshot> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/src/service/entities/notification_snapshot.g.dart b/lib/src/service/entities/notification_snapshot.g.dart new file mode 100644 index 0000000..e976db2 --- /dev/null +++ b/lib/src/service/entities/notification_snapshot.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: non_constant_identifier_names + +part of 'notification_snapshot.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_NotificationSnapshot _$$_NotificationSnapshotFromJson(Map json) => + $checkedCreate( + r'_$_NotificationSnapshot', + json, + ($checkedConvert) { + final val = _$_NotificationSnapshot( + marker: $checkedConvert( + 'notifications', + (v) => + PositionMarker.fromJson(Map.from(v as Map))), + ); + return val; + }, + fieldKeyMap: const {'marker': 'notifications'}, + ); + +Map _$$_NotificationSnapshotToJson( + _$_NotificationSnapshot instance) => + { + 'notifications': instance.marker.toJson(), + }; diff --git a/lib/src/service/entities/status_snapshot.dart b/lib/src/service/entities/status_snapshot.dart new file mode 100644 index 0000000..e9b236c --- /dev/null +++ b/lib/src/service/entities/status_snapshot.dart @@ -0,0 +1,25 @@ +// Copyright 2022 Kato Shinya. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided the conditions. + +// ignore_for_file: invalid_annotation_target + +// πŸ“¦ Package imports: +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'position_marker.dart'; + +part 'status_snapshot.freezed.dart'; +part 'status_snapshot.g.dart'; + +/// Represents the last read position within a user's timelines. +@freezed +class StatusSnapshot with _$StatusSnapshot { + const factory StatusSnapshot({ + /// Snapshot for home timeline. + @JsonKey(name: 'home') required PositionMarker marker, + }) = _StatusSnapshot; + + factory StatusSnapshot.fromJson(Map json) => + _$StatusSnapshotFromJson(json); +} diff --git a/lib/src/service/entities/status_snapshot.freezed.dart b/lib/src/service/entities/status_snapshot.freezed.dart new file mode 100644 index 0000000..e1893af --- /dev/null +++ b/lib/src/service/entities/status_snapshot.freezed.dart @@ -0,0 +1,173 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// 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 + +part of 'status_snapshot.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + '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#custom-getters-and-methods'); + +StatusSnapshot _$StatusSnapshotFromJson(Map json) { + return _StatusSnapshot.fromJson(json); +} + +/// @nodoc +mixin _$StatusSnapshot { + /// Snapshot for home timeline. + @JsonKey(name: 'home') + PositionMarker get marker => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $StatusSnapshotCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $StatusSnapshotCopyWith<$Res> { + factory $StatusSnapshotCopyWith( + StatusSnapshot value, $Res Function(StatusSnapshot) then) = + _$StatusSnapshotCopyWithImpl<$Res, StatusSnapshot>; + @useResult + $Res call({@JsonKey(name: 'home') PositionMarker marker}); + + $PositionMarkerCopyWith<$Res> get marker; +} + +/// @nodoc +class _$StatusSnapshotCopyWithImpl<$Res, $Val extends StatusSnapshot> + implements $StatusSnapshotCopyWith<$Res> { + _$StatusSnapshotCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? marker = null, + }) { + return _then(_value.copyWith( + marker: null == marker + ? _value.marker + : marker // ignore: cast_nullable_to_non_nullable + as PositionMarker, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $PositionMarkerCopyWith<$Res> get marker { + return $PositionMarkerCopyWith<$Res>(_value.marker, (value) { + return _then(_value.copyWith(marker: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_StatusSnapshotCopyWith<$Res> + implements $StatusSnapshotCopyWith<$Res> { + factory _$$_StatusSnapshotCopyWith( + _$_StatusSnapshot value, $Res Function(_$_StatusSnapshot) then) = + __$$_StatusSnapshotCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: 'home') PositionMarker marker}); + + @override + $PositionMarkerCopyWith<$Res> get marker; +} + +/// @nodoc +class __$$_StatusSnapshotCopyWithImpl<$Res> + extends _$StatusSnapshotCopyWithImpl<$Res, _$_StatusSnapshot> + implements _$$_StatusSnapshotCopyWith<$Res> { + __$$_StatusSnapshotCopyWithImpl( + _$_StatusSnapshot _value, $Res Function(_$_StatusSnapshot) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? marker = null, + }) { + return _then(_$_StatusSnapshot( + marker: null == marker + ? _value.marker + : marker // ignore: cast_nullable_to_non_nullable + as PositionMarker, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_StatusSnapshot implements _StatusSnapshot { + const _$_StatusSnapshot({@JsonKey(name: 'home') required this.marker}); + + factory _$_StatusSnapshot.fromJson(Map json) => + _$$_StatusSnapshotFromJson(json); + + /// Snapshot for home timeline. + @override + @JsonKey(name: 'home') + final PositionMarker marker; + + @override + String toString() { + return 'StatusSnapshot(marker: $marker)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_StatusSnapshot && + (identical(other.marker, marker) || other.marker == marker)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, marker); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_StatusSnapshotCopyWith<_$_StatusSnapshot> get copyWith => + __$$_StatusSnapshotCopyWithImpl<_$_StatusSnapshot>(this, _$identity); + + @override + Map toJson() { + return _$$_StatusSnapshotToJson( + this, + ); + } +} + +abstract class _StatusSnapshot implements StatusSnapshot { + const factory _StatusSnapshot( + {@JsonKey(name: 'home') required final PositionMarker marker}) = + _$_StatusSnapshot; + + factory _StatusSnapshot.fromJson(Map json) = + _$_StatusSnapshot.fromJson; + + @override + + /// Snapshot for home timeline. + @JsonKey(name: 'home') + PositionMarker get marker; + @override + @JsonKey(ignore: true) + _$$_StatusSnapshotCopyWith<_$_StatusSnapshot> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/src/service/entities/status_snapshot.g.dart b/lib/src/service/entities/status_snapshot.g.dart new file mode 100644 index 0000000..5759006 --- /dev/null +++ b/lib/src/service/entities/status_snapshot.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: non_constant_identifier_names + +part of 'status_snapshot.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_StatusSnapshot _$$_StatusSnapshotFromJson(Map json) => $checkedCreate( + r'_$_StatusSnapshot', + json, + ($checkedConvert) { + final val = _$_StatusSnapshot( + marker: $checkedConvert( + 'home', + (v) => + PositionMarker.fromJson(Map.from(v as Map))), + ); + return val; + }, + fieldKeyMap: const {'marker': 'home'}, + ); + +Map _$$_StatusSnapshotToJson(_$_StatusSnapshot instance) => + { + 'home': instance.marker.toJson(), + }; diff --git a/lib/src/service/entities/timeline_snapshot.freezed.dart b/lib/src/service/entities/timeline_snapshot.freezed.dart deleted file mode 100644 index 7334b7d..0000000 --- a/lib/src/service/entities/timeline_snapshot.freezed.dart +++ /dev/null @@ -1,213 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// 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 - -part of 'timeline_snapshot.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - '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#custom-getters-and-methods'); - -TimelineSnapshot _$TimelineSnapshotFromJson(Map json) { - return _TimelineSnapshot.fromJson(json); -} - -/// @nodoc -mixin _$TimelineSnapshot { - /// Snapshot for notifications. - PositionMarker? get notifications => throw _privateConstructorUsedError; - - /// Snapshot for home timeline. - PositionMarker? get home => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $TimelineSnapshotCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $TimelineSnapshotCopyWith<$Res> { - factory $TimelineSnapshotCopyWith( - TimelineSnapshot value, $Res Function(TimelineSnapshot) then) = - _$TimelineSnapshotCopyWithImpl<$Res, TimelineSnapshot>; - @useResult - $Res call({PositionMarker? notifications, PositionMarker? home}); - - $PositionMarkerCopyWith<$Res>? get notifications; - $PositionMarkerCopyWith<$Res>? get home; -} - -/// @nodoc -class _$TimelineSnapshotCopyWithImpl<$Res, $Val extends TimelineSnapshot> - implements $TimelineSnapshotCopyWith<$Res> { - _$TimelineSnapshotCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? notifications = freezed, - Object? home = freezed, - }) { - return _then(_value.copyWith( - notifications: freezed == notifications - ? _value.notifications - : notifications // ignore: cast_nullable_to_non_nullable - as PositionMarker?, - home: freezed == home - ? _value.home - : home // ignore: cast_nullable_to_non_nullable - as PositionMarker?, - ) as $Val); - } - - @override - @pragma('vm:prefer-inline') - $PositionMarkerCopyWith<$Res>? get notifications { - if (_value.notifications == null) { - return null; - } - - return $PositionMarkerCopyWith<$Res>(_value.notifications!, (value) { - return _then(_value.copyWith(notifications: value) as $Val); - }); - } - - @override - @pragma('vm:prefer-inline') - $PositionMarkerCopyWith<$Res>? get home { - if (_value.home == null) { - return null; - } - - return $PositionMarkerCopyWith<$Res>(_value.home!, (value) { - return _then(_value.copyWith(home: value) as $Val); - }); - } -} - -/// @nodoc -abstract class _$$_TimelineSnapshotCopyWith<$Res> - implements $TimelineSnapshotCopyWith<$Res> { - factory _$$_TimelineSnapshotCopyWith( - _$_TimelineSnapshot value, $Res Function(_$_TimelineSnapshot) then) = - __$$_TimelineSnapshotCopyWithImpl<$Res>; - @override - @useResult - $Res call({PositionMarker? notifications, PositionMarker? home}); - - @override - $PositionMarkerCopyWith<$Res>? get notifications; - @override - $PositionMarkerCopyWith<$Res>? get home; -} - -/// @nodoc -class __$$_TimelineSnapshotCopyWithImpl<$Res> - extends _$TimelineSnapshotCopyWithImpl<$Res, _$_TimelineSnapshot> - implements _$$_TimelineSnapshotCopyWith<$Res> { - __$$_TimelineSnapshotCopyWithImpl( - _$_TimelineSnapshot _value, $Res Function(_$_TimelineSnapshot) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? notifications = freezed, - Object? home = freezed, - }) { - return _then(_$_TimelineSnapshot( - notifications: freezed == notifications - ? _value.notifications - : notifications // ignore: cast_nullable_to_non_nullable - as PositionMarker?, - home: freezed == home - ? _value.home - : home // ignore: cast_nullable_to_non_nullable - as PositionMarker?, - )); - } -} - -/// @nodoc - -@JsonSerializable(includeIfNull: false) -class _$_TimelineSnapshot implements _TimelineSnapshot { - const _$_TimelineSnapshot({this.notifications, this.home}); - - factory _$_TimelineSnapshot.fromJson(Map json) => - _$$_TimelineSnapshotFromJson(json); - - /// Snapshot for notifications. - @override - final PositionMarker? notifications; - - /// Snapshot for home timeline. - @override - final PositionMarker? home; - - @override - String toString() { - return 'TimelineSnapshot(notifications: $notifications, home: $home)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_TimelineSnapshot && - (identical(other.notifications, notifications) || - other.notifications == notifications) && - (identical(other.home, home) || other.home == home)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash(runtimeType, notifications, home); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_TimelineSnapshotCopyWith<_$_TimelineSnapshot> get copyWith => - __$$_TimelineSnapshotCopyWithImpl<_$_TimelineSnapshot>(this, _$identity); - - @override - Map toJson() { - return _$$_TimelineSnapshotToJson( - this, - ); - } -} - -abstract class _TimelineSnapshot implements TimelineSnapshot { - const factory _TimelineSnapshot( - {final PositionMarker? notifications, - final PositionMarker? home}) = _$_TimelineSnapshot; - - factory _TimelineSnapshot.fromJson(Map json) = - _$_TimelineSnapshot.fromJson; - - @override - - /// Snapshot for notifications. - PositionMarker? get notifications; - @override - - /// Snapshot for home timeline. - PositionMarker? get home; - @override - @JsonKey(ignore: true) - _$$_TimelineSnapshotCopyWith<_$_TimelineSnapshot> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/src/service/entities/timeline_snapshot.g.dart b/lib/src/service/entities/timeline_snapshot.g.dart deleted file mode 100644 index d1a074a..0000000 --- a/lib/src/service/entities/timeline_snapshot.g.dart +++ /dev/null @@ -1,45 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: non_constant_identifier_names - -part of 'timeline_snapshot.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_$_TimelineSnapshot _$$_TimelineSnapshotFromJson(Map json) => $checkedCreate( - r'_$_TimelineSnapshot', - json, - ($checkedConvert) { - final val = _$_TimelineSnapshot( - notifications: $checkedConvert( - 'notifications', - (v) => v == null - ? null - : PositionMarker.fromJson( - Map.from(v as Map))), - home: $checkedConvert( - 'home', - (v) => v == null - ? null - : PositionMarker.fromJson( - Map.from(v as Map))), - ); - return val; - }, - ); - -Map _$$_TimelineSnapshotToJson(_$_TimelineSnapshot instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('notifications', instance.notifications?.toJson()); - writeNotNull('home', instance.home?.toJson()); - return val; -} diff --git a/lib/src/service/v1/timelines/timelines_v1_service.dart b/lib/src/service/v1/timelines/timelines_v1_service.dart index 7853154..bddcf28 100644 --- a/lib/src/service/v1/timelines/timelines_v1_service.dart +++ b/lib/src/service/v1/timelines/timelines_v1_service.dart @@ -7,9 +7,9 @@ import '../../../core/client/client_context.dart'; import '../../../core/client/user_context.dart'; import '../../base_service.dart'; import '../../entities/conversation.dart'; -import '../../entities/position_marker.dart'; +import '../../entities/notification_snapshot.dart'; import '../../entities/status.dart'; -import '../../entities/timeline_snapshot.dart'; +import '../../entities/status_snapshot.dart'; import '../../response/mastodon_response.dart'; abstract class TimelinesV1Service { @@ -261,13 +261,15 @@ abstract class TimelinesV1Service { required String conversationId, }); - Future> lookupSnapshot(); + Future> lookupStatusSnapshot(); - Future> createStatusSnapshot({ + Future> lookupNotificationSnapshot(); + + Future> createStatusSnapshot({ required String statusId, }); - Future> createNotificationSnapshot({ + Future> createNotificationSnapshot({ required String notificationId, }); } @@ -417,17 +419,33 @@ class _TimelinesV1Service extends BaseService implements TimelinesV1Service { ); @override - Future> lookupSnapshot() async => + Future> lookupStatusSnapshot() async => super.transformSingleDataResponse( await super.get( UserContext.oauth2Only, - '/api/v1/markers?timelines[]=β€œhome”', + '/api/v1/markers', + queryParameters: { + 'timeline[]': 'home', + }, ), - dataBuilder: TimelineSnapshot.fromJson, + dataBuilder: StatusSnapshot.fromJson, ); @override - Future> createStatusSnapshot({ + Future> + lookupNotificationSnapshot() async => super.transformSingleDataResponse( + await super.get( + UserContext.oauth2Only, + '/api/v1/markers', + queryParameters: { + 'timeline[]': 'notifications', + }, + ), + dataBuilder: NotificationSnapshot.fromJson, + ); + + @override + Future> createStatusSnapshot({ required String statusId, }) async => super.transformSingleDataResponse( @@ -441,11 +459,11 @@ class _TimelinesV1Service extends BaseService implements TimelinesV1Service { }, checkEntity: true, ), - dataBuilder: PositionMarker.fromJson, + dataBuilder: StatusSnapshot.fromJson, ); @override - Future> createNotificationSnapshot({ + Future> createNotificationSnapshot({ required String notificationId, }) async => super.transformSingleDataResponse( @@ -459,6 +477,6 @@ class _TimelinesV1Service extends BaseService implements TimelinesV1Service { }, checkEntity: true, ), - dataBuilder: PositionMarker.fromJson, + dataBuilder: NotificationSnapshot.fromJson, ); } diff --git a/test/src/service/v1/timelines/data/create_notification_snapshot.json b/test/src/service/v1/timelines/data/create_notification_snapshot.json new file mode 100644 index 0000000..f70e4db --- /dev/null +++ b/test/src/service/v1/timelines/data/create_notification_snapshot.json @@ -0,0 +1,7 @@ +{ + "notifications": { + "last_read_id": "35098814", + "version": 361, + "updated_at": "2019-11-26T22:37:25.239Z" + } +} diff --git a/test/src/service/v1/timelines/data/create_status_snapshot.json b/test/src/service/v1/timelines/data/create_status_snapshot.json new file mode 100644 index 0000000..db0b742 --- /dev/null +++ b/test/src/service/v1/timelines/data/create_status_snapshot.json @@ -0,0 +1,7 @@ +{ + "home": { + "last_read_id": "103206604258487607", + "version": 468, + "updated_at": "2019-11-26T22:37:25.235Z" + } +} diff --git a/test/src/service/v1/timelines/data/lookup_notification_snapshot.json b/test/src/service/v1/timelines/data/lookup_notification_snapshot.json new file mode 100644 index 0000000..f70e4db --- /dev/null +++ b/test/src/service/v1/timelines/data/lookup_notification_snapshot.json @@ -0,0 +1,7 @@ +{ + "notifications": { + "last_read_id": "35098814", + "version": 361, + "updated_at": "2019-11-26T22:37:25.239Z" + } +} diff --git a/test/src/service/v1/timelines/data/lookup_status_snapshot.json b/test/src/service/v1/timelines/data/lookup_status_snapshot.json new file mode 100644 index 0000000..db0b742 --- /dev/null +++ b/test/src/service/v1/timelines/data/lookup_status_snapshot.json @@ -0,0 +1,7 @@ +{ + "home": { + "last_read_id": "103206604258487607", + "version": 468, + "updated_at": "2019-11-26T22:37:25.235Z" + } +} diff --git a/test/src/service/v1/timelines/timelines_v1_service_test.dart b/test/src/service/v1/timelines/timelines_v1_service_test.dart index 26ee5ee..622aaaf 100644 --- a/test/src/service/v1/timelines/timelines_v1_service_test.dart +++ b/test/src/service/v1/timelines/timelines_v1_service_test.dart @@ -5,8 +5,10 @@ // 🌎 Project imports: import 'package:mastodon_api/src/core/client/user_context.dart'; import 'package:mastodon_api/src/service/entities/conversation.dart'; +import 'package:mastodon_api/src/service/entities/notification_snapshot.dart'; import 'package:mastodon_api/src/service/entities/rate_limit.dart'; import 'package:mastodon_api/src/service/entities/status.dart'; +import 'package:mastodon_api/src/service/entities/status_snapshot.dart'; import 'package:mastodon_api/src/service/response/mastodon_response.dart'; import 'package:mastodon_api/src/service/v1/timelines/timelines_v1_service.dart'; // πŸ“¦ Package imports: @@ -686,4 +688,250 @@ void main() { ); }); }); + + group('.lookupStatusSnapshot', () { + test('normal case', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_status_snapshot.json', + { + 'timeline[]': 'home', + }, + ), + ); + + final response = await timelinesService.lookupStatusSnapshot(); + + expect(response, isA()); + expect(response.rateLimit, isA()); + expect(response.data, isA()); + }); + + test('when unauthorized', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_status_snapshot.json', + { + 'timeline[]': 'home', + }, + statusCode: 401, + ), + ); + + expectUnauthorizedException( + () async => await timelinesService.lookupStatusSnapshot(), + ); + }); + + test('when rate limit exceeded', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_status_snapshot.json', + { + 'timeline[]': 'home', + }, + statusCode: 429, + ), + ); + + expectRateLimitExceededException( + () async => await timelinesService.lookupStatusSnapshot(), + ); + }); + }); + + group('.lookupNotificationSnapshot', () { + test('normal case', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_notification_snapshot.json', + { + 'timeline[]': 'notifications', + }, + ), + ); + + final response = await timelinesService.lookupNotificationSnapshot(); + + expect(response, isA()); + expect(response.rateLimit, isA()); + expect(response.data, isA()); + }); + + test('when unauthorized', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_notification_snapshot.json', + { + 'timeline[]': 'notifications', + }, + statusCode: 401, + ), + ); + + expectUnauthorizedException( + () async => await timelinesService.lookupNotificationSnapshot(), + ); + }); + + test('when rate limit exceeded', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildGetStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/lookup_notification_snapshot.json', + { + 'timeline[]': 'notifications', + }, + statusCode: 429, + ), + ); + + expectRateLimitExceededException( + () async => await timelinesService.lookupNotificationSnapshot(), + ); + }); + }); + + group('.createStatusSnapshot', () { + test('normal case', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_status_snapshot.json', + ), + ); + + final response = await timelinesService.createStatusSnapshot( + statusId: '1234', + ); + + expect(response, isA()); + expect(response.rateLimit, isA()); + expect(response.data, isA()); + }); + + test('when unauthorized', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_status_snapshot.json', + statusCode: 401, + ), + ); + + expectUnauthorizedException( + () async => await timelinesService.createStatusSnapshot( + statusId: '1234', + ), + ); + }); + + test('when rate limit exceeded', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_status_snapshot.json', + statusCode: 429, + ), + ); + + expectRateLimitExceededException( + () async => await timelinesService.createStatusSnapshot( + statusId: '1234', + ), + ); + }); + }); + + group('.createNotificationsSnapshot', () { + test('normal case', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_notification_snapshot.json', + ), + ); + + final response = await timelinesService.createNotificationSnapshot( + notificationId: '1234', + ); + + expect(response, isA()); + expect(response.rateLimit, isA()); + expect(response.data, isA()); + }); + + test('when unauthorized', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_notification_snapshot.json', + statusCode: 401, + ), + ); + + expectUnauthorizedException( + () async => await timelinesService.createNotificationSnapshot( + notificationId: '1234', + ), + ); + }); + + test('when rate limit exceeded', () async { + final timelinesService = TimelinesV1Service( + instance: 'test', + context: context.buildPostStub( + 'test', + UserContext.oauth2Only, + '/api/v1/markers', + 'test/src/service/v1/timelines/data/create_notification_snapshot.json', + statusCode: 429, + ), + ); + + expectRateLimitExceededException( + () async => await timelinesService.createNotificationSnapshot( + notificationId: '1234', + ), + ); + }); + }); } From 3f8da20ec955c21dc31b7996068daac218594041 Mon Sep 17 00:00:00 2001 From: myConsciousness Date: Sat, 31 Dec 2022 13:46:38 +0900 Subject: [PATCH 3/3] docs: fixed for the issue (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: myConsciousness ” --- .../v1/timelines/timelines_v1_service.dart | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/src/service/v1/timelines/timelines_v1_service.dart b/lib/src/service/v1/timelines/timelines_v1_service.dart index bddcf28..7bbcefd 100644 --- a/lib/src/service/v1/timelines/timelines_v1_service.dart +++ b/lib/src/service/v1/timelines/timelines_v1_service.dart @@ -261,14 +261,90 @@ abstract class TimelinesV1Service { required String conversationId, }); + /// Get saved timeline status position. + /// + /// ## Endpoint Url + /// + /// - GET /api/v1/markers HTTP/1.1 + /// + /// ## Authentication Methods + /// + /// - OAuth 2.0 + /// + /// ## Required Scopes + /// + /// - read:statuses + /// + /// ## Reference + /// + /// - https://docs.joinmastodon.org/methods/markers/#get Future> lookupStatusSnapshot(); + /// Get saved timeline notification position. + /// + /// ## Endpoint Url + /// + /// - GET /api/v1/markers HTTP/1.1 + /// + /// ## Authentication Methods + /// + /// - OAuth 2.0 + /// + /// ## Required Scopes + /// + /// - read:statuses + /// + /// ## Reference + /// + /// - https://docs.joinmastodon.org/methods/markers/#get Future> lookupNotificationSnapshot(); + /// Get saved timeline notification position. + /// + /// ## Parameters + /// + /// - [statusId]: ID of the last status read in the home timeline. + /// + /// ## Endpoint Url + /// + /// - POST /api/v1/markers HTTP/1.1 + /// + /// ## Authentication Methods + /// + /// - OAuth 2.0 + /// + /// ## Required Scopes + /// + /// - write:statuses + /// + /// ## Reference + /// + /// - https://docs.joinmastodon.org/methods/markers/#create Future> createStatusSnapshot({ required String statusId, }); + /// Get saved timeline notification position. + /// + /// ## Parameters + /// + /// - [notificationId]: ID of the last notification read. + /// + /// ## Endpoint Url + /// + /// - POST /api/v1/markers HTTP/1.1 + /// + /// ## Authentication Methods + /// + /// - OAuth 2.0 + /// + /// ## Required Scopes + /// + /// - write:statuses + /// + /// ## Reference + /// + /// - https://docs.joinmastodon.org/methods/markers/#create Future> createNotificationSnapshot({ required String notificationId, });