diff --git a/packages/app_center/lib/games/games_page.dart b/packages/app_center/lib/games/games_page.dart index 70c25d59e..85ffa590d 100644 --- a/packages/app_center/lib/games/games_page.dart +++ b/packages/app_center/lib/games/games_page.dart @@ -39,8 +39,16 @@ class GamesPage extends ConsumerWidget { const SizedBox(height: kPagePadding), ], ), - const CategorySnapList( - category: SnapCategoryEnum.games, + const RatedCategorySnapList( + categories: [ + SnapCategoryEnum.games, + SnapCategoryEnum.kdeGames, + SnapCategoryEnum.gnomeGames, + SnapCategoryEnum.gameLaunchers, + SnapCategoryEnum.gameEmulators, + SnapCategoryEnum.gameContentCreation, + SnapCategoryEnum.gameDev, + ], ), SliverList.list( children: [ diff --git a/packages/app_center/lib/games/games_page_featured.dart b/packages/app_center/lib/games/games_page_featured.dart index a6d0a5442..f6491d565 100644 --- a/packages/app_center/lib/games/games_page_featured.dart +++ b/packages/app_center/lib/games/games_page_featured.dart @@ -22,7 +22,7 @@ class FeaturedCarousel extends ConsumerStatefulWidget { class _FeaturedCarouselState extends ConsumerState { late YaruCarouselController controller; - late Iterable snaps; + Iterable snaps = []; @override Widget build(BuildContext context) { diff --git a/packages/app_center/lib/ratings/rated_category_model.dart b/packages/app_center/lib/ratings/rated_category_model.dart new file mode 100644 index 000000000..670b8ff12 --- /dev/null +++ b/packages/app_center/lib/ratings/rated_category_model.dart @@ -0,0 +1,35 @@ +import 'package:app_center/ratings/ratings_service.dart'; +import 'package:app_center/snapd/snapd.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:snapd/snapd.dart'; +import 'package:ubuntu_service/ubuntu_service.dart'; + +part 'rated_category_model.g.dart'; + +@riverpod +class RatedCategoryModel extends _$RatedCategoryModel { + late final _ratings = getService(); + late final _snapd = getService(); + + @override + Future> build( + List categories, + int numberOfSnaps, + ) async { + final snaps = []; + + for (final category in categories) { + final chart = await _ratings.getChart(category); + var i = 0; + while (snaps.length < numberOfSnaps && i < chart.length) { + final snap = await _snapd.findById(chart[i].rating.snapId); + if (snap != null && snap.screenshotUrls.isNotEmpty) { + snaps.add(snap); + } + i++; + } + } + + return snaps; + } +} diff --git a/packages/app_center/lib/ratings/rated_category_model.g.dart b/packages/app_center/lib/ratings/rated_category_model.g.dart new file mode 100644 index 000000000..dfcd49560 --- /dev/null +++ b/packages/app_center/lib/ratings/rated_category_model.g.dart @@ -0,0 +1,199 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'rated_category_model.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$ratedCategoryModelHash() => + r'ff7cf67846bd5a4878b79315160604ee9b62df5b'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +abstract class _$RatedCategoryModel + extends BuildlessAutoDisposeAsyncNotifier> { + late final List categories; + late final int numberOfSnaps; + + FutureOr> build( + List categories, + int numberOfSnaps, + ); +} + +/// See also [RatedCategoryModel]. +@ProviderFor(RatedCategoryModel) +const ratedCategoryModelProvider = RatedCategoryModelFamily(); + +/// See also [RatedCategoryModel]. +class RatedCategoryModelFamily extends Family>> { + /// See also [RatedCategoryModel]. + const RatedCategoryModelFamily(); + + /// See also [RatedCategoryModel]. + RatedCategoryModelProvider call( + List categories, + int numberOfSnaps, + ) { + return RatedCategoryModelProvider( + categories, + numberOfSnaps, + ); + } + + @override + RatedCategoryModelProvider getProviderOverride( + covariant RatedCategoryModelProvider provider, + ) { + return call( + provider.categories, + provider.numberOfSnaps, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'ratedCategoryModelProvider'; +} + +/// See also [RatedCategoryModel]. +class RatedCategoryModelProvider extends AutoDisposeAsyncNotifierProviderImpl< + RatedCategoryModel, List> { + /// See also [RatedCategoryModel]. + RatedCategoryModelProvider( + List categories, + int numberOfSnaps, + ) : this._internal( + () => RatedCategoryModel() + ..categories = categories + ..numberOfSnaps = numberOfSnaps, + from: ratedCategoryModelProvider, + name: r'ratedCategoryModelProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$ratedCategoryModelHash, + dependencies: RatedCategoryModelFamily._dependencies, + allTransitiveDependencies: + RatedCategoryModelFamily._allTransitiveDependencies, + categories: categories, + numberOfSnaps: numberOfSnaps, + ); + + RatedCategoryModelProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.categories, + required this.numberOfSnaps, + }) : super.internal(); + + final List categories; + final int numberOfSnaps; + + @override + FutureOr> runNotifierBuild( + covariant RatedCategoryModel notifier, + ) { + return notifier.build( + categories, + numberOfSnaps, + ); + } + + @override + Override overrideWith(RatedCategoryModel Function() create) { + return ProviderOverride( + origin: this, + override: RatedCategoryModelProvider._internal( + () => create() + ..categories = categories + ..numberOfSnaps = numberOfSnaps, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + categories: categories, + numberOfSnaps: numberOfSnaps, + ), + ); + } + + @override + AutoDisposeAsyncNotifierProviderElement> + createElement() { + return _RatedCategoryModelProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is RatedCategoryModelProvider && + other.categories == categories && + other.numberOfSnaps == numberOfSnaps; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, categories.hashCode); + hash = _SystemHash.combine(hash, numberOfSnaps.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin RatedCategoryModelRef on AutoDisposeAsyncNotifierProviderRef> { + /// The parameter `categories` of this provider. + List get categories; + + /// The parameter `numberOfSnaps` of this provider. + int get numberOfSnaps; +} + +class _RatedCategoryModelProviderElement + extends AutoDisposeAsyncNotifierProviderElement> with RatedCategoryModelRef { + _RatedCategoryModelProviderElement(super.provider); + + @override + List get categories => + (origin as RatedCategoryModelProvider).categories; + @override + int get numberOfSnaps => (origin as RatedCategoryModelProvider).numberOfSnaps; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/packages/app_center/lib/ratings/ratings_service.dart b/packages/app_center/lib/ratings/ratings_service.dart index 501249f66..d47d5057d 100644 --- a/packages/app_center/lib/ratings/ratings_service.dart +++ b/packages/app_center/lib/ratings/ratings_service.dart @@ -1,8 +1,10 @@ import 'dart:convert'; import 'dart:io'; +import 'package:app_center/snapd/snap_category_enum.dart'; import 'package:app_center_ratings_client/app_center_ratings_client.dart'; import 'package:crypto/crypto.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:glib/glib.dart'; import 'package:jwt_decode/jwt_decode.dart'; @@ -32,6 +34,11 @@ class RatingsService { return client.getRating(snapId, _jwt!); } + Future> getChart(SnapCategoryEnum category) async { + await _ensureValidToken(); + return client.getChart(Timeframe.unspecified, _jwt!, category.index); + } + Future vote(Vote vote) async { await _ensureValidToken(); await client.vote(vote.snapId, vote.snapRevision, vote.voteUp, _jwt!); diff --git a/packages/app_center/lib/snapd/snapd_service.dart b/packages/app_center/lib/snapd/snapd_service.dart index 49a42e737..b2d01de32 100644 --- a/packages/app_center/lib/snapd/snapd_service.dart +++ b/packages/app_center/lib/snapd/snapd_service.dart @@ -5,4 +5,19 @@ import 'package:snapd/snapd.dart'; class SnapdService extends SnapdClient with SnapdCache, SnapdWatcher { Future waitChange(String changeId) => watchChange(changeId).firstWhere((change) => change.ready); + + Future findById(String snapId) async { + final queryParams = { + 'series': '16', + 'remote': 'true', + 'snap-id': snapId, + }; + final result = + await getAssertions(assertion: 'snap-declaration', params: queryParams); + final declaration = SnapDeclaration.fromJson(result); + final findResult = await find(name: declaration.snapName); + return findResult + .where((element) => element.id == declaration.snapId) + .firstOrNull; + } } diff --git a/packages/app_center/lib/src/l10n/app_en.arb b/packages/app_center/lib/src/l10n/app_en.arb index 2b570b135..5d0f7db97 100644 --- a/packages/app_center/lib/src/l10n/app_en.arb +++ b/packages/app_center/lib/src/l10n/app_en.arb @@ -80,7 +80,7 @@ "developmentPageLabel": "Development", "gamesPageLabel": "Games", "gamesPageTitle": "What's Hot", - "gamesPageTop": "Top Games", + "gamesPageTop": "Top Rated", "gamesPageFeatured": "Featured Titles", "gamesPageBundles": "App Bundles", "unknownPublisher": "Unknown publisher", diff --git a/packages/app_center/lib/widgets/app_card.dart b/packages/app_center/lib/widgets/app_card.dart index 79c8ad610..2d65af81c 100644 --- a/packages/app_center/lib/widgets/app_card.dart +++ b/packages/app_center/lib/widgets/app_card.dart @@ -4,6 +4,7 @@ import 'package:app_center/l10n.dart'; import 'package:app_center/layout.dart'; import 'package:app_center/ratings/ratings.dart'; import 'package:app_center/snapd/snapd.dart'; +import 'package:app_center/widgets/small_banner.dart'; import 'package:app_center/widgets/widgets.dart'; import 'package:appstream/appstream.dart'; import 'package:flutter/material.dart'; @@ -21,6 +22,7 @@ class AppCard extends StatelessWidget { this.compact = false, this.iconUrl, this.footer, + this.rating = 0, }); AppCard.fromSnap({ @@ -35,6 +37,20 @@ class AppCard extends StatelessWidget { onTap: onTap, ); + AppCard.fromRatedSnap({ + required Snap snap, + required int rating, + VoidCallback? onTap, + }) : this( + key: ValueKey(snap.id), + title: AppTitle.fromSnap(snap), + summary: snap.summary, + iconUrl: snap.iconUrl, + footer: _RatingsInfo(snap: snap), + onTap: onTap, + rating: rating, + ); + AppCard.fromDeb({ required AppstreamComponent component, VoidCallback? onTap, @@ -73,30 +89,58 @@ class AppCard extends StatelessWidget { final bool compact; final String? iconUrl; final Widget? footer; + final int rating; @override Widget build(BuildContext context) { - return YaruBanner( - // TODO: Remove color once we have upgraded to a yaru version > 4.1.0 - color: Theme.of(context).cardColor, - padding: const EdgeInsets.all(kCardSpacing), - onTap: onTap, - child: Flex( - direction: compact ? Axis.vertical : Axis.horizontal, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppIcon(iconUrl: iconUrl), - const SizedBox(width: 16, height: 16), - Expanded( - child: _AppCardBody( - title: title, - summary: summary, - footer: footer, - ), - ), - ], + final theme = Theme.of(context); + final appContent = [ + AppIcon(iconUrl: iconUrl), + const SizedBox(width: kCardSpacing, height: kCardSpacing), + Expanded( + child: _AppCardBody( + title: title, + summary: rating > 0 ? '' : summary, + footer: footer, + ), ), - ); + ]; + + return rating > 0 + ? Flex( + direction: Axis.horizontal, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Text( + rating.toString(), + style: theme.textTheme.titleMedium, + ), + ), + const SizedBox( + width: 4, + ), + Expanded( + child: SmallBanner( + onTap: onTap, + child: Flex( + direction: Axis.horizontal, + children: appContent, + ), + ), + ), + ], + ) + : YaruBanner( + padding: const EdgeInsets.all(kCardSpacing), + onTap: onTap, + color: Theme.of(context).cardColor, + child: Flex( + direction: compact ? Axis.vertical : Axis.horizontal, + crossAxisAlignment: CrossAxisAlignment.start, + children: appContent, + ), + ); } } @@ -172,14 +216,16 @@ class _AppCardBody extends StatelessWidget { child: title, ), ), - const SizedBox(height: 12), - Flexible( - child: Text( - summary, - maxLines: maxlines, - overflow: TextOverflow.ellipsis, + if (summary.isNotEmpty) ...[ + const SizedBox(height: 12), + Flexible( + child: Text( + summary, + maxLines: maxlines, + overflow: TextOverflow.ellipsis, + ), ), - ), + ], if (footer != null) ...[ const SizedBox(height: 8), footer!, diff --git a/packages/app_center/lib/widgets/category_snap_list.dart b/packages/app_center/lib/widgets/category_snap_list.dart index d5c6eafaa..a0e87581d 100644 --- a/packages/app_center/lib/widgets/category_snap_list.dart +++ b/packages/app_center/lib/widgets/category_snap_list.dart @@ -1,10 +1,12 @@ import 'package:app_center/explore/explore_page.dart'; +import 'package:app_center/ratings/rated_category_model.dart'; import 'package:app_center/snapd/snapd.dart'; import 'package:app_center/store/store.dart'; import 'package:app_center/widgets/widgets.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:yaru/yaru.dart'; class CategorySnapList extends ConsumerWidget { const CategorySnapList({ @@ -62,3 +64,36 @@ class CategorySnapList extends ConsumerWidget { ); } } + +class RatedCategorySnapList extends ConsumerWidget { + const RatedCategorySnapList({ + required this.categories, + this.numberOfSnaps = 10, + super.key, + }); + + final List categories; + final int numberOfSnaps; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final ratedCategoryModel = + ref.watch(ratedCategoryModelProvider(categories, numberOfSnaps)); + + return ratedCategoryModel.when( + data: (snaps) => AppCardGrid.fromRatedSnaps( + snaps: snaps, + onTap: (snap) => StoreNavigator.pushSnap( + context, + name: snap.name, + ), + ), + error: (error, stackTrace) => SliverToBoxAdapter( + child: Text(error.toString()), + ), + loading: () => const SliverToBoxAdapter( + child: Center(child: YaruCircularProgressIndicator()), + ), + ); + } +} diff --git a/packages/app_center/lib/widgets/small_banner.dart b/packages/app_center/lib/widgets/small_banner.dart new file mode 100644 index 000000000..227705a6c --- /dev/null +++ b/packages/app_center/lib/widgets/small_banner.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:yaru/yaru.dart'; + +/// Slimmer version (no border or description) of the [YaruBanner]. +class SmallBanner extends StatelessWidget { + const SmallBanner({required this.child, super.key, this.onTap}); + + final VoidCallback? onTap; + final Widget child; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final borderRadius = BorderRadius.circular(kYaruBannerRadius); + final light = theme.brightness == Brightness.light; + final defaultSurfaceTintColor = + light ? theme.cardColor : const Color.fromARGB(255, 126, 126, 126); + + return Material( + color: Colors.transparent, + borderRadius: borderRadius, + child: InkWell( + onTap: onTap, + hoverColor: Colors.transparent, + child: Card( + color: theme.cardColor, + shadowColor: Colors.transparent, + surfaceTintColor: defaultSurfaceTintColor, + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: borderRadius.inner(const EdgeInsets.all(4.0)), + ), + child: Container( + padding: const EdgeInsets.all(8.0), + child: child, + ), + ), + ), + ); + } +} diff --git a/packages/app_center/lib/widgets/snap_grid.dart b/packages/app_center/lib/widgets/snap_grid.dart index bcc953520..287836967 100644 --- a/packages/app_center/lib/widgets/snap_grid.dart +++ b/packages/app_center/lib/widgets/snap_grid.dart @@ -8,6 +8,7 @@ import 'package:snapd/snapd.dart'; class AppCardGrid extends StatelessWidget { const AppCardGrid({ required this.appCards, + this.small = false, super.key, }); @@ -24,6 +25,21 @@ class AppCardGrid extends StatelessWidget { ), ); + factory AppCardGrid.fromRatedSnaps({ + required List snaps, + required ValueChanged onTap, + }) => + AppCardGrid( + appCards: snaps.asMap().entries.map( + (entry) => AppCard.fromRatedSnap( + snap: entry.value, + onTap: () => onTap(entry.value), + rating: entry.key + 1, + ), + ), + small: true, + ); + factory AppCardGrid.fromDebs({ required List debs, required ValueChanged onTap, @@ -49,14 +65,31 @@ class AppCardGrid extends StatelessWidget { ); final Iterable appCards; + final bool small; @override Widget build(BuildContext context) { final layout = ResponsiveLayout.of(context); + var columnCount = layout.cardColumnCount; + var cardAspectRatio = layout.cardSize.aspectRatio; + if (small) { + switch (layout.type) { + case ResponsiveLayoutType.small: + columnCount = 2; + cardAspectRatio = 2.5; + case ResponsiveLayoutType.medium: + columnCount = 3; + cardAspectRatio = 2.5; + case ResponsiveLayoutType.large: + columnCount = 4; + cardAspectRatio = 3.0; + } + } + return SliverGrid.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: layout.cardColumnCount, - childAspectRatio: layout.cardSize.aspectRatio, + crossAxisCount: columnCount, + childAspectRatio: cardAspectRatio, mainAxisSpacing: kCardSpacing - 2 * kCardMargin, crossAxisSpacing: kCardSpacing - 2 * kCardMargin, ), diff --git a/packages/app_center/test/ratings_service_test.dart b/packages/app_center/test/ratings_service_test.dart index adb2d75f1..1db0db1e3 100644 --- a/packages/app_center/test/ratings_service_test.dart +++ b/packages/app_center/test/ratings_service_test.dart @@ -1,4 +1,5 @@ import 'package:app_center/ratings/ratings_service.dart'; +import 'package:app_center/snapd/snap_category_enum.dart'; import 'package:app_center_ratings_client/app_center_ratings_client.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; @@ -31,6 +32,55 @@ void main() { ); }); + test('get category', () async { + final mockClient = createMockRatingsClient( + token: 'jwt', + chartData: const [ + ChartData( + rawRating: 117, + rating: Rating( + snapId: 'john', + totalVotes: 117, + ratingsBand: RatingsBand.veryGood, + ), + ), + ChartData( + rawRating: 104, + rating: Rating( + snapId: 'fred', + totalVotes: 104, + ratingsBand: RatingsBand.veryGood, + ), + ), + ], + ); + final service = RatingsService(mockClient, id: 'myId'); + + final charts = await service.getChart(SnapCategoryEnum.games); + verify(mockClient.authenticate('myId')).called(1); + expect( + charts, + containsAll([ + const ChartData( + rawRating: 117, + rating: Rating( + snapId: 'john', + totalVotes: 117, + ratingsBand: RatingsBand.veryGood, + ), + ), + const ChartData( + rawRating: 104, + rating: Rating( + snapId: 'fred', + totalVotes: 104, + ratingsBand: RatingsBand.veryGood, + ), + ), + ]), + ); + }); + test('vote', () async { final mockClient = createMockRatingsClient(token: 'jwt'); final service = RatingsService(mockClient, id: 'myId'); diff --git a/packages/app_center/test/test_utils.dart b/packages/app_center/test/test_utils.dart index d9f090348..7f98f1bfb 100644 --- a/packages/app_center/test/test_utils.dart +++ b/packages/app_center/test/test_utils.dart @@ -336,6 +336,7 @@ MockRatingsClient createMockRatingsClient({ Rating? rating, List? myVotes, List? snapVotes, + List? chartData, }) { final client = MockRatingsClient(); when(client.authenticate(any)).thenAnswer((_) async => token ?? ''); @@ -350,6 +351,7 @@ MockRatingsClient createMockRatingsClient({ ); when(client.listMyVotes(any, any)).thenAnswer((_) async => myVotes ?? []); when(client.getSnapVotes(any, any)).thenAnswer((_) async => snapVotes ?? []); + when(client.getChart(any, any, any)).thenAnswer((_) async => chartData ?? []); return client; } diff --git a/packages/app_center/test/test_utils.mocks.dart b/packages/app_center/test/test_utils.mocks.dart index f0643100c..f2c3fe48e 100644 --- a/packages/app_center/test/test_utils.mocks.dart +++ b/packages/app_center/test/test_utils.mocks.dart @@ -15,7 +15,6 @@ import 'package:app_center/snapd/multisnap_model.dart' as _i11; import 'package:app_center/snapd/snapd.dart' as _i2; import 'package:app_center_ratings_client/app_center_ratings_client.dart' as _i10; -import 'package:app_center_ratings_client/src/chart.dart' as _i21; import 'package:appstream/appstream.dart' as _i8; import 'package:dbus/dbus.dart' as _i19; import 'package:file/file.dart' as _i9; @@ -703,6 +702,15 @@ class MockSnapdService extends _i1.Mock implements _i2.SnapdService { returnValueForMissingStub: _i12.Future.value(), ) as _i12.Future); + @override + _i12.Future<_i4.Snap?> findById(String? snapId) => (super.noSuchMethod( + Invocation.method( + #findById, + [snapId], + ), + returnValue: _i12.Future<_i4.Snap?>.value(), + ) as _i12.Future<_i4.Snap?>); + @override _i12.Future loadAuthorization({String? path}) => (super.noSuchMethod( Invocation.method( @@ -2150,6 +2158,17 @@ class MockRatingsService extends _i1.Mock implements _i20.RatingsService { returnValue: _i12.Future<_i10.Rating?>.value(), ) as _i12.Future<_i10.Rating?>); + @override + _i12.Future> getChart(_i2.SnapCategoryEnum? category) => + (super.noSuchMethod( + Invocation.method( + #getChart, + [category], + ), + returnValue: + _i12.Future>.value(<_i10.ChartData>[]), + ) as _i12.Future>); + @override _i12.Future vote(_i10.Vote? vote) => (super.noSuchMethod( Invocation.method( @@ -2225,21 +2244,23 @@ class MockRatingsClient extends _i1.Mock implements _i10.RatingsClient { ) as _i12.Future); @override - _i12.Future> getChart( - _i21.Timeframe? timeframe, - String? token, - ) => + _i12.Future> getChart( + _i10.Timeframe? timeframe, + String? token, [ + int? category, + ]) => (super.noSuchMethod( Invocation.method( #getChart, [ timeframe, token, + category, ], ), returnValue: - _i12.Future>.value(<_i21.ChartData>[]), - ) as _i12.Future>); + _i12.Future>.value(<_i10.ChartData>[]), + ) as _i12.Future>); @override _i12.Future<_i10.Rating> getRating( diff --git a/packages/app_center_ratings_client/lib/app_center_ratings_client.dart b/packages/app_center_ratings_client/lib/app_center_ratings_client.dart index bc64b90ea..b7096ce4d 100644 --- a/packages/app_center_ratings_client/lib/app_center_ratings_client.dart +++ b/packages/app_center_ratings_client/lib/app_center_ratings_client.dart @@ -1,3 +1,4 @@ +export 'src/chart.dart'; export 'src/ratings.dart'; export 'src/ratings_client.dart'; export 'src/vote.dart'; diff --git a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pb.dart b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pb.dart index c17ae0130..d558fb93c 100644 --- a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pb.dart +++ b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pb.dart @@ -21,72 +21,72 @@ export 'ratings_features_chart.pbenum.dart'; class GetChartRequest extends $pb.GeneratedMessage { factory GetChartRequest({ Timeframe? timeframe, + Category? category, }) { final $result = create(); if (timeframe != null) { $result.timeframe = timeframe; } + if (category != null) { + $result.category = category; + } return $result; } GetChartRequest._() : super(); - factory GetChartRequest.fromBuffer($core.List<$core.int> i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(i, r); - factory GetChartRequest.fromJson($core.String i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'GetChartRequest', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'ratings.features.chart'), - createEmptyInstance: create) - ..e(1, _omitFieldNames ? '' : 'timeframe', $pb.PbFieldType.OE, - defaultOrMaker: Timeframe.TIMEFRAME_UNSPECIFIED, - valueOf: Timeframe.valueOf, - enumValues: Timeframe.values) - ..hasRequiredFields = false; - - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') + factory GetChartRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetChartRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GetChartRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'ratings.features.chart'), createEmptyInstance: create) + ..e(1, _omitFieldNames ? '' : 'timeframe', $pb.PbFieldType.OE, defaultOrMaker: Timeframe.TIMEFRAME_UNSPECIFIED, valueOf: Timeframe.valueOf, enumValues: Timeframe.values) + ..e(2, _omitFieldNames ? '' : 'category', $pb.PbFieldType.OE, defaultOrMaker: Category.ART_AND_DESIGN, valueOf: Category.valueOf, enumValues: Category.values) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') GetChartRequest clone() => GetChartRequest()..mergeFromMessage(this); - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - GetChartRequest copyWith(void Function(GetChartRequest) updates) => - super.copyWith((message) => updates(message as GetChartRequest)) - as GetChartRequest; + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GetChartRequest copyWith(void Function(GetChartRequest) updates) => super.copyWith((message) => updates(message as GetChartRequest)) as GetChartRequest; $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') static GetChartRequest create() => GetChartRequest._(); GetChartRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => - $pb.PbList(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static GetChartRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); + static GetChartRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static GetChartRequest? _defaultInstance; @$pb.TagNumber(1) Timeframe get timeframe => $_getN(0); @$pb.TagNumber(1) - set timeframe(Timeframe v) { - setField(1, v); - } - + set timeframe(Timeframe v) { setField(1, v); } @$pb.TagNumber(1) $core.bool hasTimeframe() => $_has(0); @$pb.TagNumber(1) void clearTimeframe() => clearField(1); + + @$pb.TagNumber(2) + Category get category => $_getN(1); + @$pb.TagNumber(2) + set category(Category v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasCategory() => $_has(1); + @$pb.TagNumber(2) + void clearCategory() => clearField(2); } class GetChartResponse extends $pb.GeneratedMessage { factory GetChartResponse({ Timeframe? timeframe, $core.Iterable? orderedChartData, + Category? category, }) { final $result = create(); if (timeframe != null) { @@ -95,60 +95,47 @@ class GetChartResponse extends $pb.GeneratedMessage { if (orderedChartData != null) { $result.orderedChartData.addAll(orderedChartData); } + if (category != null) { + $result.category = category; + } return $result; } GetChartResponse._() : super(); - factory GetChartResponse.fromBuffer($core.List<$core.int> i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(i, r); - factory GetChartResponse.fromJson($core.String i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'GetChartResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'ratings.features.chart'), - createEmptyInstance: create) - ..e(1, _omitFieldNames ? '' : 'timeframe', $pb.PbFieldType.OE, - defaultOrMaker: Timeframe.TIMEFRAME_UNSPECIFIED, - valueOf: Timeframe.valueOf, - enumValues: Timeframe.values) - ..pc( - 2, _omitFieldNames ? '' : 'orderedChartData', $pb.PbFieldType.PM, - subBuilder: ChartData.create) - ..hasRequiredFields = false; - - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') + factory GetChartResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetChartResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GetChartResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'ratings.features.chart'), createEmptyInstance: create) + ..e(1, _omitFieldNames ? '' : 'timeframe', $pb.PbFieldType.OE, defaultOrMaker: Timeframe.TIMEFRAME_UNSPECIFIED, valueOf: Timeframe.valueOf, enumValues: Timeframe.values) + ..pc(2, _omitFieldNames ? '' : 'orderedChartData', $pb.PbFieldType.PM, subBuilder: ChartData.create) + ..e(3, _omitFieldNames ? '' : 'category', $pb.PbFieldType.OE, defaultOrMaker: Category.ART_AND_DESIGN, valueOf: Category.valueOf, enumValues: Category.values) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') GetChartResponse clone() => GetChartResponse()..mergeFromMessage(this); - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - GetChartResponse copyWith(void Function(GetChartResponse) updates) => - super.copyWith((message) => updates(message as GetChartResponse)) - as GetChartResponse; + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GetChartResponse copyWith(void Function(GetChartResponse) updates) => super.copyWith((message) => updates(message as GetChartResponse)) as GetChartResponse; $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') static GetChartResponse create() => GetChartResponse._(); GetChartResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => - $pb.PbList(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static GetChartResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); + static GetChartResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static GetChartResponse? _defaultInstance; @$pb.TagNumber(1) Timeframe get timeframe => $_getN(0); @$pb.TagNumber(1) - set timeframe(Timeframe v) { - setField(1, v); - } - + set timeframe(Timeframe v) { setField(1, v); } @$pb.TagNumber(1) $core.bool hasTimeframe() => $_has(0); @$pb.TagNumber(1) @@ -156,6 +143,15 @@ class GetChartResponse extends $pb.GeneratedMessage { @$pb.TagNumber(2) $core.List get orderedChartData => $_getList(1); + + @$pb.TagNumber(3) + Category get category => $_getN(2); + @$pb.TagNumber(3) + set category(Category v) { setField(3, v); } + @$pb.TagNumber(3) + $core.bool hasCategory() => $_has(2); + @$pb.TagNumber(3) + void clearCategory() => clearField(3); } class ChartData extends $pb.GeneratedMessage { @@ -173,32 +169,25 @@ class ChartData extends $pb.GeneratedMessage { return $result; } ChartData._() : super(); - factory ChartData.fromBuffer($core.List<$core.int> i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(i, r); - factory ChartData.fromJson($core.String i, - [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ChartData', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'ratings.features.chart'), - createEmptyInstance: create) - ..a<$core.double>(1, _omitFieldNames ? '' : 'rawRating', $pb.PbFieldType.OF) - ..aOM<$1.Rating>(2, _omitFieldNames ? '' : 'rating', - subBuilder: $1.Rating.create) - ..hasRequiredFields = false; + factory ChartData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChartData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ChartData', package: const $pb.PackageName(_omitMessageNames ? '' : 'ratings.features.chart'), createEmptyInstance: create) + ..a<$core.double>(1, _omitFieldNames ? '' : 'rawRating', $pb.PbFieldType.OF) + ..aOM<$1.Rating>(2, _omitFieldNames ? '' : 'rating', subBuilder: $1.Rating.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') ChartData clone() => ChartData()..mergeFromMessage(this); - @$core.Deprecated('Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - ChartData copyWith(void Function(ChartData) updates) => - super.copyWith((message) => updates(message as ChartData)) as ChartData; + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ChartData copyWith(void Function(ChartData) updates) => super.copyWith((message) => updates(message as ChartData)) as ChartData; $pb.BuilderInfo get info_ => _i; @@ -207,17 +196,13 @@ class ChartData extends $pb.GeneratedMessage { ChartData createEmptyInstance() => create(); static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static ChartData getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ChartData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static ChartData? _defaultInstance; @$pb.TagNumber(1) $core.double get rawRating => $_getN(0); @$pb.TagNumber(1) - set rawRating($core.double v) { - $_setFloat(0, v); - } - + set rawRating($core.double v) { $_setFloat(0, v); } @$pb.TagNumber(1) $core.bool hasRawRating() => $_has(0); @$pb.TagNumber(1) @@ -226,10 +211,7 @@ class ChartData extends $pb.GeneratedMessage { @$pb.TagNumber(2) $1.Rating get rating => $_getN(1); @$pb.TagNumber(2) - set rating($1.Rating v) { - setField(2, v); - } - + set rating($1.Rating v) { setField(2, v); } @$pb.TagNumber(2) $core.bool hasRating() => $_has(1); @$pb.TagNumber(2) @@ -238,6 +220,6 @@ class ChartData extends $pb.GeneratedMessage { $1.Rating ensureRating() => $_ensure(1); } + const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); -const _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbenum.dart b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbenum.dart index f8d8dcee8..edbc693d8 100644 --- a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbenum.dart +++ b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbenum.dart @@ -14,24 +14,72 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; class Timeframe extends $pb.ProtobufEnum { - static const Timeframe TIMEFRAME_UNSPECIFIED = - Timeframe._(0, _omitEnumNames ? '' : 'TIMEFRAME_UNSPECIFIED'); - static const Timeframe TIMEFRAME_WEEK = - Timeframe._(1, _omitEnumNames ? '' : 'TIMEFRAME_WEEK'); - static const Timeframe TIMEFRAME_MONTH = - Timeframe._(2, _omitEnumNames ? '' : 'TIMEFRAME_MONTH'); - - static const $core.List values = [ + static const Timeframe TIMEFRAME_UNSPECIFIED = Timeframe._(0, _omitEnumNames ? '' : 'TIMEFRAME_UNSPECIFIED'); + static const Timeframe TIMEFRAME_WEEK = Timeframe._(1, _omitEnumNames ? '' : 'TIMEFRAME_WEEK'); + static const Timeframe TIMEFRAME_MONTH = Timeframe._(2, _omitEnumNames ? '' : 'TIMEFRAME_MONTH'); + + static const $core.List values = [ TIMEFRAME_UNSPECIFIED, TIMEFRAME_WEEK, TIMEFRAME_MONTH, ]; - static final $core.Map<$core.int, Timeframe> _byValue = - $pb.ProtobufEnum.initByValue(values); + static final $core.Map<$core.int, Timeframe> _byValue = $pb.ProtobufEnum.initByValue(values); static Timeframe? valueOf($core.int value) => _byValue[value]; const Timeframe._($core.int v, $core.String n) : super(v, n); } +class Category extends $pb.ProtobufEnum { + static const Category ART_AND_DESIGN = Category._(0, _omitEnumNames ? '' : 'ART_AND_DESIGN'); + static const Category BOOK_AND_REFERENCE = Category._(1, _omitEnumNames ? '' : 'BOOK_AND_REFERENCE'); + static const Category DEVELOPMENT = Category._(2, _omitEnumNames ? '' : 'DEVELOPMENT'); + static const Category DEVICES_AND_IOT = Category._(3, _omitEnumNames ? '' : 'DEVICES_AND_IOT'); + static const Category EDUCATION = Category._(4, _omitEnumNames ? '' : 'EDUCATION'); + static const Category ENTERTAINMENT = Category._(5, _omitEnumNames ? '' : 'ENTERTAINMENT'); + static const Category FEATURED = Category._(6, _omitEnumNames ? '' : 'FEATURED'); + static const Category FINANCE = Category._(7, _omitEnumNames ? '' : 'FINANCE'); + static const Category GAMES = Category._(8, _omitEnumNames ? '' : 'GAMES'); + static const Category HEALTH_AND_FITNESS = Category._(9, _omitEnumNames ? '' : 'HEALTH_AND_FITNESS'); + static const Category MUSIC_AND_AUDIO = Category._(10, _omitEnumNames ? '' : 'MUSIC_AND_AUDIO'); + static const Category NEWS_AND_WEATHER = Category._(11, _omitEnumNames ? '' : 'NEWS_AND_WEATHER'); + static const Category PERSONALISATION = Category._(12, _omitEnumNames ? '' : 'PERSONALISATION'); + static const Category PHOTO_AND_VIDEO = Category._(13, _omitEnumNames ? '' : 'PHOTO_AND_VIDEO'); + static const Category PRODUCTIVITY = Category._(14, _omitEnumNames ? '' : 'PRODUCTIVITY'); + static const Category SCIENCE = Category._(15, _omitEnumNames ? '' : 'SCIENCE'); + static const Category SECURITY = Category._(16, _omitEnumNames ? '' : 'SECURITY'); + static const Category SERVER_AND_CLOUD = Category._(17, _omitEnumNames ? '' : 'SERVER_AND_CLOUD'); + static const Category SOCIAL = Category._(18, _omitEnumNames ? '' : 'SOCIAL'); + static const Category UTILITIES = Category._(19, _omitEnumNames ? '' : 'UTILITIES'); + + static const $core.List values = [ + ART_AND_DESIGN, + BOOK_AND_REFERENCE, + DEVELOPMENT, + DEVICES_AND_IOT, + EDUCATION, + ENTERTAINMENT, + FEATURED, + FINANCE, + GAMES, + HEALTH_AND_FITNESS, + MUSIC_AND_AUDIO, + NEWS_AND_WEATHER, + PERSONALISATION, + PHOTO_AND_VIDEO, + PRODUCTIVITY, + SCIENCE, + SECURITY, + SERVER_AND_CLOUD, + SOCIAL, + UTILITIES, + ]; + + static final $core.Map<$core.int, Category> _byValue = $pb.ProtobufEnum.initByValue(values); + static Category? valueOf($core.int value) => _byValue[value]; + + const Category._($core.int v, $core.String n) : super(v, n); +} + + const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbgrpc.dart b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbgrpc.dart index d6c2ec188..d49f05ff2 100644 --- a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbgrpc.dart +++ b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbgrpc.dart @@ -12,49 +12,48 @@ import 'dart:async' as $async; import 'dart:core' as $core; -import 'package:app_center_ratings_client/src/generated/ratings_features_chart.pb.dart' - as $0; import 'package:grpc/service_api.dart' as $grpc; import 'package:protobuf/protobuf.dart' as $pb; +import 'ratings_features_chart.pb.dart' as $0; + export 'ratings_features_chart.pb.dart'; @$pb.GrpcServiceName('ratings.features.chart.Chart') class ChartClient extends $grpc.Client { + static final _$getChart = $grpc.ClientMethod<$0.GetChartRequest, $0.GetChartResponse>( + '/ratings.features.chart.Chart/GetChart', + ($0.GetChartRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.GetChartResponse.fromBuffer(value)); + ChartClient($grpc.ClientChannel channel, {$grpc.CallOptions? options, $core.Iterable<$grpc.ClientInterceptor>? interceptors}) - : super(channel, options: options, interceptors: interceptors); - static final _$getChart = - $grpc.ClientMethod<$0.GetChartRequest, $0.GetChartResponse>( - '/ratings.features.chart.Chart/GetChart', - (value) => value.writeToBuffer(), - (value) => $0.GetChartResponse.fromBuffer(value)); - - $grpc.ResponseFuture<$0.GetChartResponse> getChart($0.GetChartRequest request, - {$grpc.CallOptions? options}) { + : super(channel, options: options, + interceptors: interceptors); + + $grpc.ResponseFuture<$0.GetChartResponse> getChart($0.GetChartRequest request, {$grpc.CallOptions? options}) { return $createUnaryCall(_$getChart, request, options: options); } } @$pb.GrpcServiceName('ratings.features.chart.Chart') abstract class ChartServiceBase extends $grpc.Service { + $core.String get $name => 'ratings.features.chart.Chart'; + ChartServiceBase() { $addMethod($grpc.ServiceMethod<$0.GetChartRequest, $0.GetChartResponse>( 'GetChart', getChart_Pre, false, false, - (value) => $0.GetChartRequest.fromBuffer(value), - (value) => value.writeToBuffer())); + ($core.List<$core.int> value) => $0.GetChartRequest.fromBuffer(value), + ($0.GetChartResponse value) => value.writeToBuffer())); } - $core.String get $name => 'ratings.features.chart.Chart'; - $async.Future<$0.GetChartResponse> getChart_Pre( - $grpc.ServiceCall call, $async.Future<$0.GetChartRequest> request) async { + $async.Future<$0.GetChartResponse> getChart_Pre($grpc.ServiceCall call, $async.Future<$0.GetChartRequest> request) async { return getChart(call, await request); } - $async.Future<$0.GetChartResponse> getChart( - $grpc.ServiceCall call, $0.GetChartRequest request); + $async.Future<$0.GetChartResponse> getChart($grpc.ServiceCall call, $0.GetChartRequest request); } diff --git a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbjson.dart b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbjson.dart index 3ba8ff1b0..5fbec9034 100644 --- a/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbjson.dart +++ b/packages/app_center_ratings_client/lib/src/generated/ratings_features_chart.pbjson.dart @@ -28,46 +28,71 @@ final $typed_data.Uint8List timeframeDescriptor = $convert.base64Decode( 'CglUaW1lZnJhbWUSGQoVVElNRUZSQU1FX1VOU1BFQ0lGSUVEEAASEgoOVElNRUZSQU1FX1dFRU' 'sQARITCg9USU1FRlJBTUVfTU9OVEgQAg=='); +@$core.Deprecated('Use categoryDescriptor instead') +const Category$json = { + '1': 'Category', + '2': [ + {'1': 'ART_AND_DESIGN', '2': 0}, + {'1': 'BOOK_AND_REFERENCE', '2': 1}, + {'1': 'DEVELOPMENT', '2': 2}, + {'1': 'DEVICES_AND_IOT', '2': 3}, + {'1': 'EDUCATION', '2': 4}, + {'1': 'ENTERTAINMENT', '2': 5}, + {'1': 'FEATURED', '2': 6}, + {'1': 'FINANCE', '2': 7}, + {'1': 'GAMES', '2': 8}, + {'1': 'HEALTH_AND_FITNESS', '2': 9}, + {'1': 'MUSIC_AND_AUDIO', '2': 10}, + {'1': 'NEWS_AND_WEATHER', '2': 11}, + {'1': 'PERSONALISATION', '2': 12}, + {'1': 'PHOTO_AND_VIDEO', '2': 13}, + {'1': 'PRODUCTIVITY', '2': 14}, + {'1': 'SCIENCE', '2': 15}, + {'1': 'SECURITY', '2': 16}, + {'1': 'SERVER_AND_CLOUD', '2': 17}, + {'1': 'SOCIAL', '2': 18}, + {'1': 'UTILITIES', '2': 19}, + ], +}; + +/// Descriptor for `Category`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List categoryDescriptor = $convert.base64Decode( + 'CghDYXRlZ29yeRISCg5BUlRfQU5EX0RFU0lHThAAEhYKEkJPT0tfQU5EX1JFRkVSRU5DRRABEg' + '8KC0RFVkVMT1BNRU5UEAISEwoPREVWSUNFU19BTkRfSU9UEAMSDQoJRURVQ0FUSU9OEAQSEQoN' + 'RU5URVJUQUlOTUVOVBAFEgwKCEZFQVRVUkVEEAYSCwoHRklOQU5DRRAHEgkKBUdBTUVTEAgSFg' + 'oSSEVBTFRIX0FORF9GSVRORVNTEAkSEwoPTVVTSUNfQU5EX0FVRElPEAoSFAoQTkVXU19BTkRf' + 'V0VBVEhFUhALEhMKD1BFUlNPTkFMSVNBVElPThAMEhMKD1BIT1RPX0FORF9WSURFTxANEhAKDF' + 'BST0RVQ1RJVklUWRAOEgsKB1NDSUVOQ0UQDxIMCghTRUNVUklUWRAQEhQKEFNFUlZFUl9BTkRf' + 'Q0xPVUQQERIKCgZTT0NJQUwQEhINCglVVElMSVRJRVMQEw=='); + @$core.Deprecated('Use getChartRequestDescriptor instead') const GetChartRequest$json = { '1': 'GetChartRequest', '2': [ - { - '1': 'timeframe', - '3': 1, - '4': 1, - '5': 14, - '6': '.ratings.features.chart.Timeframe', - '10': 'timeframe' - }, + {'1': 'timeframe', '3': 1, '4': 1, '5': 14, '6': '.ratings.features.chart.Timeframe', '10': 'timeframe'}, + {'1': 'category', '3': 2, '4': 1, '5': 14, '6': '.ratings.features.chart.Category', '9': 0, '10': 'category', '17': true}, + ], + '8': [ + {'1': '_category'}, ], }; /// Descriptor for `GetChartRequest`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List getChartRequestDescriptor = $convert.base64Decode( 'Cg9HZXRDaGFydFJlcXVlc3QSPwoJdGltZWZyYW1lGAEgASgOMiEucmF0aW5ncy5mZWF0dXJlcy' - '5jaGFydC5UaW1lZnJhbWVSCXRpbWVmcmFtZQ=='); + '5jaGFydC5UaW1lZnJhbWVSCXRpbWVmcmFtZRJBCghjYXRlZ29yeRgCIAEoDjIgLnJhdGluZ3Mu' + 'ZmVhdHVyZXMuY2hhcnQuQ2F0ZWdvcnlIAFIIY2F0ZWdvcnmIAQFCCwoJX2NhdGVnb3J5'); @$core.Deprecated('Use getChartResponseDescriptor instead') const GetChartResponse$json = { '1': 'GetChartResponse', '2': [ - { - '1': 'timeframe', - '3': 1, - '4': 1, - '5': 14, - '6': '.ratings.features.chart.Timeframe', - '10': 'timeframe' - }, - { - '1': 'ordered_chart_data', - '3': 2, - '4': 3, - '5': 11, - '6': '.ratings.features.chart.ChartData', - '10': 'orderedChartData' - }, + {'1': 'timeframe', '3': 1, '4': 1, '5': 14, '6': '.ratings.features.chart.Timeframe', '10': 'timeframe'}, + {'1': 'ordered_chart_data', '3': 2, '4': 3, '5': 11, '6': '.ratings.features.chart.ChartData', '10': 'orderedChartData'}, + {'1': 'category', '3': 3, '4': 1, '5': 14, '6': '.ratings.features.chart.Category', '9': 0, '10': 'category', '17': true}, + ], + '8': [ + {'1': '_category'}, ], }; @@ -75,21 +100,16 @@ const GetChartResponse$json = { final $typed_data.Uint8List getChartResponseDescriptor = $convert.base64Decode( 'ChBHZXRDaGFydFJlc3BvbnNlEj8KCXRpbWVmcmFtZRgBIAEoDjIhLnJhdGluZ3MuZmVhdHVyZX' 'MuY2hhcnQuVGltZWZyYW1lUgl0aW1lZnJhbWUSTwoSb3JkZXJlZF9jaGFydF9kYXRhGAIgAygL' - 'MiEucmF0aW5ncy5mZWF0dXJlcy5jaGFydC5DaGFydERhdGFSEG9yZGVyZWRDaGFydERhdGE='); + 'MiEucmF0aW5ncy5mZWF0dXJlcy5jaGFydC5DaGFydERhdGFSEG9yZGVyZWRDaGFydERhdGESQQ' + 'oIY2F0ZWdvcnkYAyABKA4yIC5yYXRpbmdzLmZlYXR1cmVzLmNoYXJ0LkNhdGVnb3J5SABSCGNh' + 'dGVnb3J5iAEBQgsKCV9jYXRlZ29yeQ=='); @$core.Deprecated('Use chartDataDescriptor instead') const ChartData$json = { '1': 'ChartData', '2': [ {'1': 'raw_rating', '3': 1, '4': 1, '5': 2, '10': 'rawRating'}, - { - '1': 'rating', - '3': 2, - '4': 1, - '5': 11, - '6': '.ratings.features.common.Rating', - '10': 'rating' - }, + {'1': 'rating', '3': 2, '4': 1, '5': 11, '6': '.ratings.features.common.Rating', '10': 'rating'}, ], }; @@ -97,3 +117,4 @@ const ChartData$json = { final $typed_data.Uint8List chartDataDescriptor = $convert.base64Decode( 'CglDaGFydERhdGESHQoKcmF3X3JhdGluZxgBIAEoAlIJcmF3UmF0aW5nEjcKBnJhdGluZxgCIA' 'EoCzIfLnJhdGluZ3MuZmVhdHVyZXMuY29tbW9uLlJhdGluZ1IGcmF0aW5n'); + diff --git a/packages/app_center_ratings_client/lib/src/ratings_client.dart b/packages/app_center_ratings_client/lib/src/ratings_client.dart index 1471194d3..5d67efdcb 100644 --- a/packages/app_center_ratings_client/lib/src/ratings_client.dart +++ b/packages/app_center_ratings_client/lib/src/ratings_client.dart @@ -53,8 +53,15 @@ class RatingsClient { await _userClient.delete(request, options: callOptions); } - Future> getChart(Timeframe timeframe, String token) async { - final request = chart_pb.GetChartRequest(timeframe: timeframe.toDTO()); + Future> getChart( + Timeframe timeframe, + String token, [ + int? category, + ]) async { + final request = chart_pb.GetChartRequest( + timeframe: timeframe.toDTO(), + category: category != null ? chart_pb.Category.valueOf(category) : null, + ); final callOptions = CallOptions(metadata: {'authorization': 'Bearer $token'}); final grpcResponse = diff --git a/packages/app_center_ratings_client/protos/ratings_features_chart.proto b/packages/app_center_ratings_client/protos/ratings_features_chart.proto index 19f39d37e..b426445af 100644 --- a/packages/app_center_ratings_client/protos/ratings_features_chart.proto +++ b/packages/app_center_ratings_client/protos/ratings_features_chart.proto @@ -10,11 +10,13 @@ service Chart { message GetChartRequest { Timeframe timeframe = 1; + optional Category category = 2; } message GetChartResponse { Timeframe timeframe = 1; repeated ChartData ordered_chart_data = 2; + optional Category category = 3; } message ChartData { @@ -27,3 +29,26 @@ enum Timeframe { TIMEFRAME_WEEK = 1; TIMEFRAME_MONTH = 2; } + +enum Category { + ART_AND_DESIGN = 0; + BOOK_AND_REFERENCE = 1; + DEVELOPMENT = 2; + DEVICES_AND_IOT = 3; + EDUCATION = 4; + ENTERTAINMENT = 5; + FEATURED = 6; + FINANCE = 7; + GAMES = 8; + HEALTH_AND_FITNESS = 9; + MUSIC_AND_AUDIO = 10; + NEWS_AND_WEATHER = 11; + PERSONALISATION = 12; + PHOTO_AND_VIDEO = 13; + PRODUCTIVITY = 14; + SCIENCE = 15; + SECURITY = 16; + SERVER_AND_CLOUD = 17; + SOCIAL = 18; + UTILITIES = 19; +} diff --git a/packages/app_center_ratings_client/test/ratings_client_test.dart b/packages/app_center_ratings_client/test/ratings_client_test.dart index c3b33e732..01915ba24 100644 --- a/packages/app_center_ratings_client/test/ratings_client_test.dart +++ b/packages/app_center_ratings_client/test/ratings_client_test.dart @@ -7,7 +7,8 @@ import 'package:app_center_ratings_client/src/generated/google/protobuf/empty.pb import 'package:app_center_ratings_client/src/generated/google/protobuf/timestamp.pb.dart'; import 'package:app_center_ratings_client/src/generated/ratings_features_app.pbgrpc.dart' as pb; -import 'package:app_center_ratings_client/src/generated/ratings_features_chart.pbgrpc.dart'; +import 'package:app_center_ratings_client/src/generated/ratings_features_chart.pbgrpc.dart' + as pb_chart; import 'package:app_center_ratings_client/src/generated/ratings_features_common.pb.dart'; import 'package:app_center_ratings_client/src/generated/ratings_features_user.pbgrpc.dart'; import 'package:app_center_ratings_client/src/ratings.dart' as ratings; @@ -20,7 +21,7 @@ import 'package:test/test.dart'; import 'ratings_client_test.mocks.dart'; -@GenerateMocks([pb.AppClient, UserClient, ChartClient]) +@GenerateMocks([pb.AppClient, UserClient, pb_chart.ChartClient]) void main() { final mockAppClient = MockAppClient(); final mockUserClient = MockUserClient(); @@ -33,7 +34,7 @@ void main() { const token = 'bar'; const timeframe = chart.Timeframe.month; final pbChartList = [ - ChartData( + pb_chart.ChartData( rawRating: 3, rating: Rating( snapId: snapId, @@ -53,18 +54,27 @@ void main() { ), ), ]; - final mockResponse = GetChartResponse( - timeframe: Timeframe.TIMEFRAME_MONTH, + final mockResponse = pb_chart.GetChartResponse( + timeframe: pb_chart.Timeframe.TIMEFRAME_MONTH, orderedChartData: pbChartList, ); - final request = GetChartRequest(timeframe: Timeframe.TIMEFRAME_MONTH); + final request = pb_chart.GetChartRequest( + timeframe: pb_chart.Timeframe.TIMEFRAME_MONTH, + category: pb_chart.Category.GAMES, + ); when( mockChartClient.getChart( request, options: anyNamed('options'), ), - ).thenAnswer((_) => MockResponseFuture(mockResponse)); - final response = await ratingsClient.getChart(timeframe, token); + ).thenAnswer( + (_) => MockResponseFuture(mockResponse), + ); + final response = await ratingsClient.getChart( + timeframe, + token, + pb_chart.Category.GAMES.value, + ); expect( response, equals(expectedResponse),