Tweak stream card weights & tap category (#91)
This commit is contained in:
parent
300981a849
commit
7673f3753d
6 changed files with 72 additions and 7 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ class CategoryStreams extends StatelessWidget {
|
|||
width: thumbnailWidth,
|
||||
height: thumbnailHeight,
|
||||
showUptime: context.read<SettingsStore>().showThumbnailUptime,
|
||||
showCategory: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue