♻️ Refactored publisher subscription

This commit is contained in:
2025-12-23 00:23:25 +08:00
parent 33686b83e3
commit 0a179acb13
12 changed files with 563 additions and 414 deletions

View File

@@ -35,7 +35,7 @@ Future<List<SnPublisher>> publishersManaged(Ref ref) async {
}
@riverpod
Future<SnPublisher?> publisher(Ref ref, String? identifier) async {
Future<SnPublisher?> publisherNullable(Ref ref, String? identifier) async {
if (identifier == null) return null;
final client = ref.watch(apiClientProvider);
final resp = await client.get('/sphere/publishers/$identifier');
@@ -93,14 +93,10 @@ class EditPublisherScreen extends HookConsumerWidget {
submitting.value = true;
try {
final cloudFile =
await FileUploader.createCloudFile(
ref: ref,
fileData: UniversalFile(
data: result,
type: UniversalFileType.image,
),
).future;
final cloudFile = await FileUploader.createCloudFile(
ref: ref,
fileData: UniversalFile(data: result, type: UniversalFileType.image),
).future;
if (cloudFile == null) {
throw ArgumentError('Failed to upload the file...');
}
@@ -118,7 +114,7 @@ class EditPublisherScreen extends HookConsumerWidget {
}
}
final publisher = ref.watch(publisherProvider(name));
final publisher = ref.watch(publisherNullableProvider(name));
final formKey = useMemoized(GlobalKey<FormState>.new, const []);
final nameController = useTextEditingController(
@@ -155,8 +151,8 @@ class EditPublisherScreen extends HookConsumerWidget {
final resp = await client.request(
'/sphere${name == null
? currentRealm.value == null
? '/publishers/individual'
: '/publishers/organization/${currentRealm.value!.slug}'
? '/publishers/individual'
: '/publishers/organization/${currentRealm.value!.slug}'
: '/publishers/$name'}',
data: {
'name': nameController.text,
@@ -194,13 +190,12 @@ class EditPublisherScreen extends HookConsumerWidget {
GestureDetector(
child: Container(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
child:
background.value != null
? CloudImageWidget(
fileId: background.value!,
fit: BoxFit.cover,
)
: const SizedBox.shrink(),
child: background.value != null
? CloudImageWidget(
fileId: background.value!,
fit: BoxFit.cover,
)
: const SizedBox.shrink(),
),
onTap: () {
setPicture('background');
@@ -238,14 +233,14 @@ class EditPublisherScreen extends HookConsumerWidget {
prefixText: '@',
),
readOnly: name != null,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
TextFormField(
controller: nickController,
decoration: InputDecoration(labelText: 'nickname'.tr()),
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
TextFormField(
controller: bioController,
@@ -255,8 +250,8 @@ class EditPublisherScreen extends HookConsumerWidget {
),
minLines: 3,
maxLines: null,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
DropdownButtonFormField<SnRealm>(
value: currentRealm.value,
@@ -267,22 +262,20 @@ class EditPublisherScreen extends HookConsumerWidget {
child: Text('individual'.tr()),
),
...joinedRealms.maybeWhen(
data:
(realms) => realms.map(
(realm) => DropdownMenuItem(
value: realm,
child: Text(realm.name),
),
),
data: (realms) => realms.map(
(realm) => DropdownMenuItem(
value: realm,
child: Text(realm.name),
),
),
orElse: () => [],
),
],
onChanged:
joinedRealms.isLoading
? null
: (SnRealm? value) {
currentRealm.value = value;
},
onChanged: joinedRealms.isLoading
? null
: (SnRealm? value) {
currentRealm.value = value;
},
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -307,20 +300,18 @@ class EditPublisherScreen extends HookConsumerWidget {
currentRealm.value!.background?.id;
}
},
label:
Text(
currentRealm.value == null
? 'syncPublisher'
: 'syncPublisherRealm',
).tr(),
label: Text(
currentRealm.value == null
? 'syncPublisher'
: 'syncPublisherRealm',
).tr(),
icon: const Icon(Symbols.link),
),
TextButton.icon(
onPressed: submitting.value ? null : performAction,
label:
Text(
name == null ? 'create' : 'saveChanges',
).tr(),
label: Text(
name == null ? 'create' : 'saveChanges',
).tr(),
icon: const Icon(Symbols.save),
),
],

View File

@@ -50,10 +50,10 @@ final class PublishersManagedProvider
String _$publishersManagedHash() => r'ea83759fed9bd5119738b4d09f12b4476959e0a3';
@ProviderFor(publisher)
const publisherProvider = PublisherFamily._();
@ProviderFor(publisherNullable)
const publisherNullableProvider = PublisherNullableFamily._();
final class PublisherProvider
final class PublisherNullableProvider
extends
$FunctionalProvider<
AsyncValue<SnPublisher?>,
@@ -61,23 +61,23 @@ final class PublisherProvider
FutureOr<SnPublisher?>
>
with $FutureModifier<SnPublisher?>, $FutureProvider<SnPublisher?> {
const PublisherProvider._({
required PublisherFamily super.from,
const PublisherNullableProvider._({
required PublisherNullableFamily super.from,
required String? super.argument,
}) : super(
retry: null,
name: r'publisherProvider',
name: r'publisherNullableProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$publisherHash();
String debugGetCreateSourceHash() => _$publisherNullableHash();
@override
String toString() {
return r'publisherProvider'
return r'publisherNullableProvider'
''
'($argument)';
}
@@ -91,12 +91,12 @@ final class PublisherProvider
@override
FutureOr<SnPublisher?> create(Ref ref) {
final argument = this.argument as String?;
return publisher(ref, argument);
return publisherNullable(ref, argument);
}
@override
bool operator ==(Object other) {
return other is PublisherProvider && other.argument == argument;
return other is PublisherNullableProvider && other.argument == argument;
}
@override
@@ -105,22 +105,22 @@ final class PublisherProvider
}
}
String _$publisherHash() => r'18fb5c6b3d79dd8af4fbee108dec1a0e8a034038';
String _$publisherNullableHash() => r'49b28083a2f351c5e5cde0b1a97f6c7503969041';
final class PublisherFamily extends $Family
final class PublisherNullableFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<SnPublisher?>, String?> {
const PublisherFamily._()
const PublisherNullableFamily._()
: super(
retry: null,
name: r'publisherProvider',
name: r'publisherNullableProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
PublisherProvider call(String? identifier) =>
PublisherProvider._(argument: identifier, from: this);
PublisherNullableProvider call(String? identifier) =>
PublisherNullableProvider._(argument: identifier, from: this);
@override
String toString() => r'publisherProvider';
String toString() => r'publisherNullableProvider';
}

View File

@@ -33,7 +33,7 @@ part 'publisher_profile.g.dart';
class _PublisherBasisWidget extends StatelessWidget {
final SnPublisher data;
final AsyncValue<SnSubscriptionStatus> subStatus;
final AsyncValue<SnPublisherSubscription?> subStatus;
final ValueNotifier<bool> subscribing;
final VoidCallback subscribe;
final VoidCallback unsubscribe;
@@ -208,16 +208,16 @@ class _PublisherBasisWidget extends StatelessWidget {
data: (status) => FilledButton.icon(
onPressed: subscribing.value
? null
: (status.isSubscribed
: (status != null
? unsubscribe
: subscribe),
icon: Icon(
status.isSubscribed
status != null
? Symbols.remove_circle
: Symbols.add_circle,
),
label: Text(
status.isSubscribed
status != null
? 'unsubscribe'
: 'subscribe',
).tr(),
@@ -366,13 +366,16 @@ Future<List<SnAccountBadge>> publisherBadges(Ref ref, String pubName) async {
}
@riverpod
Future<SnSubscriptionStatus> publisherSubscriptionStatus(
Future<SnPublisherSubscription?> publisherSubscriptionStatus(
Ref ref,
String pubName,
) async {
final apiClient = ref.watch(apiClientProvider);
final resp = await apiClient.get("/sphere/publishers/$pubName/subscription");
return SnSubscriptionStatus.fromJson(resp.data);
if (resp.statusCode == 200) {
return SnPublisherSubscription.fromJson(resp.data);
}
return null;
}
@riverpod

View File

@@ -168,13 +168,13 @@ const publisherSubscriptionStatusProvider =
final class PublisherSubscriptionStatusProvider
extends
$FunctionalProvider<
AsyncValue<SnSubscriptionStatus>,
SnSubscriptionStatus,
FutureOr<SnSubscriptionStatus>
AsyncValue<SnPublisherSubscription?>,
SnPublisherSubscription?,
FutureOr<SnPublisherSubscription?>
>
with
$FutureModifier<SnSubscriptionStatus>,
$FutureProvider<SnSubscriptionStatus> {
$FutureModifier<SnPublisherSubscription?>,
$FutureProvider<SnPublisherSubscription?> {
const PublisherSubscriptionStatusProvider._({
required PublisherSubscriptionStatusFamily super.from,
required String super.argument,
@@ -198,12 +198,12 @@ final class PublisherSubscriptionStatusProvider
@$internal
@override
$FutureProviderElement<SnSubscriptionStatus> $createElement(
$FutureProviderElement<SnPublisherSubscription?> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<SnSubscriptionStatus> create(Ref ref) {
FutureOr<SnPublisherSubscription?> create(Ref ref) {
final argument = this.argument as String;
return publisherSubscriptionStatus(ref, argument);
}
@@ -221,10 +221,10 @@ final class PublisherSubscriptionStatusProvider
}
String _$publisherSubscriptionStatusHash() =>
r'634262ce519e1c8288267df11e08e1d4acaa4a44';
r'accf6a0cdf98f8b0474d94ac575e8b20448adc79';
final class PublisherSubscriptionStatusFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<SnSubscriptionStatus>, String> {
with $FunctionalFamilyOverride<FutureOr<SnPublisherSubscription?>, String> {
const PublisherSubscriptionStatusFamily._()
: super(
retry: null,