✨ Feature flags
This commit is contained in:
parent
fd979c3a35
commit
666a2dfbf5
@ -670,5 +670,10 @@
|
|||||||
"uriInvalid": "The URI is invalid.",
|
"uriInvalid": "The URI is invalid.",
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
"addScope": "Add Scope",
|
"addScope": "Add Scope",
|
||||||
"scope": "Scope"
|
"scope": "Scope",
|
||||||
|
"publisherFeatures": "Features",
|
||||||
|
"publisherFeatureDevelop": "Developer Program",
|
||||||
|
"publisherFeatureDevelopDescription": "Unlock development abilities for your publisher, including custom apps, API keys, and more.",
|
||||||
|
"publisherFeatureDevelopHint": "Currently, this feature is under active development, you need send a request to unlock this feature.",
|
||||||
|
"learnMore": "Learn More"
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import 'package:island/models/publisher.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/creators/publishers.dart';
|
import 'package:island/screens/creators/publishers.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/services/text.dart';
|
||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@ -46,6 +47,14 @@ Future<SnPublisherMember?> publisherIdentity(Ref ref, String uname) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<Map<String, bool>> publisherFeatures(Ref ref, String? uname) async {
|
||||||
|
if (uname == null) return {};
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final response = await apiClient.get('/publishers/$uname/features');
|
||||||
|
return Map<String, bool>.from(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnPublisherMember>> publisherInvites(Ref ref) async {
|
Future<List<SnPublisherMember>> publisherInvites(Ref ref) async {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
@ -184,6 +193,10 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
publisherStatsProvider(currentPublisher.value?.name),
|
publisherStatsProvider(currentPublisher.value?.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final publisherFeatures = ref.watch(
|
||||||
|
publisherFeaturesProvider(currentPublisher.value?.name),
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
noBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -374,6 +387,52 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ExpansionTile(
|
||||||
|
title: Text('publisherFeatures').tr(),
|
||||||
|
leading: const Icon(Symbols.flag),
|
||||||
|
tilePadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
minTileHeight: 48,
|
||||||
|
children: [
|
||||||
|
...publisherFeatures.when(
|
||||||
|
data: (data) {
|
||||||
|
return data.entries.map((entry) {
|
||||||
|
final keyPrefix =
|
||||||
|
'publisherFeature${entry.key.capitalizeEachWord()}';
|
||||||
|
return ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
leading: Icon(
|
||||||
|
Symbols.circle,
|
||||||
|
color:
|
||||||
|
entry.value
|
||||||
|
? Colors.green
|
||||||
|
: Colors.red,
|
||||||
|
fill: 1,
|
||||||
|
size: 16,
|
||||||
|
).padding(left: 2, top: 4),
|
||||||
|
title: Text(keyPrefix).tr(),
|
||||||
|
subtitle: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('${keyPrefix}Description').tr(),
|
||||||
|
if (!entry.value)
|
||||||
|
Text(
|
||||||
|
'${keyPrefix}Hint',
|
||||||
|
).tr().bold(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
isThreeLine: true,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
error: (_, _) => [],
|
||||||
|
loading: () => [],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
Divider(height: 1).padding(vertical: 8),
|
Divider(height: 1).padding(vertical: 8),
|
||||||
ListTile(
|
ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
|
@ -271,6 +271,128 @@ class _PublisherIdentityProviderElement
|
|||||||
String get uname => (origin as PublisherIdentityProvider).uname;
|
String get uname => (origin as PublisherIdentityProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$publisherFeaturesHash() => r'34db65d9a4b6b0c6961733ae79e67f25d5d111d3';
|
||||||
|
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
@ProviderFor(publisherFeatures)
|
||||||
|
const publisherFeaturesProvider = PublisherFeaturesFamily();
|
||||||
|
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
class PublisherFeaturesFamily extends Family<AsyncValue<Map<String, bool>>> {
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
const PublisherFeaturesFamily();
|
||||||
|
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
PublisherFeaturesProvider call(String? uname) {
|
||||||
|
return PublisherFeaturesProvider(uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PublisherFeaturesProvider getProviderOverride(
|
||||||
|
covariant PublisherFeaturesProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'publisherFeaturesProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
class PublisherFeaturesProvider
|
||||||
|
extends AutoDisposeFutureProvider<Map<String, bool>> {
|
||||||
|
/// See also [publisherFeatures].
|
||||||
|
PublisherFeaturesProvider(String? uname)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => publisherFeatures(ref as PublisherFeaturesRef, uname),
|
||||||
|
from: publisherFeaturesProvider,
|
||||||
|
name: r'publisherFeaturesProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$publisherFeaturesHash,
|
||||||
|
dependencies: PublisherFeaturesFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PublisherFeaturesFamily._allTransitiveDependencies,
|
||||||
|
uname: uname,
|
||||||
|
);
|
||||||
|
|
||||||
|
PublisherFeaturesProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.uname,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String? uname;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<Map<String, bool>> Function(PublisherFeaturesRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PublisherFeaturesProvider._internal(
|
||||||
|
(ref) => create(ref as PublisherFeaturesRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
uname: uname,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<Map<String, bool>> createElement() {
|
||||||
|
return _PublisherFeaturesProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PublisherFeaturesProvider && other.uname == uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, uname.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PublisherFeaturesRef on AutoDisposeFutureProviderRef<Map<String, bool>> {
|
||||||
|
/// The parameter `uname` of this provider.
|
||||||
|
String? get uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PublisherFeaturesProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<Map<String, bool>>
|
||||||
|
with PublisherFeaturesRef {
|
||||||
|
_PublisherFeaturesProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get uname => (origin as PublisherFeaturesProvider).uname;
|
||||||
|
}
|
||||||
|
|
||||||
String _$publisherInvitesHash() => r'488cd443407895ce11f4edff07cb6ea58f2aa018';
|
String _$publisherInvitesHash() => r'488cd443407895ce11f4edff07cb6ea58f2aa018';
|
||||||
|
|
||||||
/// See also [publisherInvites].
|
/// See also [publisherInvites].
|
||||||
|
Loading…
x
Reference in New Issue
Block a user