Subscription

This commit is contained in:
LittleSheep 2024-12-01 23:07:48 +08:00
parent cf1c4403c1
commit 177ff513ee
4 changed files with 380 additions and 6 deletions

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
@ -51,6 +53,63 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> {
}
}
bool _isSubscribing = false;
SnSubscription? _subscription;
Future<void> _fetchSubscription() async {
try {
setState(() => _isSubscribing = true);
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get(
'/cgi/co/subscriptions/users/${_publisher!.id}',
);
if (!mounted) return;
_subscription = SnSubscription.fromJson(resp.data);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isSubscribing = false);
}
}
Future<void> _toggleSubscription() async {
if (_subscription == null) {
try {
setState(() => _isSubscribing = true);
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.post(
'/cgi/co/subscriptions/users/${_publisher!.id}',
);
if (!mounted) return;
_subscription = SnSubscription.fromJson(resp.data);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isSubscribing = false);
}
} else {
try {
setState(() => _isSubscribing = true);
final sn = context.read<SnNetworkProvider>();
await sn.client.delete(
'/cgi/co/subscriptions/users/${_publisher!.id}',
);
if (!mounted) return;
_subscription = null;
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isSubscribing = false);
}
}
}
double _appBarBlur = 0.0;
late final _appBarWidth = MediaQuery.of(context).size.width;
@ -95,6 +154,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> {
super.initState();
_fetchPublisher().then((_) {
_fetchPosts();
_fetchSubscription();
});
_scrollController.addListener(_updateAppBarBlur);
}
@ -233,12 +293,28 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> {
],
),
),
ElevatedButton(
style: ButtonStyle(
elevation: WidgetStatePropertyAll(0)),
onPressed: () {},
child: Text('subscribe').tr(),
),
if (_subscription == null)
ElevatedButton.icon(
style: ButtonStyle(
elevation: WidgetStatePropertyAll(0),
),
onPressed: _isSubscribing
? null
: _toggleSubscription,
label: Text('subscribe').tr(),
icon: const Icon(Symbols.add),
)
else
OutlinedButton.icon(
style: ButtonStyle(
elevation: WidgetStatePropertyAll(0),
),
onPressed: _isSubscribing
? null
: _toggleSubscription,
label: Text('unsubscribe').tr(),
icon: const Icon(Symbols.remove),
),
],
).padding(right: 8),
const Gap(12),

View File

@ -125,3 +125,18 @@ class SnPublisher with _$SnPublisher {
factory SnPublisher.fromJson(Map<String, Object?> json) =>
_$SnPublisherFromJson(json);
}
@freezed
class SnSubscription with _$SnSubscription {
const factory SnSubscription({
required int id,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
required int followerId,
required int accountId,
}) = _SnSubscription;
factory SnSubscription.fromJson(Map<String, Object?> json) =>
_$SnSubscriptionFromJson(json);
}

View File

@ -2326,3 +2326,263 @@ abstract class _SnPublisher implements SnPublisher {
_$$SnPublisherImplCopyWith<_$SnPublisherImpl> get copyWith =>
throw _privateConstructorUsedError;
}
SnSubscription _$SnSubscriptionFromJson(Map<String, dynamic> json) {
return _SnSubscription.fromJson(json);
}
/// @nodoc
mixin _$SnSubscription {
int get id => throw _privateConstructorUsedError;
DateTime get createdAt => throw _privateConstructorUsedError;
DateTime get updatedAt => throw _privateConstructorUsedError;
DateTime? get deletedAt => throw _privateConstructorUsedError;
int get followerId => throw _privateConstructorUsedError;
int get accountId => throw _privateConstructorUsedError;
/// Serializes this SnSubscription to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of SnSubscription
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$SnSubscriptionCopyWith<SnSubscription> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SnSubscriptionCopyWith<$Res> {
factory $SnSubscriptionCopyWith(
SnSubscription value, $Res Function(SnSubscription) then) =
_$SnSubscriptionCopyWithImpl<$Res, SnSubscription>;
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
int followerId,
int accountId});
}
/// @nodoc
class _$SnSubscriptionCopyWithImpl<$Res, $Val extends SnSubscription>
implements $SnSubscriptionCopyWith<$Res> {
_$SnSubscriptionCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of SnSubscription
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? followerId = null,
Object? accountId = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
followerId: null == followerId
? _value.followerId
: followerId // ignore: cast_nullable_to_non_nullable
as int,
accountId: null == accountId
? _value.accountId
: accountId // ignore: cast_nullable_to_non_nullable
as int,
) as $Val);
}
}
/// @nodoc
abstract class _$$SnSubscriptionImplCopyWith<$Res>
implements $SnSubscriptionCopyWith<$Res> {
factory _$$SnSubscriptionImplCopyWith(_$SnSubscriptionImpl value,
$Res Function(_$SnSubscriptionImpl) then) =
__$$SnSubscriptionImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
int followerId,
int accountId});
}
/// @nodoc
class __$$SnSubscriptionImplCopyWithImpl<$Res>
extends _$SnSubscriptionCopyWithImpl<$Res, _$SnSubscriptionImpl>
implements _$$SnSubscriptionImplCopyWith<$Res> {
__$$SnSubscriptionImplCopyWithImpl(
_$SnSubscriptionImpl _value, $Res Function(_$SnSubscriptionImpl) _then)
: super(_value, _then);
/// Create a copy of SnSubscription
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? followerId = null,
Object? accountId = null,
}) {
return _then(_$SnSubscriptionImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
followerId: null == followerId
? _value.followerId
: followerId // ignore: cast_nullable_to_non_nullable
as int,
accountId: null == accountId
? _value.accountId
: accountId // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
@JsonSerializable()
class _$SnSubscriptionImpl implements _SnSubscription {
const _$SnSubscriptionImpl(
{required this.id,
required this.createdAt,
required this.updatedAt,
required this.deletedAt,
required this.followerId,
required this.accountId});
factory _$SnSubscriptionImpl.fromJson(Map<String, dynamic> json) =>
_$$SnSubscriptionImplFromJson(json);
@override
final int id;
@override
final DateTime createdAt;
@override
final DateTime updatedAt;
@override
final DateTime? deletedAt;
@override
final int followerId;
@override
final int accountId;
@override
String toString() {
return 'SnSubscription(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, followerId: $followerId, accountId: $accountId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SnSubscriptionImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt) &&
(identical(other.deletedAt, deletedAt) ||
other.deletedAt == deletedAt) &&
(identical(other.followerId, followerId) ||
other.followerId == followerId) &&
(identical(other.accountId, accountId) ||
other.accountId == accountId));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType, id, createdAt, updatedAt, deletedAt, followerId, accountId);
/// Create a copy of SnSubscription
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$SnSubscriptionImplCopyWith<_$SnSubscriptionImpl> get copyWith =>
__$$SnSubscriptionImplCopyWithImpl<_$SnSubscriptionImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$SnSubscriptionImplToJson(
this,
);
}
}
abstract class _SnSubscription implements SnSubscription {
const factory _SnSubscription(
{required final int id,
required final DateTime createdAt,
required final DateTime updatedAt,
required final DateTime? deletedAt,
required final int followerId,
required final int accountId}) = _$SnSubscriptionImpl;
factory _SnSubscription.fromJson(Map<String, dynamic> json) =
_$SnSubscriptionImpl.fromJson;
@override
int get id;
@override
DateTime get createdAt;
@override
DateTime get updatedAt;
@override
DateTime? get deletedAt;
@override
int get followerId;
@override
int get accountId;
/// Create a copy of SnSubscription
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$SnSubscriptionImplCopyWith<_$SnSubscriptionImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -218,3 +218,26 @@ Map<String, dynamic> _$$SnPublisherImplToJson(_$SnPublisherImpl instance) =>
'realm_id': instance.realmId,
'account_id': instance.accountId,
};
_$SnSubscriptionImpl _$$SnSubscriptionImplFromJson(Map<String, dynamic> json) =>
_$SnSubscriptionImpl(
id: (json['id'] as num).toInt(),
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
deletedAt: json['deleted_at'] == null
? null
: DateTime.parse(json['deleted_at'] as String),
followerId: (json['follower_id'] as num).toInt(),
accountId: (json['account_id'] as num).toInt(),
);
Map<String, dynamic> _$$SnSubscriptionImplToJson(
_$SnSubscriptionImpl instance) =>
<String, dynamic>{
'id': instance.id,
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
'follower_id': instance.followerId,
'account_id': instance.accountId,
};