From 1a53101047d6a42a7598dd06b16845186b396ef7 Mon Sep 17 00:00:00 2001 From: tommyxchow Date: Sun, 16 Jan 2022 12:39:20 -0500 Subject: [PATCH] Add some documentation --- lib/api/bttv_api.dart | 4 +- lib/api/ffz_api.dart | 4 +- lib/api/seventv_api.dart | 7 +- lib/api/twitch_api.dart | 74 +++++++++++-------- lib/main.dart | 6 +- lib/models/{irc_message.dart => irc.dart} | 6 +- .../channel/chat/details/chat_modes.dart | 2 +- .../channel/chat/widgets/chat_message.dart | 2 +- .../channel/stores/chat_assets_store.dart | 2 +- .../channel/stores/chat_details_store.dart | 2 +- lib/screens/channel/stores/chat_store.dart | 2 +- lib/screens/channel/video_chat.dart | 9 +-- .../home/search/search_results_channels.dart | 6 +- lib/screens/home/widgets/stream_card.dart | 3 +- 14 files changed, 68 insertions(+), 61 deletions(-) rename lib/models/{irc_message.dart => irc.dart} (99%) diff --git a/lib/api/bttv_api.dart b/lib/api/bttv_api.dart index 5c514881..0c017cee 100644 --- a/lib/api/bttv_api.dart +++ b/lib/api/bttv_api.dart @@ -4,10 +4,11 @@ import 'package:frosty/models/badges.dart'; import 'package:frosty/models/emotes.dart'; import 'package:http/http.dart'; +/// The BTTV service for making API calls. class BTTVApi { final Client _client; - BTTVApi(this._client); + const BTTVApi(this._client); /// Returns a map of global BTTV emotes to their URL. Future> getEmotesGlobal() async { @@ -43,6 +44,7 @@ class BTTVApi { } } + /// Returns a map of username to their BTTV badge. Future> getBadges() async { final url = Uri.parse('https://api.betterttv.net/3/cached/badges'); diff --git a/lib/api/ffz_api.dart b/lib/api/ffz_api.dart index d148b3e9..85e15fbf 100644 --- a/lib/api/ffz_api.dart +++ b/lib/api/ffz_api.dart @@ -5,10 +5,11 @@ import 'package:frosty/models/emotes.dart'; import 'package:http/http.dart'; import 'package:tuple/tuple.dart'; +/// The FFZ service for making API calls. class FFZApi { final Client _client; - FFZApi(this._client); + const FFZApi(this._client); /// Returns a map of global FFZ emotes to their URL. Future> getEmotesGlobal() async { @@ -49,6 +50,7 @@ class FFZApi { } } + /// Returns a map of badges user IDs to a list of their FFZ badges. Future>> getBadges() async { final url = Uri.parse('https://api.frankerfacez.com/v1/badges/ids'); diff --git a/lib/api/seventv_api.dart b/lib/api/seventv_api.dart index 8d60a243..1b94db5d 100644 --- a/lib/api/seventv_api.dart +++ b/lib/api/seventv_api.dart @@ -4,11 +4,11 @@ import 'package:frosty/models/badges.dart'; import 'package:frosty/models/emotes.dart'; import 'package:http/http.dart'; -// A class for general requests. -class SevenTVAPI { +/// The 7TV service for making API calls. +class SevenTVApi { final Client _client; - SevenTVAPI(this._client); + const SevenTVApi(this._client); /// Returns a map of global 7TV emotes to their URL. Future> getEmotesGlobal() async { @@ -40,6 +40,7 @@ class SevenTVAPI { } } + /// Returns a map of user IDS to a list of their 7TV badges. Future>> getBadges() async { final url = Uri.parse('https://api.7tv.app/v2/badges?user_identifier=twitch_id'); diff --git a/lib/api/twitch_api.dart b/lib/api/twitch_api.dart index 45aea8f8..ca1c3800 100644 --- a/lib/api/twitch_api.dart +++ b/lib/api/twitch_api.dart @@ -11,12 +11,14 @@ import 'package:frosty/models/stream.dart'; import 'package:frosty/models/user.dart'; import 'package:http/http.dart'; +/// The Twitch service for making API calls. class TwitchApi { final Client _client; - TwitchApi(this._client); + const TwitchApi(this._client); - Future> getEmotesGlobal({required Map? headers}) async { + /// Returns a list of all Twitch global emotes. + Future> getEmotesGlobal({required Map headers}) async { final url = Uri.parse('https://api.twitch.tv/helix/chat/emotes/global'); final response = await _client.get(url, headers: headers); @@ -30,10 +32,10 @@ class TwitchApi { } } - /// Returns a map of a channel's Twitch emotes to their URL. + /// Returns a list of a channel's Twitch emotes given their [id]. Future> getEmotesChannel({ required String id, - required Map? headers, + required Map headers, }) async { final url = Uri.parse('https://api.twitch.tv/helix/chat/emotes?broadcaster_id=$id'); @@ -48,10 +50,10 @@ class TwitchApi { } } - /// Returns a map of a channel's Twitch emotes to their URL. + /// Returns a list of Twitch emotes under the provided [setId]. Future> getEmotesSets({ required String setId, - required Map? headers, + required Map headers, }) async { final url = Uri.parse('https://api.twitch.tv/helix/chat/emotes/set?emote_set_id=$setId'); @@ -76,7 +78,7 @@ class TwitchApi { } } - /// Returns a map of global Twitch badges to their URL. + /// Returns a map of global Twitch badges to their [Emote] object. Future> getBadgesGlobal() async { final url = Uri.parse('https://badges.twitch.tv/v1/badges/global/display'); @@ -93,7 +95,7 @@ class TwitchApi { } } - /// Returns a map of a channel's Twitch badges to their URL. + /// Returns a map of a channel's Twitch badges to their [Emote] object. Future> getBadgesChannel({required String id}) async { final url = Uri.parse('https://badges.twitch.tv/v1/badges/channels/$id/display'); @@ -110,8 +112,8 @@ class TwitchApi { } } - /// Returns the user's info given their token (headers) - Future getUserInfo({required Map? headers}) async { + /// Returns the user's info given their token through [headers]. + Future getUserInfo({required Map headers}) async { final url = Uri.parse('https://api.twitch.tv/helix/users'); final response = await _client.get(url, headers: headers); @@ -145,7 +147,7 @@ class TwitchApi { } } - /// Returns the validity of the given token + /// Returns a bool indicating the validity of the given token. Future validateToken({required String token}) async { final url = Uri.parse('https://id.twitch.tv/oauth2/validate'); @@ -159,9 +161,9 @@ class TwitchApi { } } - /// Returns a map containing top 20 streams and a cursor for further requests. + /// Returns a [StreamsTwitch] object that contains the top 20 streams and a cursor for further requests. Future getTopStreams({ - required Map? headers, + required Map headers, String? cursor, }) async { final url = Uri.parse(cursor == null ? 'https://api.twitch.tv/helix/streams' : 'https://api.twitch.tv/helix/streams?after=$cursor'); @@ -175,10 +177,10 @@ class TwitchApi { } } - /// Returns a map with the given user's top 20 followed streams and a cursor for further requests. + /// Returns a [StreamsTwitch] object that contains the given user ID's top 20 followed streams and a cursor for further requests. Future getFollowedStreams({ required String id, - required Map? headers, + required Map headers, String? cursor, }) async { final url = Uri.parse(cursor == null @@ -194,10 +196,10 @@ class TwitchApi { } } - /// Returns the list of streams under the given game/category ID. + /// Returns a [StreamsTwitch] object that contains the list of streams under the given game/category ID. Future getStreamsUnderCategory({ required String gameId, - required Map? headers, + required Map headers, String? cursor, }) async { final url = Uri.parse( @@ -212,10 +214,10 @@ class TwitchApi { } } - /// Returns the stream info given the user login. + /// Returns a [StreamTwitch] object containing the stream info associated with the given [userLogin]. Future getStream({ required String userLogin, - required Map? headers, + required Map headers, }) async { final uri = Uri.parse('https://api.twitch.tv/helix/streams?user_login=$userLogin'); @@ -234,11 +236,11 @@ class TwitchApi { } } - /// Returns a user's info given their login name. + /// Returns a [UserTwitch] object containing the user info associated with the given [userLogin]. Future getUser({ String? userLogin, String? id, - required Map? headers, + required Map headers, }) async { final url = Uri.parse(id != null ? 'https://api.twitch.tv/helix/users?id=$id' : 'https://api.twitch.tv/helix/users?login=$userLogin'); @@ -258,10 +260,10 @@ class TwitchApi { } } - /// Returns a channels's info associated with the given ID. + /// Returns a [Channel] object containing a channels's info associated with the given [userId]. Future getChannel({ required String userId, - required Map? headers, + required Map headers, }) async { final url = Uri.parse('https://api.twitch.tv/helix/channels?broadcaster_id=$userId'); @@ -280,10 +282,10 @@ class TwitchApi { } } - /// Returns a list of channel query objects closest matching the given query string. + /// Returns a list of [ChannelQuery] objects closest matching the given [query]. Future> searchChannels({ required String query, - required Map? headers, + required Map headers, }) async { final url = Uri.parse('https://api.twitch.tv/helix/search/channels?first=8&query=$query'); @@ -297,9 +299,9 @@ class TwitchApi { } } - /// Returns the next top 20 categories/games and a cursor for further requests. + /// Returns a [CategoriesTwitch] object containing the next top 20 categories/games and a cursor for further requests. Future getTopCategories({ - required Map? headers, + required Map headers, String? cursor, }) async { final url = Uri.parse(cursor == null ? 'https://api.twitch.tv/helix/games/top' : 'https://api.twitch.tv/helix/games/top?after=$cursor'); @@ -313,8 +315,12 @@ class TwitchApi { } } - /// Returns up to 20 categories/games closest matching the [query] and a cursor for further requests. - Future searchCategories({required Map? headers, required String query, String? cursor}) async { + /// Returns a [CategoriesTwitch] containing up to 20 categories/games closest matching the [query] and a cursor for further requests. + Future searchCategories({ + required Map headers, + required String query, + String? cursor, + }) async { final url = Uri.parse(cursor == null ? 'https://api.twitch.tv/helix/search/categories?first=8&query=$query' : 'https://api.twitch.tv/helix/search/categories?first=8&query=$query&after=$cursor'); @@ -329,8 +335,11 @@ class TwitchApi { } } - /// Returns the sub count for a user. - Future getSubscriberCount({required String userId, required Map? headers}) async { + /// Returns the sub count associated with the given [userId]. + Future getSubscriberCount({ + required String userId, + required Map headers, + }) async { final uri = Uri.parse('https://api.twitch.tv/helix/subscriptions?broadcaster_id=$userId'); final response = await _client.get(uri, headers: headers); @@ -343,6 +352,7 @@ class TwitchApi { } } + /// Returns a [ChatUsers] object containing the names of chatters in the given [userLogin]'s chat. Future getChatters({required String userLogin}) async { final uri = Uri.parse('https://tmi.twitch.tv/group/user/$userLogin/chatters'); @@ -359,7 +369,7 @@ class TwitchApi { /// Returns a user's list of blocked users given their id. Future> getUserBlockedList({ required String id, - required Map? headers, + required Map headers, String? cursor, }) async { final url = Uri.parse(cursor == null diff --git a/lib/main.dart b/lib/main.dart index 60aabf4c..fd9c688c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -39,11 +39,13 @@ Future main() async { await SentryFlutter.init((options) => options.tracesSampleRate = sampleRate); } + /// Initialize API services with a common client. + /// This will prevent every request from creating a new client instance. final client = Client(); final twitchApiService = TwitchApi(client); final bttvApiService = BTTVApi(client); final ffzApiService = FFZApi(client); - final sevenTvApiService = SevenTVAPI(client); + final sevenTvApiService = SevenTVApi(client); // Create and initialize the authentication store final authStore = AuthStore(twitchApi: twitchApiService); @@ -57,7 +59,7 @@ Future main() async { Provider(create: (_) => twitchApiService), Provider(create: (_) => bttvApiService), Provider(create: (_) => ffzApiService), - Provider(create: (_) => sevenTvApiService), + Provider(create: (_) => sevenTvApiService), ], child: const MyApp(), ), diff --git a/lib/models/irc_message.dart b/lib/models/irc.dart similarity index 99% rename from lib/models/irc_message.dart rename to lib/models/irc.dart index a4bb8514..207c8369 100644 --- a/lib/models/irc_message.dart +++ b/lib/models/irc.dart @@ -83,10 +83,10 @@ class IRCMessage { required ChatAssetsStore assetsStore, required double badgeHeight, required double emoteHeight, + required bool isLightTheme, bool showMessage = true, bool useZeroWidth = false, bool useReadableColors = false, - bool? isLightTheme, TimestampType timestamp = TimestampType.disabled, }) { final emoteToObject = assetsStore.emoteToObject; @@ -267,9 +267,7 @@ class IRCMessage { ); // Add the colon separator between the username and their message to the span. - if (action == false) { - span.add(const TextSpan(text: ':')); - } + if (action == false) span.add(const TextSpan(text: ':')); // Italicize the text it was called with an IRC Action i.e., "/me". final textStyle = action == true ? const TextStyle(fontStyle: FontStyle.italic) : style; diff --git a/lib/screens/channel/chat/details/chat_modes.dart b/lib/screens/channel/chat/details/chat_modes.dart index 5f9d3f0e..d03686bd 100644 --- a/lib/screens/channel/chat/details/chat_modes.dart +++ b/lib/screens/channel/chat/details/chat_modes.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:frosty/models/irc_message.dart'; +import 'package:frosty/models/irc.dart'; class ChatModes extends StatelessWidget { final ROOMSTATE roomState; diff --git a/lib/screens/channel/chat/widgets/chat_message.dart b/lib/screens/channel/chat/widgets/chat_message.dart index df0d70fd..c8cc4851 100644 --- a/lib/screens/channel/chat/widgets/chat_message.dart +++ b/lib/screens/channel/chat/widgets/chat_message.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:frosty/models/irc_message.dart'; +import 'package:frosty/models/irc.dart'; import 'package:frosty/screens/channel/stores/chat_assets_store.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; diff --git a/lib/screens/channel/stores/chat_assets_store.dart b/lib/screens/channel/stores/chat_assets_store.dart index 2a05c3de..a6a8316a 100644 --- a/lib/screens/channel/stores/chat_assets_store.dart +++ b/lib/screens/channel/stores/chat_assets_store.dart @@ -14,7 +14,7 @@ abstract class _ChatAssetsStoreBase with Store { final TwitchApi twitchApi; final BTTVApi bttvApi; final FFZApi ffzApi; - final SevenTVAPI sevenTvApi; + final SevenTVApi sevenTvApi; /// Contains any custom FFZ mod and vip badges for the channel. RoomFFZ? ffzRoomInfo; diff --git a/lib/screens/channel/stores/chat_details_store.dart b/lib/screens/channel/stores/chat_details_store.dart index ff0b9d2f..90bdc286 100644 --- a/lib/screens/channel/stores/chat_details_store.dart +++ b/lib/screens/channel/stores/chat_details_store.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:frosty/api/twitch_api.dart'; import 'package:frosty/models/chatters.dart'; -import 'package:frosty/models/irc_message.dart'; +import 'package:frosty/models/irc.dart'; import 'package:mobx/mobx.dart'; part 'chat_details_store.g.dart'; diff --git a/lib/screens/channel/stores/chat_store.dart b/lib/screens/channel/stores/chat_store.dart index 3c4a1c7a..0521cdac 100644 --- a/lib/screens/channel/stores/chat_store.dart +++ b/lib/screens/channel/stores/chat_store.dart @@ -5,7 +5,7 @@ import 'package:flutter/scheduler.dart'; import 'package:frosty/core/auth/auth_store.dart'; import 'package:frosty/models/badges.dart'; import 'package:frosty/models/emotes.dart'; -import 'package:frosty/models/irc_message.dart'; +import 'package:frosty/models/irc.dart'; import 'package:frosty/screens/channel/stores/chat_assets_store.dart'; import 'package:frosty/screens/channel/stores/chat_details_store.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; diff --git a/lib/screens/channel/video_chat.dart b/lib/screens/channel/video_chat.dart index fceb2151..2a5a9b39 100644 --- a/lib/screens/channel/video_chat.dart +++ b/lib/screens/channel/video_chat.dart @@ -10,14 +10,9 @@ import 'package:frosty/screens/settings/settings.dart'; import 'package:provider/provider.dart'; class VideoChat extends StatefulWidget { - final String displayName; final ChatStore chatStore; - const VideoChat({ - Key? key, - required this.displayName, - required this.chatStore, - }) : super(key: key); + const VideoChat({Key? key, required this.chatStore}) : super(key: key); @override _VideoChatState createState() => _VideoChatState(); @@ -47,7 +42,7 @@ class _VideoChatState extends State { final appBar = AppBar( title: Text( - widget.displayName, + chatStore.displayName, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), actions: [ diff --git a/lib/screens/home/search/search_results_channels.dart b/lib/screens/home/search/search_results_channels.dart index 014fa066..098c2363 100644 --- a/lib/screens/home/search/search_results_channels.dart +++ b/lib/screens/home/search/search_results_channels.dart @@ -33,7 +33,6 @@ class SearchResultsChannels extends StatelessWidget { context, MaterialPageRoute( builder: (context) => VideoChat( - displayName: channelInfo.broadcasterName, chatStore: ChatStore( channelName: channelInfo.broadcasterLogin, channelId: channelInfo.broadcasterId, @@ -45,7 +44,7 @@ class SearchResultsChannels extends StatelessWidget { twitchApi: context.read(), ffzApi: context.read(), bttvApi: context.read(), - sevenTvApi: context.read(), + sevenTvApi: context.read(), ), auth: searchStore.authStore, settings: context.read(), @@ -110,7 +109,6 @@ class SearchResultsChannels extends StatelessWidget { context, MaterialPageRoute( builder: (context) => VideoChat( - displayName: channel.displayName, chatStore: ChatStore( channelName: channel.broadcasterLogin, channelId: channel.id, @@ -122,7 +120,7 @@ class SearchResultsChannels extends StatelessWidget { twitchApi: context.read(), ffzApi: context.read(), bttvApi: context.read(), - sevenTvApi: context.read(), + sevenTvApi: context.read(), ), auth: searchStore.authStore, settings: context.read(), diff --git a/lib/screens/home/widgets/stream_card.dart b/lib/screens/home/widgets/stream_card.dart index a19d25a6..3f9d1e19 100644 --- a/lib/screens/home/widgets/stream_card.dart +++ b/lib/screens/home/widgets/stream_card.dart @@ -41,7 +41,6 @@ class StreamCard extends StatelessWidget { context, MaterialPageRoute( builder: (context) => VideoChat( - displayName: streamInfo.userName, chatStore: ChatStore( channelName: streamInfo.userLogin, channelId: streamInfo.userId, @@ -55,7 +54,7 @@ class StreamCard extends StatelessWidget { twitchApi: context.read(), ffzApi: context.read(), bttvApi: context.read(), - sevenTvApi: context.read(), + sevenTvApi: context.read(), ), ), ),