Tweak stream card weights & tap category (#91)

This commit is contained in:
Tommy Chow 2022-03-25 21:23:14 -04:00
parent 300981a849
commit 7673f3753d
6 changed files with 72 additions and 7 deletions

View file

@ -326,6 +326,22 @@ class TwitchApi {
}
}
/// Returns a [CategoriesTwitch] object containing the category info corresponding to the provided [gameId].
Future<CategoriesTwitch> getCategory({
required Map<String, String> headers,
required String gameId,
}) async {
final url = Uri.parse('https://api.twitch.tv/helix/games?id=$gameId');
final response = await _client.get(url, headers: headers);
final decoded = jsonDecode(response.body);
if (response.statusCode == 200) {
return CategoriesTwitch.fromJson(decoded);
} else {
return Future.error('Failed to get category: ${decoded['message']}');
}
}
/// Returns a [CategoriesTwitch] containing up to 20 categories/games closest matching the [query] and a cursor for further requests.
Future<CategoriesTwitch> searchCategories({
required Map<String, String> headers,

View file

@ -20,7 +20,7 @@ class CategoryTwitch {
@JsonSerializable(createToJson: false, fieldRename: FieldRename.snake)
class CategoriesTwitch {
final List<CategoryTwitch> data;
final Map<String, String> pagination;
final Map<String, String>? pagination;
const CategoriesTwitch(
this.data,

View file

@ -18,5 +18,7 @@ CategoriesTwitch _$CategoriesTwitchFromJson(Map<String, dynamic> json) =>
(json['data'] as List<dynamic>)
.map((e) => CategoryTwitch.fromJson(e as Map<String, dynamic>))
.toList(),
Map<String, String>.from(json['pagination'] as Map),
(json['pagination'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as String),
),
);

View file

@ -5,6 +5,7 @@ import 'package:frosty/api/twitch_api.dart';
import 'package:frosty/core/auth/auth_store.dart';
import 'package:frosty/models/category.dart';
import 'package:mobx/mobx.dart';
part 'categories_store.g.dart';
class CategoriesStore = _CategoriesStoreBase with _$CategoriesStore;
@ -68,7 +69,7 @@ abstract class _CategoriesStoreBase with Store {
} else {
_categories.addAll(result.data);
}
_categoriesCursor = result.pagination['cursor'];
_categoriesCursor = result.pagination?['cursor'];
_error = null;
} on SocketException {

View file

@ -95,6 +95,7 @@ class CategoryStreams extends StatelessWidget {
width: thumbnailWidth,
height: thumbnailHeight,
showUptime: context.read<SettingsStore>().showThumbnailUptime,
showCategory: false,
),
);
},

View file

@ -1,13 +1,17 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:frosty/api/twitch_api.dart';
import 'package:frosty/constants/constants.dart';
import 'package:frosty/core/auth/auth_store.dart';
import 'package:frosty/models/stream.dart';
import 'package:frosty/screens/channel/video_chat.dart';
import 'package:frosty/screens/home/stores/list_store.dart';
import 'package:frosty/screens/home/top/category_streams.dart';
import 'package:frosty/widgets/block_report_modal.dart';
import 'package:frosty/widgets/loading_indicator.dart';
import 'package:frosty/widgets/profile_picture.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
/// A tappable card widget that displays a stream's thumbnail and details.
class StreamCard extends StatelessWidget {
@ -16,6 +20,7 @@ class StreamCard extends StatelessWidget {
final int width;
final int height;
final bool showUptime;
final bool showCategory;
const StreamCard({
Key? key,
@ -24,6 +29,7 @@ class StreamCard extends StatelessWidget {
required this.width,
required this.height,
required this.showUptime,
this.showCategory = true,
}) : super(key: key);
@override
@ -105,7 +111,10 @@ class StreamCard extends StatelessWidget {
preferBelow: false,
child: Text(
streamerName,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
@ -120,14 +129,50 @@ class StreamCard extends StatelessWidget {
child: Text(
streamInfo.title.trim(),
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w500,
color: DefaultTextStyle.of(context).style.color?.withOpacity(0.8),
),
),
),
const SizedBox(height: 5.0),
Text(streamInfo.gameName),
const SizedBox(height: 5.0),
if (showCategory) ...[
InkWell(
child: Text(
streamInfo.gameName,
style: TextStyle(
fontWeight: FontWeight.w300,
color: DefaultTextStyle.of(context).style.color?.withOpacity(0.8),
),
),
onTap: () async {
final category = await context
.read<TwitchApi>()
.getCategory(headers: context.read<AuthStore>().headersTwitch, gameId: streamInfo.gameId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryStreams(
listStore: ListStore(
twitchApi: context.read<TwitchApi>(),
authStore: context.read<AuthStore>(),
listType: ListType.category,
categoryInfo: category.data.first,
),
),
),
);
},
),
const SizedBox(height: 5.0),
],
Text(
'${NumberFormat().format(streamInfo.viewerCount)} viewers',
style: const TextStyle(fontSize: 12),
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w300,
color: DefaultTextStyle.of(context).style.color?.withOpacity(0.8),
),
),
],
),