Skip to content

Commit

Permalink
refactor(*): Migrate to explicit exceptions: part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
realth000 committed Aug 21, 2024
1 parent 348a06c commit c41d1b9
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 291 deletions.
10 changes: 10 additions & 0 deletions lib/exceptions/exceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,13 @@ final class LogoutFormHashNotFoundException extends AppException
@MappableClass()
final class LogoutFailedException extends AppException
with LogoutFailedExceptionMappable {}

/// Document contains chat data not found.
@MappableClass()
final class ChatDataDocumentNotFoundException extends AppException
with ChatDataDocumentNotFoundExceptionMappable {}

/// Failed to load emoji
@MappableClass()
final class EmojiLoadFailedException extends AppException
with EmojiLoadFailedExceptionMappable {}
21 changes: 8 additions & 13 deletions lib/features/chat/bloc/chat_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ import 'dart:async';
import 'package:collection/collection.dart';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tsdm_client/exceptions/exceptions.dart';
import 'package:tsdm_client/features/chat/exceptions/exceptions.dart';
import 'package:tsdm_client/features/chat/models/models.dart';
import 'package:tsdm_client/features/chat/repository/chat_repository.dart';
import 'package:tsdm_client/utils/logger.dart';
import 'package:universal_html/html.dart' as uh;

part 'chat_bloc.mapper.dart';
part 'chat_event.dart';

part 'chat_state.dart';

/// Emit
Expand All @@ -37,16 +34,14 @@ final class ChatBloc extends Bloc<ChatEvent, ChatState> with LoggerMixin {
_Emit emit,
) async {
emit(state.copyWith(status: ChatStatus.loading));
try {
final document = await _chatRepository.fetchChat(event.uid);
_updateState(document, emit);
} on HttpRequestFailedException catch (e) {
error('failed to fetch chat data: $e');
emit(state.copyWith(status: ChatStatus.failure));
} on ChatDataDocumentNotFoundException catch (e) {
error('failed to fetch chat data: $e');
emit(state.copyWith(status: ChatStatus.failure));
}

await await _chatRepository.fetchChat(event.uid).match(
(e) {
handle(e);
emit(state.copyWith(status: ChatStatus.failure));
},
(v) async => _updateState(v, emit),
).run();
}

void _updateState(uh.Document document, _Emit emit) {
Expand Down
23 changes: 12 additions & 11 deletions lib/features/chat/bloc/chat_history_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:tsdm_client/exceptions/exceptions.dart';
import 'package:tsdm_client/extensions/string.dart';
import 'package:tsdm_client/features/authentication/repository/models/models.dart';
import 'package:tsdm_client/features/chat/models/models.dart';
Expand Down Expand Up @@ -37,16 +36,18 @@ final class ChatHistoryBloc extends Bloc<ChatHistoryEvent, ChatHistoryState>
} else {
emit(state.copyWith(status: ChatHistoryStatus.loadingMore));
}
try {
final document = await _chatRepository.fetchChatHistory(
event.uid,
page: event.page,
);
await _updateState(document, emit, event.page);
} on HttpRequestFailedException catch (e) {
error('failed to fetch chat history: $e');
emit(state.copyWith(status: ChatHistoryStatus.failure));
}
await await _chatRepository
.fetchChatHistory(
event.uid,
page: event.page,
)
.match(
(e) {
handle(e);
emit(state.copyWith(status: ChatHistoryStatus.failure));
},
(v) async => _updateState(v, emit, event.page),
).run();
}

FutureOr<void> _updateState(
Expand Down
9 changes: 0 additions & 9 deletions lib/features/chat/exceptions/exceptions.dart

This file was deleted.

59 changes: 26 additions & 33 deletions lib/features/chat/repository/chat_repository.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'dart:io' if (dart.libaray.js) 'package:web/web.dart';

import 'package:fpdart/fpdart.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/exceptions/exceptions.dart';
import 'package:tsdm_client/features/chat/exceptions/exceptions.dart';
import 'package:tsdm_client/instance.dart';
import 'package:tsdm_client/shared/providers/net_client_provider/net_client_provider.dart';
import 'package:universal_html/html.dart' as uh;
Expand All @@ -14,38 +14,31 @@ final class ChatRepository {
const ChatRepository();

/// Fetch the chat history with user [uid].
///
/// # Exceptions
///
/// * **HttpRequestFailedException** if http request failed.
Future<uh.Document> fetchChatHistory(String uid, {int? page}) async {
final resp = await getIt.get<NetClientProvider>().get(
formatChatFullHistoryUrl(uid, page: page),
);
if (resp.statusCode != HttpStatus.ok) {
throw HttpRequestFailedException(resp.statusCode);
}
final document = parseHtmlDocument(resp.data as String);
return document;
}
AsyncEither<uh.Document> fetchChatHistory(String uid, {int? page}) =>
AsyncEither(() async {
final resp = await getIt.get<NetClientProvider>().get(
formatChatFullHistoryUrl(uid, page: page),
);
if (resp.statusCode != HttpStatus.ok) {
return left(HttpRequestFailedException(resp.statusCode));
}
final document = parseHtmlDocument(resp.data as String);
return right(document);
});

/// Fetch the chat history with user [uid].
///
/// # Exceptions
///
/// * **HttpRequestFailedException** if http request failed.
/// * **ChatDataDocumentNotFoundException** if chat html document not found.
Future<uh.Document> fetchChat(String uid) async {
final resp = await getIt.get<NetClientProvider>().get(formatChatUrl(uid));
if (resp.statusCode != HttpStatus.ok) {
throw HttpRequestFailedException(resp.statusCode);
}
final xmlDoc = parseXmlDocument(resp.data as String);
final htmlBodyData = xmlDoc.documentElement?.nodes.firstOrNull?.text;
if (htmlBodyData == null) {
throw ChatDataDocumentNotFoundException();
}
final document = parseHtmlDocument(htmlBodyData);
return document;
}
AsyncEither<uh.Document> fetchChat(String uid) => AsyncEither(() async {
final resp =
await getIt.get<NetClientProvider>().get(formatChatUrl(uid));
if (resp.statusCode != HttpStatus.ok) {
return left(HttpRequestFailedException(resp.statusCode));
}
final xmlDoc = parseXmlDocument(resp.data as String);
final htmlBodyData = xmlDoc.documentElement?.nodes.firstOrNull?.text;
if (htmlBodyData == null) {
return left(ChatDataDocumentNotFoundException());
}
final document = parseHtmlDocument(htmlBodyData);
return right(document);
});
}
17 changes: 8 additions & 9 deletions lib/features/editor/bloc/emoji_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:bloc/bloc.dart';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:tsdm_client/exceptions/exceptions.dart';
import 'package:tsdm_client/features/editor/exceptions/exceptions.dart';
import 'package:tsdm_client/features/editor/repository/editor_repository.dart';
import 'package:tsdm_client/shared/models/models.dart';
import 'package:tsdm_client/utils/logger.dart';
Expand Down Expand Up @@ -32,18 +31,18 @@ final class EmojiBloc extends Bloc<EmojiEvent, EmojiState> with LoggerMixin {
EmojiEmitter emit,
) async {
emit(state.copyWith(status: EmojiStatus.loading));
try {
await _editorRepository.loadEmojiFromCacheOrServer();
emit(
await _editorRepository.loadEmojiFromCacheOrServer().match(
(e) {
handle(e);
emit(state.copyWith(status: EmojiStatus.failure));
},
(v) => emit(
state.copyWith(
status: EmojiStatus.success,
emojiGroupList: _editorRepository.emojiGroupList,
),
);
} on EmojiRelatedException catch (e) {
error('failed to load emoji from cache: $e');
emit(state.copyWith(status: EmojiStatus.failure));
}
),
).run();
}

Future<void> _onEmojiFetchFromServerEvent(
Expand Down
14 changes: 0 additions & 14 deletions lib/features/editor/exceptions/exceptions.dart

This file was deleted.

34 changes: 16 additions & 18 deletions lib/features/editor/repository/editor_repository.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'dart:io' if (dart.libaray.js) 'package:web/web.dart';

import 'package:fpdart/fpdart.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/features/editor/exceptions/exceptions.dart';
import 'package:tsdm_client/exceptions/exceptions.dart';
import 'package:tsdm_client/instance.dart';
import 'package:tsdm_client/shared/models/models.dart';
import 'package:tsdm_client/shared/providers/image_cache_provider/image_cache_provider.dart';
Expand Down Expand Up @@ -234,21 +235,18 @@ final class EditorRepository with LoggerMixin {
/// Only load the emoji info, do not load the emoji image data.
///
/// Currently there there is no validation on emoji and emoji groups.
///
/// # Sealed Exceptions
///
/// * **[EmojiRelatedException]** when failed to load emoji.
Future<void> loadEmojiFromCacheOrServer() async {
final cacheProvider = getIt.get<ImageCacheProvider>();
if (await cacheProvider.validateEmojiCache()) {
// Have valid emoji cache.
emojiGroupList = await cacheProvider.loadEmojiInfo();
} else {
// Do not have valid emoji cache, reload from server.
final ret = await loadEmojiFromServer();
if (!ret) {
throw EmojiLoadFailedException();
}
}
}
AsyncVoidEither loadEmojiFromCacheOrServer() => AsyncVoidEither(() async {
final cacheProvider = getIt.get<ImageCacheProvider>();
if (await cacheProvider.validateEmojiCache()) {
// Have valid emoji cache.
emojiGroupList = await cacheProvider.loadEmojiInfo();
} else {
// Do not have valid emoji cache, reload from server.
final ret = await loadEmojiFromServer();
if (!ret) {
return left(EmojiLoadFailedException());
}
}
return rightVoid();
});
}
Loading

0 comments on commit c41d1b9

Please sign in to comment.