mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-14 01:58:29 +08:00
fix flickering image. (#343)
This commit is contained in:
@ -35,7 +35,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
|
||||
super(const StoriesState.init()) {
|
||||
on<LoadStories>(
|
||||
onLoadStories,
|
||||
transformer: sequential(),
|
||||
transformer: concurrent(),
|
||||
);
|
||||
on<StoriesInitialize>(onInitialize);
|
||||
on<StoriesRefresh>(onRefresh);
|
||||
|
@ -169,20 +169,26 @@ class FavCubit extends Cubit<FavState> {
|
||||
emit(FavState.init());
|
||||
}
|
||||
|
||||
Future<void> merge() async {
|
||||
Future<void> merge({required AppExceptionHandler onError}) async {
|
||||
if (_authBloc.state.isLoggedIn) {
|
||||
emit(state.copyWith(mergeStatus: Status.inProgress));
|
||||
try {
|
||||
final Iterable<int> ids = await _hackerNewsWebRepository.fetchFavorites(
|
||||
of: _authBloc.state.username,
|
||||
);
|
||||
final List<int> combinedIds = <int>[...ids, ...state.favIds];
|
||||
final LinkedHashSet<int> mergedIds = LinkedHashSet<int>.from(combinedIds);
|
||||
final LinkedHashSet<int> mergedIds =
|
||||
LinkedHashSet<int>.from(combinedIds);
|
||||
await _preferenceRepository.overwriteFav(
|
||||
username: username,
|
||||
ids: mergedIds,
|
||||
);
|
||||
emit(state.copyWith(mergeStatus: Status.success));
|
||||
refresh();
|
||||
} on RateLimitedException catch (e) {
|
||||
onError(e);
|
||||
emit(state.copyWith(mergeStatus: Status.failure));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,19 @@ extension ContextExtension on BuildContext {
|
||||
);
|
||||
}
|
||||
|
||||
void showErrorSnackBar() => showSnackBar(
|
||||
content: Constants.errorMessage,
|
||||
void showErrorSnackBar([String? message]) {
|
||||
ScaffoldMessenger.of(this).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Theme.of(this).colorScheme.errorContainer,
|
||||
content: Text(
|
||||
message ?? Constants.errorMessage,
|
||||
style: TextStyle(
|
||||
color: Theme.of(this).colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Rect? get rect {
|
||||
final RenderBox? box = findRenderObject() as RenderBox?;
|
||||
|
15
lib/models/app_exception.dart
Normal file
15
lib/models/app_exception.dart
Normal file
@ -0,0 +1,15 @@
|
||||
typedef AppExceptionHandler = void Function(AppException);
|
||||
|
||||
class AppException implements Exception {
|
||||
AppException({
|
||||
required this.message,
|
||||
this.stackTrace,
|
||||
});
|
||||
|
||||
final String message;
|
||||
final StackTrace? stackTrace;
|
||||
}
|
||||
|
||||
class RateLimitedException extends AppException {
|
||||
RateLimitedException() : super(message: 'Rate limited...');
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export 'app_exception.dart';
|
||||
export 'comments_order.dart';
|
||||
export 'discoverable_feature.dart';
|
||||
export 'export_destination.dart';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hacki/models/item/comment.dart';
|
||||
import 'package:hacki/config/constants.dart';
|
||||
import 'package:hacki/models/models.dart';
|
||||
import 'package:html/dom.dart' hide Comment;
|
||||
import 'package:html/parser.dart';
|
||||
import 'package:html_unescape/html_unescape.dart';
|
||||
@ -25,6 +26,14 @@ class HackerNewsWebRepository {
|
||||
'''$_favoritesBaseUrl$username${isComment ? '&comments=t' : ''}&p=$page''',
|
||||
);
|
||||
final Response response = await get(url);
|
||||
|
||||
if (response.body.contains('Sorry')) {
|
||||
throw RateLimitedException();
|
||||
}
|
||||
|
||||
/// Due to rate limiting, we have a short break here.
|
||||
await Future<void>.delayed(AppDurations.oneSecond);
|
||||
|
||||
final Document document = parse(response.body);
|
||||
final List<Element> elements = document.querySelectorAll(_aThingSelector);
|
||||
final Iterable<int> parsedIds = elements
|
||||
@ -45,6 +54,7 @@ class HackerNewsWebRepository {
|
||||
page++;
|
||||
}
|
||||
|
||||
page = 1;
|
||||
while (true) {
|
||||
ids = await fetchIds(page, isComment: true);
|
||||
if (ids.isEmpty) {
|
||||
|
@ -150,7 +150,11 @@ class _ProfileScreenState extends State<ProfileScreen>
|
||||
) =>
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.read<FavCubit>().merge();
|
||||
context.read<FavCubit>().merge(
|
||||
onError: (AppException e) {
|
||||
context.showErrorSnackBar(e.message);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: status == Status.inProgress
|
||||
? const SizedBox(
|
||||
|
@ -119,10 +119,14 @@ class LinkView extends StatelessWidget {
|
||||
: CachedNetworkImage(
|
||||
imageUrl: imageUri!,
|
||||
fit: isIcon ? BoxFit.scaleDown : BoxFit.fitWidth,
|
||||
memCacheHeight: layoutHeight.toInt() * 4,
|
||||
cacheKey: imageUri,
|
||||
errorWidget: (_, __, ___) => const Center(
|
||||
child: Text(r'¯\_(ツ)_/¯'),
|
||||
errorWidget: (_, __, ___) => Center(
|
||||
child: Text(
|
||||
r'¯\_(ツ)_/¯',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
Reference in New Issue
Block a user