Compare commits

..

4 Commits

Author SHA1 Message Date
381c99b353 fix crashing. (#248) 2023-09-08 09:07:48 -07:00
39ee3137f8 fix reply box in full screen. (#247) 2023-09-05 15:17:23 -07:00
0d76be8634 bump flutter version. (#243) 2023-08-22 06:54:59 -07:00
9986f72e11 improve shortcut buttons. (#242) 2023-07-19 21:09:24 -07:00
55 changed files with 413 additions and 556 deletions

View File

@ -9,13 +9,14 @@ on:
jobs: jobs:
releases: releases:
name: Check commit name: Check commit
runs-on: ubuntu-latest runs-on: macos-latest
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- name: checkout all the submodules - name: checkout all the submodules
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
fetch-depth: 0
- run: submodules/flutter/bin/flutter doctor - run: submodules/flutter/bin/flutter doctor
- run: submodules/flutter/bin/flutter pub get - run: submodules/flutter/bin/flutter pub get
- run: submodules/flutter/bin/dart format --set-exit-if-changed lib test integration_test - run: submodules/flutter/bin/dart format --set-exit-if-changed lib test integration_test

View File

@ -23,6 +23,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
fetch-depth: 0
- run: submodules/flutter/bin/flutter doctor - run: submodules/flutter/bin/flutter doctor
- run: submodules/flutter/bin/flutter pub get - run: submodules/flutter/bin/flutter pub get
- run: submodules/flutter/bin/dart format --set-exit-if-changed lib test integration_test - run: submodules/flutter/bin/dart format --set-exit-if-changed lib test integration_test

View File

@ -1,121 +0,0 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:in_app_review_platform_interface/method_channel_in_app_review.dart';
import 'package:platform/platform.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late MethodChannelInAppReview methodChannelInAppReview;
late List<MethodCall> log = <MethodCall>[];
const MethodChannel channel = MethodChannel('dev.britannio.in_app_review');
setUp(() {
methodChannelInAppReview = MethodChannelInAppReview();
methodChannelInAppReview.channel = channel;
log = <MethodCall>[];
});
tearDown(() {
log.clear();
});
group('isAvailable', () {
test(
'should invoke the isAvailable method channel',
() async {
// ACT
final bool result = await methodChannelInAppReview.isAvailable();
// ASSERT
expect(log, <Matcher>[isMethodCall('isAvailable', arguments: null)]);
expect(result, isTrue);
},
);
});
group('requestReview', () {
test(
'should invoke the requestReview method channel',
() async {
// ACT
await methodChannelInAppReview.requestReview();
// ASSERT
expect(log, <Matcher>[isMethodCall('requestReview', arguments: null)]);
},
);
});
group('openStoreListing', () {
test(
'should invoke the openStoreListing method channel on Android',
() async {
// ARRANGE
methodChannelInAppReview.platform =
FakePlatform(operatingSystem: 'android');
// ACT
await methodChannelInAppReview.openStoreListing();
// ASSERT
expect(
log,
<Matcher>[isMethodCall('openStoreListing', arguments: null)],
);
},
);
test(
'should invoke the openStoreListing method channel on iOS',
() async {
// ARRANGE
methodChannelInAppReview.platform =
FakePlatform(operatingSystem: 'ios');
final String appStoreId = "store_id";
// ACT
await methodChannelInAppReview.openStoreListing(appStoreId: appStoreId);
// ASSERT
expect(log,
<Matcher>[isMethodCall('openStoreListing', arguments: appStoreId)]);
},
);
test(
'should invoke the openStoreListing method channel on MacOS',
() async {
// ARRANGE
methodChannelInAppReview.platform =
FakePlatform(operatingSystem: 'macos');
final String appStoreId = "store_id";
// ACT
await methodChannelInAppReview.openStoreListing(appStoreId: appStoreId);
// ASSERT
expect(log,
<Matcher>[isMethodCall('openStoreListing', arguments: appStoreId)]);
},
);
test(
'should invoke the openStoreListing method channel on Windows',
() async {
// ARRANGE
methodChannelInAppReview.platform =
FakePlatform(operatingSystem: 'windows');
final String microsoftStoreId = 'store_id';
// ACT
await methodChannelInAppReview.openStoreListing(
microsoftStoreId: microsoftStoreId,
);
// ASSERT
expect(log, <Matcher>[
isMethodCall('openStoreListing', arguments: microsoftStoreId)
]);
},
skip:
'The windows uwp implementation still uses the url_launcher package',
);
});
}

View File

@ -151,12 +151,12 @@ SPEC CHECKSUMS:
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1 receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028 share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
synced_shared_preferences: f722742b06d65c7315b8e9f56b794c9fbd5597f7 synced_shared_preferences: f722742b06d65c7315b8e9f56b794c9fbd5597f7
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4

View File

@ -291,7 +291,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1330; LastSwiftUpdateCheck = 1330;
LastUpgradeCheck = 1300; LastUpgradeCheck = 1430;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1430"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -77,8 +77,10 @@
<key>UIApplicationSupportsIndirectInputEvents</key> <key>UIApplicationSupportsIndirectInputEvents</key>
<true/> <true/>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string> <string>This app needs camera access to scan QR codes</string>
<key>io.flutter.embedded_views_preview</key> <key>io.flutter.embedded_views_preview</key>
<true/> <true/>
<key>FLTEnableWideGamut</key>
<false/>
</dict> </dict>
</plist> </plist>

View File

@ -52,14 +52,14 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
state.copyWith( state.copyWith(
isLoggedIn: true, isLoggedIn: true,
user: user, user: user,
status: AuthStatus.loaded, status: Status.success,
), ),
); );
} else { } else {
emit( emit(
state.copyWith( state.copyWith(
isLoggedIn: false, isLoggedIn: false,
status: AuthStatus.loaded, status: Status.success,
), ),
); );
} }
@ -81,7 +81,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} }
Future<void> onLogin(AuthLogin event, Emitter<AuthState> emit) async { Future<void> onLogin(AuthLogin event, Emitter<AuthState> emit) async {
emit(state.copyWith(status: AuthStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final bool successful = await _authRepository.login( final bool successful = await _authRepository.login(
username: event.username, username: event.username,
@ -94,11 +94,11 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
state.copyWith( state.copyWith(
user: user ?? User.emptyWithId(event.username), user: user ?? User.emptyWithId(event.username),
isLoggedIn: true, isLoggedIn: true,
status: AuthStatus.loaded, status: Status.success,
), ),
); );
} else { } else {
emit(state.copyWith(status: AuthStatus.failure)); emit(state.copyWith(status: Status.failure));
} }
} }

View File

@ -1,11 +1,5 @@
part of 'auth_bloc.dart'; part of 'auth_bloc.dart';
enum AuthStatus {
loading,
loaded,
failure,
}
class AuthState extends Equatable { class AuthState extends Equatable {
const AuthState({ const AuthState({
required this.user, required this.user,
@ -17,13 +11,13 @@ class AuthState extends Equatable {
const AuthState.init() const AuthState.init()
: user = const User.empty(), : user = const User.empty(),
isLoggedIn = false, isLoggedIn = false,
status = AuthStatus.loaded, status = Status.success,
agreedToEULA = false; agreedToEULA = false;
final User user; final User user;
final bool isLoggedIn; final bool isLoggedIn;
final bool agreedToEULA; final bool agreedToEULA;
final AuthStatus status; final Status status;
String get username => user.id; String get username => user.id;
@ -31,7 +25,7 @@ class AuthState extends Equatable {
User? user, User? user,
bool? isLoggedIn, bool? isLoggedIn,
bool? agreedToEULA, bool? agreedToEULA,
AuthStatus? status, Status? status,
}) { }) {
return AuthState( return AuthState(
user: user ?? this.user, user: user ?? this.user,

View File

@ -79,7 +79,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
const StoriesState.init().copyWith( const StoriesState.init().copyWith(
isOfflineReading: hasCachedStories && isOfflineReading: hasCachedStories &&
// Only go into offline mode in the next session. // Only go into offline mode in the next session.
state.downloadStatus == StoriesDownloadStatus.initial, state.downloadStatus == StoriesDownloadStatus.idle,
currentPageSize: pageSize, currentPageSize: pageSize,
downloadStatus: state.downloadStatus, downloadStatus: state.downloadStatus,
storiesDownloaded: state.storiesDownloaded, storiesDownloaded: state.storiesDownloaded,
@ -133,12 +133,12 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
StoriesRefresh event, StoriesRefresh event,
Emitter<StoriesState> emit, Emitter<StoriesState> emit,
) async { ) async {
if (state.statusByType[event.type] == StoriesStatus.loading) return; if (state.statusByType[event.type] == Status.inProgress) return;
emit( emit(
state.copyWithStatusUpdated( state.copyWithStatusUpdated(
type: event.type, type: event.type,
to: StoriesStatus.loading, to: Status.inProgress,
), ),
); );
@ -146,7 +146,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
emit( emit(
state.copyWithStatusUpdated( state.copyWithStatusUpdated(
type: event.type, type: event.type,
to: StoriesStatus.loaded, to: Status.success,
), ),
); );
} else { } else {
@ -159,7 +159,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
emit( emit(
state.copyWithStatusUpdated( state.copyWithStatusUpdated(
type: event.type, type: event.type,
to: StoriesStatus.loading, to: Status.inProgress,
), ),
); );
@ -218,7 +218,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
emit( emit(
state.copyWithStatusUpdated( state.copyWithStatusUpdated(
type: event.type, type: event.type,
to: StoriesStatus.loaded, to: Status.success,
), ),
); );
} }
@ -245,7 +245,7 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
void onStoriesLoaded(StoriesLoaded event, Emitter<StoriesState> emit) { void onStoriesLoaded(StoriesLoaded event, Emitter<StoriesState> emit) {
emit( emit(
state.copyWithStatusUpdated(type: event.type, to: StoriesStatus.loaded), state.copyWithStatusUpdated(type: event.type, to: Status.success),
); );
} }

View File

@ -1,13 +1,7 @@
part of 'stories_bloc.dart'; part of 'stories_bloc.dart';
enum StoriesStatus {
initial,
loading,
loaded,
}
enum StoriesDownloadStatus { enum StoriesDownloadStatus {
initial, idle,
downloading, downloading,
finished, finished,
failure, failure,
@ -43,12 +37,12 @@ class StoriesState extends Equatable {
StoryType.ask: <int>[], StoryType.ask: <int>[],
StoryType.show: <int>[], StoryType.show: <int>[],
}, },
this.statusByType = const <StoryType, StoriesStatus>{ this.statusByType = const <StoryType, Status>{
StoryType.top: StoriesStatus.initial, StoryType.top: Status.idle,
StoryType.best: StoriesStatus.initial, StoryType.best: Status.idle,
StoryType.latest: StoriesStatus.initial, StoryType.latest: Status.idle,
StoryType.ask: StoriesStatus.initial, StoryType.ask: Status.idle,
StoryType.show: StoriesStatus.initial, StoryType.show: Status.idle,
}, },
this.currentPageByType = const <StoryType, int>{ this.currentPageByType = const <StoryType, int>{
StoryType.top: 0, StoryType.top: 0,
@ -58,7 +52,7 @@ class StoriesState extends Equatable {
StoryType.show: 0, StoryType.show: 0,
}, },
}) : isOfflineReading = false, }) : isOfflineReading = false,
downloadStatus = StoriesDownloadStatus.initial, downloadStatus = StoriesDownloadStatus.idle,
currentPageSize = 0, currentPageSize = 0,
readStoriesIds = const <int>{}, readStoriesIds = const <int>{},
storiesDownloaded = 0, storiesDownloaded = 0,
@ -66,7 +60,7 @@ class StoriesState extends Equatable {
final Map<StoryType, List<Story>> storiesByType; final Map<StoryType, List<Story>> storiesByType;
final Map<StoryType, List<int>> storyIdsByType; final Map<StoryType, List<int>> storyIdsByType;
final Map<StoryType, StoriesStatus> statusByType; final Map<StoryType, Status> statusByType;
final Map<StoryType, int> currentPageByType; final Map<StoryType, int> currentPageByType;
final Set<int> readStoriesIds; final Set<int> readStoriesIds;
final StoriesDownloadStatus downloadStatus; final StoriesDownloadStatus downloadStatus;
@ -78,7 +72,7 @@ class StoriesState extends Equatable {
StoriesState copyWith({ StoriesState copyWith({
Map<StoryType, List<Story>>? storiesByType, Map<StoryType, List<Story>>? storiesByType,
Map<StoryType, List<int>>? storyIdsByType, Map<StoryType, List<int>>? storyIdsByType,
Map<StoryType, StoriesStatus>? statusByType, Map<StoryType, Status>? statusByType,
Map<StoryType, int>? currentPageByType, Map<StoryType, int>? currentPageByType,
Set<int>? readStoriesIds, Set<int>? readStoriesIds,
StoriesDownloadStatus? downloadStatus, StoriesDownloadStatus? downloadStatus,
@ -133,10 +127,10 @@ class StoriesState extends Equatable {
StoriesState copyWithStatusUpdated({ StoriesState copyWithStatusUpdated({
required StoryType type, required StoryType type,
required StoriesStatus to, required Status to,
}) { }) {
final Map<StoryType, StoriesStatus> newMap = final Map<StoryType, Status> newMap =
Map<StoryType, StoriesStatus>.from(statusByType); Map<StoryType, Status>.from(statusByType);
newMap[type] = to; newMap[type] = to;
return copyWith( return copyWith(
statusByType: newMap, statusByType: newMap,
@ -162,9 +156,9 @@ class StoriesState extends Equatable {
final Map<StoryType, List<int>> newStoryIdsMap = final Map<StoryType, List<int>> newStoryIdsMap =
Map<StoryType, List<int>>.from(storyIdsByType); Map<StoryType, List<int>>.from(storyIdsByType);
newStoryIdsMap[type] = <int>[]; newStoryIdsMap[type] = <int>[];
final Map<StoryType, StoriesStatus> newStatusMap = final Map<StoryType, Status> newStatusMap =
Map<StoryType, StoriesStatus>.from(statusByType); Map<StoryType, Status>.from(statusByType);
newStatusMap[type] = StoriesStatus.loading; newStatusMap[type] = Status.inProgress;
final Map<StoryType, int> newCurrentPageMap = final Map<StoryType, int> newCurrentPageMap =
Map<StoryType, int>.from(currentPageByType); Map<StoryType, int>.from(currentPageByType);
newCurrentPageMap[type] = 0; newCurrentPageMap[type] = 0;

View File

@ -39,8 +39,9 @@ abstract class Constants {
static const String featureOpenStoryInWebView = 'open_story_in_web_view'; static const String featureOpenStoryInWebView = 'open_story_in_web_view';
static const String featureLogIn = 'log_in'; static const String featureLogIn = 'log_in';
static const String featurePinToTop = 'pin_to_top'; static const String featurePinToTop = 'pin_to_top';
static const String featureJumpUpButton = 'jump_up_button'; static const String featureJumpUpButton = 'jump_up_button_with_long_press';
static const String featureJumpDownButton = 'jump_down_button'; static const String featureJumpDownButton =
'jump_down_button_with_long_press';
static final String happyFace = <String>[ static final String happyFace = <String>[
'(๑•̀ㅂ•́)و✧', '(๑•̀ㅂ•́)و✧',

View File

@ -2,7 +2,7 @@ import 'package:logger/logger.dart';
class CustomLogFilter extends LogFilter { class CustomLogFilter extends LogFilter {
@override @override
Level? get level => Level.verbose; Level? get level => Level.trace;
/// The minimal level allowed in production. /// The minimal level allowed in production.
static const Level _minimalLevel = Level.info; static const Level _minimalLevel = Level.info;

View File

@ -20,7 +20,7 @@ class CustomFileOutput extends LogOutput {
IOSink? _sink; IOSink? _sink;
@override @override
void init() { Future<void> init() async {
_sink = file.openWrite( _sink = file.openWrite(
mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend, mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend,
encoding: encoding, encoding: encoding,

View File

@ -106,7 +106,7 @@ class CommentsCubit extends Cubit<CommentsState> {
emit( emit(
state.copyWith( state.copyWith(
status: CommentsStatus.loading, status: CommentsStatus.inProgress,
comments: <Comment>[], comments: <Comment>[],
currentPage: 0, currentPage: 0,
), ),
@ -150,7 +150,7 @@ class CommentsCubit extends Cubit<CommentsState> {
Future<void> refresh() async { Future<void> refresh() async {
emit( emit(
state.copyWith( state.copyWith(
status: CommentsStatus.loading, status: CommentsStatus.inProgress,
), ),
); );
@ -224,7 +224,7 @@ class CommentsCubit extends Cubit<CommentsState> {
void Function(Comment)? onCommentFetched, void Function(Comment)? onCommentFetched,
VoidCallback? onDone, VoidCallback? onDone,
}) { }) {
if (comment == null && state.status == CommentsStatus.loading) return; if (comment == null && state.status == CommentsStatus.inProgress) return;
switch (state.fetchMode) { switch (state.fetchMode) {
case FetchMode.lazy: case FetchMode.lazy:
@ -269,7 +269,7 @@ class CommentsCubit extends Cubit<CommentsState> {
_streamSubscriptions[comment.id] = streamSubscription; _streamSubscriptions[comment.id] = streamSubscription;
case FetchMode.eager: case FetchMode.eager:
if (_streamSubscription != null) { if (_streamSubscription != null) {
emit(state.copyWith(status: CommentsStatus.loading)); emit(state.copyWith(status: CommentsStatus.inProgress));
_streamSubscription _streamSubscription
?..resume() ?..resume()
..onData(onCommentFetched); ..onData(onCommentFetched);
@ -279,7 +279,7 @@ class CommentsCubit extends Cubit<CommentsState> {
Future<void> loadParentThread() async { Future<void> loadParentThread() async {
HapticFeedbackUtil.light(); HapticFeedbackUtil.light();
emit(state.copyWith(fetchParentStatus: CommentsStatus.loading)); emit(state.copyWith(fetchParentStatus: CommentsStatus.inProgress));
final Item? parent = final Item? parent =
await _storiesRepository.fetchItem(id: state.item.parent); await _storiesRepository.fetchItem(id: state.item.parent);
@ -301,7 +301,7 @@ class CommentsCubit extends Cubit<CommentsState> {
Future<void> loadRootThread() async { Future<void> loadRootThread() async {
HapticFeedbackUtil.light(); HapticFeedbackUtil.light();
emit(state.copyWith(fetchRootStatus: CommentsStatus.loading)); emit(state.copyWith(fetchRootStatus: CommentsStatus.inProgress));
final Story? parent = await _storiesRepository final Story? parent = await _storiesRepository
.fetchParentStory(id: state.item.id) .fetchParentStory(id: state.item.id)
.then(_toBuildableStory); .then(_toBuildableStory);
@ -349,8 +349,8 @@ class CommentsCubit extends Cubit<CommentsState> {
init(useCommentCache: true); init(useCommentCache: true);
} }
/// Jump to next root level comment. /// Scroll to next root level comment.
void jump( void scrollToNextRoot(
ItemScrollController itemScrollController, ItemScrollController itemScrollController,
ItemPositionsListener itemPositionsListener, ItemPositionsListener itemPositionsListener,
) { ) {
@ -387,8 +387,8 @@ class CommentsCubit extends Cubit<CommentsState> {
} }
} }
/// Jump to previous root level comment. /// Scroll to previous root level comment.
void jumpUp( void scrollToPreviousRoot(
ItemScrollController itemScrollController, ItemScrollController itemScrollController,
ItemPositionsListener itemPositionsListener, ItemPositionsListener itemPositionsListener,
) { ) {

View File

@ -1,11 +1,11 @@
part of 'comments_cubit.dart'; part of 'comments_cubit.dart';
enum CommentsStatus { enum CommentsStatus {
init, idle,
loading, inProgress,
loaded, loaded,
allLoaded, allLoaded,
failure, error,
} }
class CommentsState extends Equatable { class CommentsState extends Equatable {
@ -28,9 +28,9 @@ class CommentsState extends Equatable {
required this.fetchMode, required this.fetchMode,
required this.order, required this.order,
}) : comments = <Comment>[], }) : comments = <Comment>[],
status = CommentsStatus.init, status = CommentsStatus.idle,
fetchParentStatus = CommentsStatus.init, fetchParentStatus = CommentsStatus.idle,
fetchRootStatus = CommentsStatus.init, fetchRootStatus = CommentsStatus.idle,
onlyShowTargetComment = false, onlyShowTargetComment = false,
currentPage = 0; currentPage = 0;

View File

@ -51,7 +51,7 @@ class FavCubit extends Cubit<FavState> {
.onDone(() { .onDone(() {
emit( emit(
state.copyWith( state.copyWith(
status: FavStatus.loaded, status: Status.success,
), ),
); );
}); });
@ -107,7 +107,7 @@ class FavCubit extends Cubit<FavState> {
} }
void loadMore() { void loadMore() {
emit(state.copyWith(status: FavStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final int currentPage = state.currentPage; final int currentPage = state.currentPage;
final int len = state.favIds.length; final int len = state.favIds.length;
emit(state.copyWith(currentPage: currentPage + 1)); emit(state.copyWith(currentPage: currentPage + 1));
@ -128,10 +128,10 @@ class FavCubit extends Cubit<FavState> {
) )
.listen(_onItemLoaded) .listen(_onItemLoaded)
.onDone(() { .onDone(() {
emit(state.copyWith(status: FavStatus.loaded)); emit(state.copyWith(status: Status.success));
}); });
} else { } else {
emit(state.copyWith(status: FavStatus.loaded)); emit(state.copyWith(status: Status.success));
} }
} }
@ -140,7 +140,7 @@ class FavCubit extends Cubit<FavState> {
emit( emit(
state.copyWith( state.copyWith(
status: FavStatus.loading, status: Status.inProgress,
currentPage: 0, currentPage: 0,
favItems: <Item>[], favItems: <Item>[],
favIds: <int>[], favIds: <int>[],
@ -155,7 +155,7 @@ class FavCubit extends Cubit<FavState> {
) )
.listen(_onItemLoaded) .listen(_onItemLoaded)
.onDone(() { .onDone(() {
emit(state.copyWith(status: FavStatus.loaded)); emit(state.copyWith(status: Status.success));
}); });
}); });
} }

View File

@ -1,12 +1,5 @@
part of 'fav_cubit.dart'; part of 'fav_cubit.dart';
enum FavStatus {
init,
loading,
loaded,
failure,
}
class FavState extends Equatable { class FavState extends Equatable {
const FavState({ const FavState({
required this.favIds, required this.favIds,
@ -18,18 +11,18 @@ class FavState extends Equatable {
FavState.init() FavState.init()
: favIds = <int>[], : favIds = <int>[],
favItems = <Item>[], favItems = <Item>[],
status = FavStatus.init, status = Status.idle,
currentPage = 0; currentPage = 0;
final List<int> favIds; final List<int> favIds;
final List<Item> favItems; final List<Item> favItems;
final FavStatus status; final Status status;
final int currentPage; final int currentPage;
FavState copyWith({ FavState copyWith({
List<int>? favIds, List<int>? favIds,
List<Item>? favItems, List<Item>? favItems,
FavStatus? status, Status? status,
int? currentPage, int? currentPage,
}) { }) {
return FavState( return FavState(

View File

@ -54,7 +54,7 @@ class HistoryCubit extends Cubit<HistoryState> {
} }
void loadMore() { void loadMore() {
emit(state.copyWith(status: HistoryStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final int currentPage = state.currentPage; final int currentPage = state.currentPage;
final int len = state.submittedIds.length; final int len = state.submittedIds.length;
emit(state.copyWith(currentPage: currentPage + 1)); emit(state.copyWith(currentPage: currentPage + 1));
@ -75,10 +75,10 @@ class HistoryCubit extends Cubit<HistoryState> {
) )
.listen(_onItemLoaded) .listen(_onItemLoaded)
.onDone(() { .onDone(() {
emit(state.copyWith(status: HistoryStatus.loaded)); emit(state.copyWith(status: Status.success));
}); });
} else { } else {
emit(state.copyWith(status: HistoryStatus.loaded)); emit(state.copyWith(status: Status.success));
} }
} }
@ -86,7 +86,7 @@ class HistoryCubit extends Cubit<HistoryState> {
final String username = _authBloc.state.username; final String username = _authBloc.state.username;
emit( emit(
state.copyWith( state.copyWith(
status: HistoryStatus.loading, status: Status.inProgress,
currentPage: 0, currentPage: 0,
submittedIds: <int>[], submittedIds: <int>[],
submittedItems: <Item>[], submittedItems: <Item>[],
@ -107,7 +107,7 @@ class HistoryCubit extends Cubit<HistoryState> {
) )
.listen(_onItemLoaded) .listen(_onItemLoaded)
.onDone(() { .onDone(() {
emit(state.copyWith(status: HistoryStatus.loaded)); emit(state.copyWith(status: Status.success));
}); });
} }
}); });

View File

@ -1,12 +1,5 @@
part of 'history_cubit.dart'; part of 'history_cubit.dart';
enum HistoryStatus {
init,
loading,
loaded,
failure,
}
class HistoryState extends Equatable { class HistoryState extends Equatable {
const HistoryState({ const HistoryState({
required this.submittedIds, required this.submittedIds,
@ -18,18 +11,18 @@ class HistoryState extends Equatable {
HistoryState.init() HistoryState.init()
: submittedIds = <int>[], : submittedIds = <int>[],
submittedItems = <Item>[], submittedItems = <Item>[],
status = HistoryStatus.init, status = Status.idle,
currentPage = 0; currentPage = 0;
final List<int> submittedIds; final List<int> submittedIds;
final List<Item> submittedItems; final List<Item> submittedItems;
final HistoryStatus status; final Status status;
final int currentPage; final int currentPage;
HistoryState copyWith({ HistoryState copyWith({
List<int>? submittedIds, List<int>? submittedIds,
List<Item>? submittedItems, List<Item>? submittedItems,
HistoryStatus? status, Status? status,
int? currentPage, int? currentPage,
}) { }) {
return HistoryState( return HistoryState(

View File

@ -100,7 +100,7 @@ class NotificationCubit extends Cubit<NotificationState> {
void markAsRead(int id) { void markAsRead(int id) {
Future.doWhile(() { Future.doWhile(() {
if (state.status != NotificationStatus.loading) { if (state.status != Status.inProgress) {
if (state.unreadCommentsIds.contains(id)) { if (state.unreadCommentsIds.contains(id)) {
final List<int> updatedUnreadIds = <int>[...state.unreadCommentsIds] final List<int> updatedUnreadIds = <int>[...state.unreadCommentsIds]
..remove(id); ..remove(id);
@ -116,7 +116,7 @@ class NotificationCubit extends Cubit<NotificationState> {
void markAllAsRead() { void markAllAsRead() {
Future.doWhile(() { Future.doWhile(() {
if (state.status != NotificationStatus.loading) { if (state.status != Status.inProgress) {
emit(state.copyWith(unreadCommentsIds: <int>[])); emit(state.copyWith(unreadCommentsIds: <int>[]));
_preferenceRepository.updateUnreadCommentsIds(<int>[]); _preferenceRepository.updateUnreadCommentsIds(<int>[]);
return false; return false;
@ -131,7 +131,7 @@ class NotificationCubit extends Cubit<NotificationState> {
_preferenceCubit.state.notificationEnabled) { _preferenceCubit.state.notificationEnabled) {
emit( emit(
state.copyWith( state.copyWith(
status: NotificationStatus.loading, status: Status.inProgress,
), ),
); );
@ -141,14 +141,14 @@ class NotificationCubit extends Cubit<NotificationState> {
} else { } else {
emit( emit(
state.copyWith( state.copyWith(
status: NotificationStatus.loaded, status: Status.success,
), ),
); );
} }
} }
Future<void> loadMore() async { Future<void> loadMore() async {
emit(state.copyWith(status: NotificationStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final int currentPage = state.currentPage + 1; final int currentPage = state.currentPage + 1;
final int lower = currentPage * _pageSize + state.offset; final int lower = currentPage * _pageSize + state.offset;
@ -169,7 +169,7 @@ class NotificationCubit extends Cubit<NotificationState> {
emit( emit(
state.copyWith( state.copyWith(
status: NotificationStatus.loaded, status: Status.success,
currentPage: currentPage, currentPage: currentPage,
), ),
); );
@ -237,7 +237,7 @@ class NotificationCubit extends Cubit<NotificationState> {
} }
}).whenComplete( }).whenComplete(
() => emit( () => emit(
state.copyWith(status: NotificationStatus.loaded), state.copyWith(status: Status.success),
), ),
); );
} }

View File

@ -1,12 +1,5 @@
part of 'notification_cubit.dart'; part of 'notification_cubit.dart';
enum NotificationStatus {
initial,
loading,
loaded,
failure,
}
class NotificationState extends Equatable { class NotificationState extends Equatable {
const NotificationState({ const NotificationState({
required this.comments, required this.comments,
@ -23,14 +16,14 @@ class NotificationState extends Equatable {
allCommentsIds = <int>[], allCommentsIds = <int>[],
currentPage = 0, currentPage = 0,
offset = 0, offset = 0,
status = NotificationStatus.initial; status = Status.idle;
final List<Comment> comments; final List<Comment> comments;
final List<int> allCommentsIds; final List<int> allCommentsIds;
final List<int> unreadCommentsIds; final List<int> unreadCommentsIds;
final int currentPage; final int currentPage;
final int offset; final int offset;
final NotificationStatus status; final Status status;
NotificationState copyWith({ NotificationState copyWith({
List<Comment>? comments, List<Comment>? comments,
@ -38,7 +31,7 @@ class NotificationState extends Equatable {
List<int>? unreadCommentsIds, List<int>? unreadCommentsIds,
int? currentPage, int? currentPage,
int? offset, int? offset,
NotificationStatus? status, Status? status,
}) { }) {
return NotificationState( return NotificationState(
comments: comments ?? this.comments, comments: comments ?? this.comments,

View File

@ -27,7 +27,7 @@ class PinCubit extends Cubit<PinState> {
emit(state.copyWith(pinnedStoriesIds: ids)); emit(state.copyWith(pinnedStoriesIds: ids));
_storiesRepository.fetchStoriesStream(ids: ids).listen(_onStoryFetched); _storiesRepository.fetchStoriesStream(ids: ids).listen(_onStoryFetched);
}).whenComplete(() => emit(state.copyWith(status: Status.loaded))); }).whenComplete(() => emit(state.copyWith(status: Status.success)));
} }
void pinStory(Story story) { void pinStory(Story story) {
@ -53,7 +53,7 @@ class PinCubit extends Cubit<PinState> {
} }
void refresh() { void refresh() {
if (state.status == Status.loading) return; if (state.status.isLoading) return;
init(); init();
} }

View File

@ -27,7 +27,7 @@ class PollCubit extends Cubit<PollState> {
emit(PollState.init()); emit(PollState.init());
} }
emit(state.copyWith(status: PollStatus.loading)); emit(state.copyWith(status: Status.inProgress));
List<int> pollOptionsIds = _story.parts; List<int> pollOptionsIds = _story.parts;
@ -42,7 +42,7 @@ class PollCubit extends Cubit<PollState> {
// If pollOptionsIds is still empty, exit loading state. // If pollOptionsIds is still empty, exit loading state.
if (pollOptionsIds.isEmpty) { if (pollOptionsIds.isEmpty) {
emit(state.copyWith(status: PollStatus.loaded)); emit(state.copyWith(status: Status.success));
return; return;
} }
@ -72,7 +72,7 @@ class PollCubit extends Cubit<PollState> {
); );
} }
emit(state.copyWith(status: PollStatus.loaded)); emit(state.copyWith(status: Status.success));
} }
} }

View File

@ -1,12 +1,5 @@
part of 'poll_cubit.dart'; part of 'poll_cubit.dart';
enum PollStatus {
initial,
loading,
loaded,
failure,
}
class PollState extends Equatable { class PollState extends Equatable {
const PollState({ const PollState({
required this.totalVotes, required this.totalVotes,
@ -19,18 +12,18 @@ class PollState extends Equatable {
: totalVotes = 0, : totalVotes = 0,
selections = <int>{}, selections = <int>{},
pollOptions = <PollOption>[], pollOptions = <PollOption>[],
status = PollStatus.initial; status = Status.idle;
final int totalVotes; final int totalVotes;
final Set<int> selections; final Set<int> selections;
final List<PollOption> pollOptions; final List<PollOption> pollOptions;
final PollStatus status; final Status status;
PollState copyWith({ PollState copyWith({
int? totalVotes, int? totalVotes,
Set<int>? selections, Set<int>? selections,
List<PollOption>? pollOptions, List<PollOption>? pollOptions,
PollStatus? status, Status? status,
}) { }) {
return PollState( return PollState(
totalVotes: totalVotes ?? this.totalVotes, totalVotes: totalVotes ?? this.totalVotes,

View File

@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:hacki/config/locator.dart'; import 'package:hacki/config/locator.dart';
import 'package:hacki/models/models.dart';
import 'package:hacki/repositories/repositories.dart'; import 'package:hacki/repositories/repositories.dart';
part 'post_state.dart'; part 'post_state.dart';
@ -14,31 +15,31 @@ class PostCubit extends Cubit<PostState> {
final PostRepository _postRepository; final PostRepository _postRepository;
Future<void> post({required String text, required int to}) async { Future<void> post({required String text, required int to}) async {
emit(state.copyWith(status: PostStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final bool successful = await _postRepository.comment( final bool successful = await _postRepository.comment(
parentId: to, parentId: to,
text: text, text: text,
); );
if (successful) { if (successful) {
emit(state.copyWith(status: PostStatus.successful)); emit(state.copyWith(status: Status.success));
} else { } else {
emit(state.copyWith(status: PostStatus.failure)); emit(state.copyWith(status: Status.failure));
} }
} }
Future<void> edit({required String text, required int id}) async { Future<void> edit({required String text, required int id}) async {
emit(state.copyWith(status: PostStatus.loading)); emit(state.copyWith(status: Status.inProgress));
final bool successful = await _postRepository.edit(id: id, text: text); final bool successful = await _postRepository.edit(id: id, text: text);
if (successful) { if (successful) {
emit(state.copyWith(status: PostStatus.successful)); emit(state.copyWith(status: Status.success));
} else { } else {
emit(state.copyWith(status: PostStatus.failure)); emit(state.copyWith(status: Status.failure));
} }
} }
void reset() { void reset() {
emit(state.copyWith(status: PostStatus.init)); emit(state.copyWith(status: Status.idle));
} }
} }

View File

@ -1,20 +1,13 @@
part of 'post_cubit.dart'; part of 'post_cubit.dart';
enum PostStatus {
init,
loading,
successful,
failure,
}
class PostState extends Equatable { class PostState extends Equatable {
const PostState({required this.status}); const PostState({required this.status});
const PostState.init() : status = PostStatus.init; const PostState.init() : status = Status.idle;
final PostStatus status; final Status status;
PostState copyWith({PostStatus? status}) { PostState copyWith({Status? status}) {
return PostState( return PostState(
status: status ?? this.status, status: status ?? this.status,
); );

View File

@ -1,7 +1,7 @@
part of 'search_cubit.dart'; part of 'search_cubit.dart';
enum SearchStatus { enum SearchStatus {
initial, idle,
loading, loading,
loadingMore, loadingMore,
loaded, loaded,
@ -15,7 +15,7 @@ class SearchState extends Equatable {
}); });
SearchState.init() SearchState.init()
: status = SearchStatus.initial, : status = SearchStatus.idle,
results = <Item>[], results = <Item>[],
params = SearchParams.init(); params = SearchParams.init();

View File

@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:hacki/config/locator.dart'; import 'package:hacki/config/locator.dart';
import 'package:hacki/models/models.dart';
import 'package:hacki/repositories/post_repository.dart'; import 'package:hacki/repositories/post_repository.dart';
part 'submit_state.dart'; part 'submit_state.dart';
@ -25,7 +26,7 @@ class SubmitCubit extends Cubit<SubmitState> {
} }
void onSubmitTapped() { void onSubmitTapped() {
emit(state.copyWith(status: SubmitStatus.submitting)); emit(state.copyWith(status: Status.inProgress));
if (state.title?.isNotEmpty ?? false) { if (state.title?.isNotEmpty ?? false) {
_postRepository _postRepository
@ -35,9 +36,9 @@ class SubmitCubit extends Cubit<SubmitState> {
text: state.text, text: state.text,
) )
.then((bool successful) { .then((bool successful) {
emit(state.copyWith(status: SubmitStatus.submitted)); emit(state.copyWith(status: Status.success));
}).onError((Object? error, StackTrace stackTrace) { }).onError((Object? error, StackTrace stackTrace) {
emit(state.copyWith(status: SubmitStatus.failure)); emit(state.copyWith(status: Status.failure));
}); });
} }
} }

View File

@ -1,12 +1,5 @@
part of 'submit_cubit.dart'; part of 'submit_cubit.dart';
enum SubmitStatus {
initial,
submitting,
submitted,
failure,
}
class SubmitState extends Equatable { class SubmitState extends Equatable {
const SubmitState({ const SubmitState({
required this.title, required this.title,
@ -19,18 +12,18 @@ class SubmitState extends Equatable {
: title = null, : title = null,
url = null, url = null,
text = null, text = null,
status = SubmitStatus.initial; status = Status.idle;
final String? title; final String? title;
final String? url; final String? url;
final String? text; final String? text;
final SubmitStatus status; final Status status;
SubmitState copyWith({ SubmitState copyWith({
String? title, String? title,
String? url, String? url,
String? text, String? text,
SubmitStatus? status, Status? status,
}) { }) {
return SubmitState( return SubmitState(
title: title ?? this.title, title: title ?? this.title,

View File

@ -15,16 +15,16 @@ class UserCubit extends Cubit<UserState> {
final StoriesRepository _storiesRepository; final StoriesRepository _storiesRepository;
void init({required String userId}) { void init({required String userId}) {
emit(state.copyWith(status: UserStatus.loading)); emit(state.copyWith(status: Status.inProgress));
_storiesRepository.fetchUser(id: userId).then((User? user) { _storiesRepository.fetchUser(id: userId).then((User? user) {
emit( emit(
state.copyWith( state.copyWith(
user: user ?? User.emptyWithId(userId), user: user ?? User.emptyWithId(userId),
status: UserStatus.loaded, status: Status.success,
), ),
); );
}).onError((_, __) { }).onError((_, __) {
emit(state.copyWith(status: UserStatus.failure)); emit(state.copyWith(status: Status.failure));
return; return;
}); });
} }

View File

@ -1,12 +1,5 @@
part of 'user_cubit.dart'; part of 'user_cubit.dart';
enum UserStatus {
initial,
loading,
loaded,
failure,
}
class UserState extends Equatable { class UserState extends Equatable {
const UserState({ const UserState({
required this.user, required this.user,
@ -15,14 +8,14 @@ class UserState extends Equatable {
const UserState.init() const UserState.init()
: user = const User.empty(), : user = const User.empty(),
status = UserStatus.initial; status = Status.idle;
final User user; final User user;
final UserStatus status; final Status status;
UserState copyWith({ UserState copyWith({
User? user, User? user,
UserStatus? status, Status? status,
}) { }) {
return UserState( return UserState(
user: user ?? this.user, user: user ?? this.user,

View File

@ -6,7 +6,7 @@ enum Vote {
} }
enum VoteStatus { enum VoteStatus {
initial, idle,
canceled, canceled,
submitted, submitted,
failureBeHumble, failureBeHumble,
@ -24,7 +24,7 @@ class VoteState extends Equatable {
const VoteState.init({required this.item}) const VoteState.init({required this.item})
: vote = null, : vote = null,
status = VoteStatus.initial; status = VoteStatus.idle;
/// Null means user has not voted, /// Null means user has not voted,
/// True means user voted up, /// True means user voted up,

View File

@ -14,6 +14,10 @@ extension ObjectExtension on Object {
String identifier = '', String identifier = '',
StackTrace? stackTrace, StackTrace? stackTrace,
}) { }) {
locator.get<Logger>().e(identifier, this, stackTrace ?? StackTrace.current); locator.get<Logger>().e(
identifier,
error: this,
stackTrace: stackTrace ?? StackTrace.current,
);
} }
} }

View File

@ -58,8 +58,8 @@ Future<void> main({bool testing = false}) async {
FlutterError.onError = (FlutterErrorDetails details) { FlutterError.onError = (FlutterErrorDetails details) {
locator.get<Logger>().e( locator.get<Logger>().e(
details.summary, details.summary,
details.exceptionAsString(), error: details.exceptionAsString(),
details.stack, stackTrace: details.stack,
); );
}; };
@ -241,7 +241,7 @@ class HackiApp extends StatelessWidget {
create: (BuildContext context) => TabCubit( create: (BuildContext context) => TabCubit(
preferenceCubit: context.read<PreferenceCubit>(), preferenceCubit: context.read<PreferenceCubit>(),
)..init(), )..init(),
) ),
], ],
child: AdaptiveTheme( child: AdaptiveTheme(
light: ThemeData( light: ThemeData(
@ -289,7 +289,9 @@ class HackiApp extends StatelessWidget {
child: MaterialApp( child: MaterialApp(
title: 'Hacki', title: 'Hacki',
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: useTrueDark ? trueDarkTheme : theme, theme: (useTrueDark ? trueDarkTheme : theme).copyWith(
useMaterial3: false,
),
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
navigatorObservers: <NavigatorObserver>[ navigatorObservers: <NavigatorObserver>[
locator.get<RouteObserver<ModalRoute<dynamic>>>(), locator.get<RouteObserver<ModalRoute<dynamic>>>(),

View File

@ -1,6 +1,14 @@
enum Status { enum Status {
idle, idle,
loading, inProgress,
loaded, success,
error, failure,
}
extension StatusExtension on Status {
bool get isLoading => this == Status.inProgress;
bool get isSuccessful => this == Status.success;
bool get hasError => this == Status.failure;
} }

View File

@ -64,7 +64,7 @@ class PostableRepository {
validateStatus: validateStatus, validateStatus: validateStatus,
), ),
); );
} on DioError catch (e) { } on DioException catch (e) {
throw ServiceException(e.message); throw ServiceException(e.message);
} }
} }

View File

@ -213,7 +213,7 @@ class _ItemScreenState extends State<ItemScreen> with RouteAware {
listeners: <BlocListener<dynamic, dynamic>>[ listeners: <BlocListener<dynamic, dynamic>>[
BlocListener<PostCubit, PostState>( BlocListener<PostCubit, PostState>(
listener: (BuildContext context, PostState postState) { listener: (BuildContext context, PostState postState) {
if (postState.status == PostStatus.successful) { if (postState.status == Status.success) {
Navigator.popUntil( Navigator.popUntil(
context, context,
(Route<dynamic> route) => (Route<dynamic> route) =>
@ -228,7 +228,7 @@ class _ItemScreenState extends State<ItemScreen> with RouteAware {
showSnackBar(content: msg); showSnackBar(content: msg);
context.read<EditCubit>().onReplySubmittedSuccessfully(); context.read<EditCubit>().onReplySubmittedSuccessfully();
context.read<PostCubit>().reset(); context.read<PostCubit>().reset();
} else if (postState.status == PostStatus.failure) { } else if (postState.status == Status.failure) {
Navigator.popUntil( Navigator.popUntil(
context, context,
(Route<dynamic> route) => (Route<dynamic> route) =>
@ -355,6 +355,7 @@ class _ItemScreenState extends State<ItemScreen> with RouteAware {
showModalBottomSheet<void>( showModalBottomSheet<void>(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
enableDrag: false,
builder: (BuildContext context) { builder: (BuildContext context) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -370,7 +371,7 @@ class _ItemScreenState extends State<ItemScreen> with RouteAware {
), ),
SizedBox( SizedBox(
height: MediaQuery.of(context).viewInsets.bottom, height: MediaQuery.of(context).viewInsets.bottom,
) ),
], ],
); );
}, },

View File

@ -32,30 +32,32 @@ class CustomFloatingActionButton extends StatelessWidget {
Icons.keyboard_arrow_up, Icons.keyboard_arrow_up,
color: Palette.white, color: Palette.white,
), ),
title: const Text('Jump to previous root level comment.'), title: const Text('Shortcut'),
description: const Text( description: const Text(
'''Tapping on this button will take you to the previous off-screen root level comment.''', '''Tapping on this button will take you to the previous off-screen root level comment.\n\nLong press on it to jump to the very beginning of this thread.''',
), ),
child: FloatingActionButton.small( child: InkWell(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, onLongPress: () => itemScrollController.scrollTo(
index: 0,
duration: Durations.ms400,
),
child: FloatingActionButton.small(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
/// Randomly generated string as heroTag to prevent /// Randomly generated string as heroTag to prevent
/// default [FloatingActionButton] animation. /// default [FloatingActionButton] animation.
heroTag: UniqueKey().hashCode, heroTag: UniqueKey().hashCode,
onPressed: () { onPressed: () {
if (state.status == CommentsStatus.loading) return; HapticFeedbackUtil.selection();
context.read<CommentsCubit>().scrollToPreviousRoot(
HapticFeedbackUtil.selection(); itemScrollController,
context.read<CommentsCubit>().jumpUp( itemPositionsListener,
itemScrollController, );
itemPositionsListener, },
); child: Icon(
}, Icons.keyboard_arrow_up,
child: Icon( color: Theme.of(context).colorScheme.primary,
Icons.keyboard_arrow_up, ),
color: state.status == CommentsStatus.loading
? Palette.grey
: Theme.of(context).colorScheme.primary,
), ),
), ),
), ),
@ -65,29 +67,31 @@ class CustomFloatingActionButton extends StatelessWidget {
Icons.keyboard_arrow_down, Icons.keyboard_arrow_down,
color: Palette.white, color: Palette.white,
), ),
title: const Text('Jump to next root level comment.'), title: const Text('Shortcut'),
description: const Text( description: const Text(
'''Tapping on this button will take you to the next off-screen root level comment.''', '''Tapping on this button will take you to the next off-screen root level comment.\n\nLong press on it to jump to the end of this thread.''',
), ),
child: FloatingActionButton.small( child: InkWell(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, onLongPress: () => itemScrollController.scrollTo(
index: state.comments.length,
duration: Durations.ms400,
),
child: FloatingActionButton.small(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
/// Same as above. /// Same as above.
heroTag: UniqueKey().hashCode, heroTag: UniqueKey().hashCode,
onPressed: () { onPressed: () {
if (state.status == CommentsStatus.loading) return; HapticFeedbackUtil.selection();
context.read<CommentsCubit>().scrollToNextRoot(
HapticFeedbackUtil.selection(); itemScrollController,
context.read<CommentsCubit>().jump( itemPositionsListener,
itemScrollController, );
itemPositionsListener, },
); child: Icon(
}, Icons.keyboard_arrow_down,
child: Icon( color: Theme.of(context).colorScheme.primary,
Icons.keyboard_arrow_down, ),
color: state.status == CommentsStatus.loading
? Palette.grey
: Theme.of(context).colorScheme.primary,
), ),
), ),
), ),

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hacki/blocs/blocs.dart'; import 'package:hacki/blocs/blocs.dart';
import 'package:hacki/config/constants.dart'; import 'package:hacki/config/constants.dart';
import 'package:hacki/extensions/extensions.dart'; import 'package:hacki/extensions/extensions.dart';
import 'package:hacki/models/status.dart';
import 'package:hacki/screens/widgets/widgets.dart'; import 'package:hacki/screens/widgets/widgets.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
import 'package:hacki/utils/utils.dart'; import 'package:hacki/utils/utils.dart';
@ -32,7 +33,7 @@ class _LoginDialogState extends State<LoginDialog> {
builder: (BuildContext context, AuthState state) { builder: (BuildContext context, AuthState state) {
return SimpleDialog( return SimpleDialog(
children: <Widget>[ children: <Widget>[
if (state.status == AuthStatus.loading) if (state.status.isLoading)
const SizedBox( const SizedBox(
height: Dimens.pt36, height: Dimens.pt36,
width: Dimens.pt36, width: Dimens.pt36,
@ -82,7 +83,7 @@ class _LoginDialogState extends State<LoginDialog> {
const SizedBox( const SizedBox(
height: Dimens.pt16, height: Dimens.pt16,
), ),
if (state.status == AuthStatus.failure) if (state.status == Status.failure)
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: Dimens.pt18, left: Dimens.pt18,
@ -141,7 +142,7 @@ class _LoginDialogState extends State<LoginDialog> {
), ),
], ],
), ),
) ),
], ],
), ),
Padding( Padding(

View File

@ -159,7 +159,7 @@ class MainView extends StatelessWidget {
prev.status != current.status, prev.status != current.status,
builder: (BuildContext context, CommentsState state) { builder: (BuildContext context, CommentsState state) {
return AnimatedOpacity( return AnimatedOpacity(
opacity: state.status == CommentsStatus.loading opacity: state.status == CommentsStatus.inProgress
? NumSwitch.on ? NumSwitch.on
: NumSwitch.off, : NumSwitch.off,
duration: const Duration( duration: const Duration(
@ -417,27 +417,28 @@ class _ParentItemSection extends StatelessWidget {
width: _viewParentButtonWidth, width: _viewParentButtonWidth,
child: TextButton( child: TextButton(
onPressed: context.read<CommentsCubit>().loadParentThread, onPressed: context.read<CommentsCubit>().loadParentThread,
child: state.fetchParentStatus == CommentsStatus.loading child:
? const SizedBox( state.fetchParentStatus == CommentsStatus.inProgress
height: Dimens.pt12, ? const SizedBox(
width: Dimens.pt12, height: Dimens.pt12,
child: CustomCircularProgressIndicator( width: Dimens.pt12,
strokeWidth: Dimens.pt2, child: CustomCircularProgressIndicator(
), strokeWidth: Dimens.pt2,
) ),
: const Text( )
'View parent', : const Text(
style: TextStyle( 'View parent',
fontSize: TextDimens.pt13, style: TextStyle(
), fontSize: TextDimens.pt13,
), ),
),
), ),
), ),
SizedBox( SizedBox(
width: _viewRootButtonWidth, width: _viewRootButtonWidth,
child: TextButton( child: TextButton(
onPressed: context.read<CommentsCubit>().loadRootThread, onPressed: context.read<CommentsCubit>().loadRootThread,
child: state.fetchRootStatus == CommentsStatus.loading child: state.fetchRootStatus == CommentsStatus.inProgress
? const SizedBox( ? const SizedBox(
height: Dimens.pt12, height: Dimens.pt12,
width: Dimens.pt12, width: Dimens.pt12,

View File

@ -81,7 +81,7 @@ class MorePopupMenu extends StatelessWidget {
child: BlocBuilder<UserCubit, UserState>( child: BlocBuilder<UserCubit, UserState>(
builder: (BuildContext context, UserState state) { builder: (BuildContext context, UserState state) {
return Semantics( return Semantics(
excludeSemantics: state.status == UserStatus.loading, excludeSemantics: state.status == Status.inProgress,
child: ListTile( child: ListTile(
leading: const Icon( leading: const Icon(
Icons.account_circle, Icons.account_circle,
@ -285,7 +285,7 @@ class MorePopupMenu extends StatelessWidget {
child: SearchScreen( child: SearchScreen(
fromUserDialog: true, fromUserDialog: true,
), ),
) ),
], ],
), ),
), ),

View File

@ -25,7 +25,7 @@ class _PollViewState extends State<PollView> {
const SizedBox( const SizedBox(
height: Dimens.pt24, height: Dimens.pt24,
), ),
if (state.status == PollStatus.loading) ...<Widget>[ if (state.status == Status.inProgress) ...<Widget>[
const LinearProgressIndicator(), const LinearProgressIndicator(),
const SizedBox( const SizedBox(
height: Dimens.pt24, height: Dimens.pt24,
@ -134,7 +134,7 @@ class _PollViewState extends State<PollView> {
), ),
], ],
), ),
) ),
], ],
), ),
); );

View File

@ -5,7 +5,7 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:hacki/config/constants.dart'; import 'package:hacki/config/constants.dart';
import 'package:hacki/cubits/cubits.dart'; import 'package:hacki/cubits/cubits.dart';
import 'package:hacki/extensions/extensions.dart'; import 'package:hacki/extensions/extensions.dart';
import 'package:hacki/models/item/item.dart'; import 'package:hacki/models/models.dart';
import 'package:hacki/screens/screens.dart'; import 'package:hacki/screens/screens.dart';
import 'package:hacki/screens/widgets/widgets.dart'; import 'package:hacki/screens/widgets/widgets.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
@ -35,11 +35,12 @@ class _ReplyBoxState extends State<ReplyBox> {
bool expanded = false; bool expanded = false;
double? expandedHeight; double? expandedHeight;
static const double _collapsedHeight = 100; static const double collapsedHeight = 140;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
expandedHeight ??= MediaQuery.of(context).size.height; expandedHeight ??= MediaQuery.of(context).size.height -
MediaQuery.of(context).viewInsets.bottom;
return BlocBuilder<EditCubit, EditState>( return BlocBuilder<EditCubit, EditState>(
buildWhen: (EditState previous, EditState current) => buildWhen: (EditState previous, EditState current) =>
previous.showReplyBox != current.showReplyBox || previous.showReplyBox != current.showReplyBox ||
@ -49,7 +50,7 @@ class _ReplyBoxState extends State<ReplyBox> {
return BlocBuilder<PostCubit, PostState>( return BlocBuilder<PostCubit, PostState>(
builder: (BuildContext context, PostState postState) { builder: (BuildContext context, PostState postState) {
final Item? replyingTo = editState.replyingTo; final Item? replyingTo = editState.replyingTo;
final bool isLoading = postState.status == PostStatus.loading; final bool isLoading = postState.status.isLoading;
return Padding( return Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@ -60,7 +61,7 @@ class _ReplyBoxState extends State<ReplyBox> {
: Dimens.zero, : Dimens.zero,
), ),
child: AnimatedContainer( child: AnimatedContainer(
height: expanded ? expandedHeight : _collapsedHeight, height: expanded ? expandedHeight : collapsedHeight,
duration: Durations.ms200, duration: Durations.ms200,
decoration: BoxDecoration( decoration: BoxDecoration(
boxShadow: <BoxShadow>[ boxShadow: <BoxShadow>[
@ -73,6 +74,7 @@ class _ReplyBoxState extends State<ReplyBox> {
), ),
child: Material( child: Material(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
if (context.read<SplitViewCubit>().state.enabled) if (context.read<SplitViewCubit>().state.enabled)
const Divider( const Divider(
@ -213,13 +215,21 @@ class _ReplyBoxState extends State<ReplyBox> {
), ),
Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: EdgeInsets.only(
horizontal: Dimens.pt16, left: Dimens.pt16,
right: Dimens.pt16,
bottom: expanded
// This padding here prevents keyboard
// overlapping with TextField.
? MediaQuery.of(context).viewInsets.bottom +
Dimens.pt16
: Dimens.zero,
), ),
child: TextField( child: TextField(
autofocus: true,
controller: widget.textEditingController, controller: widget.textEditingController,
maxLines: 100, autofocus: true,
expands: true,
maxLines: null,
decoration: const InputDecoration( decoration: const InputDecoration(
alignLabelWithHint: true, alignLabelWithHint: true,
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,

View File

@ -53,7 +53,7 @@ class _ProfileScreenState extends State<ProfileScreen>
previous.status != current.status, previous.status != current.status,
listener: listener:
(BuildContext context, NotificationState notificationState) { (BuildContext context, NotificationState notificationState) {
if (notificationState.status == NotificationStatus.loaded) { if (notificationState.status == Status.success) {
refreshControllerNotification refreshControllerNotification
..refreshCompleted() ..refreshCompleted()
..loadComplete(); ..loadComplete();
@ -71,7 +71,7 @@ class _ProfileScreenState extends State<ProfileScreen>
BuildContext context, BuildContext context,
HistoryState historyState, HistoryState historyState,
) { ) {
if (historyState.status == HistoryStatus.loaded) { if (historyState.status == Status.success) {
refreshControllerHistory refreshControllerHistory
..refreshCompleted() ..refreshCompleted()
..loadComplete(); ..loadComplete();
@ -83,7 +83,7 @@ class _ProfileScreenState extends State<ProfileScreen>
) { ) {
if ((!authState.isLoggedIn || if ((!authState.isLoggedIn ||
historyState.submittedItems.isEmpty) && historyState.submittedItems.isEmpty) &&
historyState.status != HistoryStatus.loading) { historyState.status != Status.inProgress) {
return const CenteredMessageView( return const CenteredMessageView(
content: 'Your past comments and stories will ' content: 'Your past comments and stories will '
'show up here.', 'show up here.',
@ -126,7 +126,7 @@ class _ProfileScreenState extends State<ProfileScreen>
visible: pageType == PageType.fav, visible: pageType == PageType.fav,
child: BlocConsumer<FavCubit, FavState>( child: BlocConsumer<FavCubit, FavState>(
listener: (BuildContext context, FavState favState) { listener: (BuildContext context, FavState favState) {
if (favState.status == FavStatus.loaded) { if (favState.status == Status.success) {
refreshControllerFav refreshControllerFav
..refreshCompleted() ..refreshCompleted()
..loadComplete(); ..loadComplete();
@ -134,7 +134,7 @@ class _ProfileScreenState extends State<ProfileScreen>
}, },
builder: (BuildContext context, FavState favState) { builder: (BuildContext context, FavState favState) {
if (favState.favItems.isEmpty && if (favState.favItems.isEmpty &&
favState.status != FavStatus.loading) { favState.status != Status.inProgress) {
return const CenteredMessageView( return const CenteredMessageView(
content: 'Your favorite stories will show up here.' content: 'Your favorite stories will show up here.'
'\nThey will be synced to your Hacker ' '\nThey will be synced to your Hacker '
@ -363,7 +363,7 @@ class _ProfileScreenState extends State<ProfileScreen>
? <Comment>[comment] ? <Comment>[comment]
: <Comment>[ : <Comment>[
...children, ...children,
comment.copyWith(level: children.length) comment.copyWith(level: children.length),
], ],
onlyShowTargetComment: true, onlyShowTargetComment: true,
), ),

View File

@ -361,7 +361,7 @@ class _SettingsState extends State<Settings> {
), ),
Spacer(), Spacer(),
], ],
) ),
], ],
), ),
); );

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hacki/cubits/cubits.dart'; import 'package:hacki/cubits/cubits.dart';
import 'package:hacki/extensions/extensions.dart'; import 'package:hacki/extensions/extensions.dart';
import 'package:hacki/models/models.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
import 'package:hacki/utils/utils.dart'; import 'package:hacki/utils/utils.dart';
@ -43,13 +44,13 @@ class _SubmitScreenState extends State<SubmitScreen> {
listenWhen: (SubmitState previous, SubmitState current) => listenWhen: (SubmitState previous, SubmitState current) =>
previous.status != current.status, previous.status != current.status,
listener: (BuildContext context, SubmitState state) { listener: (BuildContext context, SubmitState state) {
if (state.status == SubmitStatus.submitted) { if (state.status == Status.success) {
Navigator.pop(context); Navigator.pop(context);
HapticFeedbackUtil.light(); HapticFeedbackUtil.light();
showSnackBar( showSnackBar(
content: 'Post submitted successfully.', content: 'Post submitted successfully.',
); );
} else if (state.status == SubmitStatus.failure) { } else if (state.status == Status.failure) {
showErrorSnackBar(); showErrorSnackBar();
} }
}, },
@ -95,7 +96,7 @@ class _SubmitScreenState extends State<SubmitScreen> {
'Submit', 'Submit',
), ),
actions: <Widget>[ actions: <Widget>[
if (state.status == SubmitStatus.submitting) if (state.status == Status.inProgress)
const Padding( const Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: Dimens.pt18, vertical: Dimens.pt18,

View File

@ -49,7 +49,7 @@ class _StoriesListViewState extends State<StoriesListView> {
previous.statusByType[storyType] != previous.statusByType[storyType] !=
current.statusByType[storyType], current.statusByType[storyType],
listener: (BuildContext context, StoriesState state) { listener: (BuildContext context, StoriesState state) {
if (state.statusByType[storyType] == StoriesStatus.loaded) { if (state.statusByType[storyType] == Status.success) {
refreshController refreshController
..refreshCompleted(resetFooterState: true) ..refreshCompleted(resetFooterState: true)
..loadComplete(); ..loadComplete();

View File

@ -229,7 +229,7 @@ class _LinkPreviewPlaceholder extends StatelessWidget {
], ],
), ),
), ),
) ),
], ],
), ),
), ),

View File

@ -273,7 +273,7 @@ class WebAnalyzer {
info.title, info.title,
info.description, info.description,
info.icon, info.icon,
info.image info.image,
]; ];
} else if (info is WebVideoInfo) { } else if (info is WebVideoInfo) {
return <dynamic>['1', info.image]; return <dynamic>['1', info.image];

View File

@ -26,8 +26,8 @@ abstract class HtmlUtil {
.querySelectorAll("input[type='hidden']"); .querySelectorAll("input[type='hidden']");
return <String, String>{ return <String, String>{
if (hiddenInputs != null) if (hiddenInputs != null)
for (dom.Element hiddenInput in hiddenInputs) for (final dom.Element hiddenInput in hiddenInputs)
hiddenInput.attributes['name']!: hiddenInput.attributes['value']! hiddenInput.attributes['name']!: hiddenInput.attributes['value']!,
}; };
} }

View File

@ -5,34 +5,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07" sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "60.0.0" version: "61.0.0"
adaptive_theme: adaptive_theme:
dependency: "direct main" dependency: "direct main"
description: description:
name: adaptive_theme name: adaptive_theme
sha256: "3568bb526d4823c7bb35f9ce3604af15e04cc0e9cc4f257da3604fe6b48d74ae" sha256: "2d9bfee4240cdfad1b169cb43ac38fb49487e7fe1cc845e2973d4cef1780c0f6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.3.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3" sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.12.0" version: "5.13.0"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.2"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -53,18 +53,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: bloc name: bloc
sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80" sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.1" version: "8.1.2"
bloc_test: bloc_test:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: bloc_test name: bloc_test
sha256: ffbb60c17ee3d8e3784cb78071088e353199057233665541e8ac6cd438dca8ad sha256: af0de1a1e16a7536e95dcd7491e0a6d6078e11d2d691988e862280b74f5c7968
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.1" version: "9.1.4"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -125,18 +125,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: collection name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.1" version: "1.17.2"
connectivity_plus: connectivity_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: connectivity_plus name: connectivity_plus
sha256: "45262924896ff72a8cd92b722bb7e3d5020f9e0724531a3e10e22ddae2005991" sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.2"
connectivity_plus_platform_interface: connectivity_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -181,10 +181,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: csslib name: csslib
sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.17.2" version: "1.0.0"
dbus: dbus:
dependency: transitive dependency: transitive
description: description:
@ -197,10 +197,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "9b1a0c32b2a503f8fe9f8764fac7b5fcd4f6bd35d8f49de5350bccf9e2a33b8a" sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.0.0" version: "9.0.3"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -221,10 +221,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dio name: dio
sha256: "347d56c26d63519552ef9a569f2a593dda99a81fdbdff13c584b7197cfe05059" sha256: ce75a1b40947fea0a0e16ce73337122a86762e38b982e1ccb909daa3b9bc4197
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.2" version: "5.3.2"
equatable: equatable:
dependency: "direct main" dependency: "direct main"
description: description:
@ -262,10 +262,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.1.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -283,10 +283,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_bloc name: flutter_bloc
sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775" sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.2" version: "8.1.3"
flutter_blurhash: flutter_blurhash:
dependency: transitive dependency: transitive
description: description:
@ -299,10 +299,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_cache_manager name: flutter_cache_manager
sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.3.0" version: "3.3.1"
flutter_driver: flutter_driver:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -312,10 +312,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_email_sender name: flutter_email_sender
sha256: "9e253c69617f43d4cb5de672e93a7a19c12a21fb6a75e66c6ce7626336c4c1bc" sha256: "52b713a67a966be4d9e6f68a323fc0a5bc2da71c567eb451af1aa90d30adbc3a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.2.0" version: "6.0.1"
flutter_fadein: flutter_fadein:
dependency: "direct main" dependency: "direct main"
description: description:
@ -344,10 +344,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_local_notifications name: flutter_local_notifications
sha256: "20c92629902b125cb624efdbacbbe98806b3c0b01adb3d84d1c72198b3eafb1a" sha256: "3cc40fe8c50ab8383f3e053a499f00f975636622ecdc8e20a77418ece3b1e975"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.0.1" version: "15.1.0+1"
flutter_local_notifications_linux: flutter_local_notifications_linux:
dependency: transitive dependency: transitive
description: description:
@ -442,10 +442,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: font_awesome_flutter name: font_awesome_flutter
sha256: "959ef4add147753f990b4a7c6cccb746d5792dbdc81b1cde99e62e7edb31b206" sha256: "5fb789145cae1f4c3245c58b3f8fb287d055c26323879eab57a7bf0cfd1e45f3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.4.0" version: "10.5.0"
frontend_server_client: frontend_server_client:
dependency: transitive dependency: transitive
description: description:
@ -479,10 +479,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
hive: hive:
dependency: "direct main" dependency: "direct main"
description: description:
@ -495,10 +495,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: html name: html
sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.3" version: "0.15.4"
html_unescape: html_unescape:
dependency: "direct main" dependency: "direct main"
description: description:
@ -511,10 +511,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.6" version: "1.1.0"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
@ -535,10 +535,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: hydrated_bloc name: hydrated_bloc
sha256: eb92d88061b6b911c48779b08a91c8a9f3a3aa8475f80d9380045375d9876536 sha256: "24994e61f64904d911683cce1a31dc4ef611619da5253f1de2b7b8fc6f79a118"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.0" version: "9.1.2"
in_app_review: in_app_review:
dependency: "direct main" dependency: "direct main"
description: description:
@ -595,34 +595,34 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: logger name: logger
sha256: db2ff852ed77090ba9f62d3611e4208a3d11dfa35991a81ae724c113fcb3e3f7 sha256: "66cb048220ca51cf9011da69fa581e4ee2bed4be6e82870d9e9baae75739da49"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "2.0.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.15" version: "0.12.16"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "0.5.0"
memoize: memoize:
dependency: "direct main" dependency: "direct main"
description: description:
@ -651,10 +651,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mocktail name: mocktail
sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" sha256: "9503969a7c2c78c7292022c70c0289ed6241df7a9ba720010c0b215af29a5a58"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.0" version: "1.0.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
@ -699,10 +699,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: d39e8fbff4c5aef4592737e25ad6ac500df006ce7a7a8e1f838ce1256e167542 sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.1.0"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -723,58 +723,50 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.15" version: "2.1.0"
path_provider_android: path_provider_android:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider_android name: path_provider_android
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.27" version: "2.1.0"
path_provider_foundation: path_provider_foundation:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.3.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.10" version: "2.2.0"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.6" version: "2.1.0"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.6" version: "2.2.0"
pedantic:
dependency: transitive
description:
name: pedantic
sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
@ -795,10 +787,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: plugin_platform_interface name: plugin_platform_interface
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.5"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -900,82 +892,82 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: sembast name: sembast
sha256: a784dbcf313ff38a7f57249694c64a6bcf79f704dbec127958459a7737716830 sha256: "85ff944434f7b566fdc388be4f85b23e954736b7d6e51f965f4f419d966c15b1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.4" version: "3.5.0+1"
share_plus: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: "322a1ec9d9fe07e2e2252c098ce93d12dbd06133cc4c00ffe6a4ef505c295c17" sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.0" version: "7.1.0"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981" sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.3.0"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.2.0"
shared_preferences_android: shared_preferences_android:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
shared_preferences_foundation: shared_preferences_foundation:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.3.3"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.0"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.0"
shared_preferences_web: shared_preferences_web:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.2.0"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.0"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
@ -1012,10 +1004,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shimmer name: shimmer
sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "3.0.0"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -1041,26 +1033,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.10.0"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
name: sqflite name: sqflite
sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.8+4" version: "2.3.0"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.5" version: "2.5.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -1120,26 +1112,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test name: test
sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.24.1" version: "1.24.3"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.6.0"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.5.3"
timezone: timezone:
dependency: transitive dependency: transitive
description: description:
@ -1168,18 +1160,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: url_launcher name: url_launcher
sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.11" version: "6.1.12"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87" sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.34" version: "6.0.38"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
@ -1200,34 +1192,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.6"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_platform_interface name: url_launcher_platform_interface
sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
url_launcher_web: url_launcher_web:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.16" version: "2.0.18"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.6" version: "3.0.7"
uuid: uuid:
dependency: transitive dependency: transitive
description: description:
@ -1248,18 +1240,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: very_good_analysis name: very_good_analysis
sha256: "5f77d7c00d6010d8ad93ac5d91ecc851c216bcc1e7a51e56c3c01b27152453bb" sha256: "5e4ea72d2a9188630f0dd8f120a541de730090ef8863243fedca8267a84508b8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "5.0.0+1"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: f6deed8ed625c52864792459709183da231ebf66ff0cf09e69b573227c377efe sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.3.0" version: "11.7.1"
wakelock: wakelock:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1308,6 +1300,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@ -1336,42 +1336,42 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: webview_flutter name: webview_flutter
sha256: "1a37bdbaaf5fbe09ad8579ab09ecfd473284ce482f900b5aea27cf834386a567" sha256: "789d52bd789373cc1e100fb634af2127e86c99cf9abde09499743270c5de8d00"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.0" version: "4.2.2"
webview_flutter_android: webview_flutter_android:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "1acea8def62592123e2fbbca164ed8681a98a890bdcbb88f916d5b4a22687759" sha256: bca797abba472868655b5f1a6029c1132385685ee9db4713cb0e7f33076210c6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.7.0" version: "3.9.3"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_platform_interface name: webview_flutter_platform_interface
sha256: "78715dc442b7849dbde74e92bb67de1cecf5addf95531c5fb474e72f5fe9a507" sha256: "0ca3cfcc6781a7de701d580917af4a9efc4e3e129f8ead95a80587f0a749480a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.5.0"
webview_flutter_wkwebview: webview_flutter_wkwebview:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: "4646bb68297803bdbb96d46853e8fcb560d6cb5e04153fa64581535767875dfe" sha256: ed749f94ac9e814d04a258a9255cf69cfa4cc6006ff59542aea7fb4590144972
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.3" version: "3.7.3"
win32: win32:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
name: win32 name: win32
sha256: "6ca3aaab1790eeb1f5cad232e33d9c53ba66e884dd3e7686c4e730bffc45f1a3" sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.2" version: "5.0.6"
win32_registry: win32_registry:
dependency: transitive dependency: transitive
description: description:
@ -1392,10 +1392,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0+3" version: "1.0.2"
xml: xml:
dependency: transitive dependency: transitive
description: description:
@ -1413,5 +1413,5 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.10.5" flutter: ">=3.13.2"

View File

@ -1,11 +1,11 @@
name: hacki name: hacki
description: A Hacker News reader. description: A Hacker News reader.
version: 1.8.1+117 version: 1.8.4+120
publish_to: none publish_to: none
environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"
flutter: "3.10.5" flutter: "3.13.2"
dependencies: dependencies:
adaptive_theme: ^3.2.0 adaptive_theme: ^3.2.0
@ -27,11 +27,11 @@ dependencies:
sdk: flutter sdk: flutter
flutter_bloc: ^8.1.2 flutter_bloc: ^8.1.2
flutter_cache_manager: ^3.3.0 flutter_cache_manager: ^3.3.0
flutter_email_sender: ^5.2.0 flutter_email_sender: ^6.0.1
flutter_fadein: ^2.0.0 flutter_fadein: ^2.0.0
flutter_feather_icons: 2.0.0+1 flutter_feather_icons: 2.0.0+1
flutter_inappwebview: ^5.7.2+3 flutter_inappwebview: ^5.7.2+3
flutter_local_notifications: ^14.0.1 flutter_local_notifications: ^15.1.0+1
flutter_secure_storage: ^8.0.0 flutter_secure_storage: ^8.0.0
flutter_siri_suggestions: ^2.1.0 flutter_siri_suggestions: ^2.1.0
flutter_slidable: ^3.0.0 flutter_slidable: ^3.0.0
@ -41,13 +41,13 @@ dependencies:
hive: ^2.2.3 hive: ^2.2.3
html: ^0.15.1 html: ^0.15.1
html_unescape: ^2.0.0 html_unescape: ^2.0.0
http: ^0.13.5 http: ^1.1.0
hydrated_bloc: ^9.1.0 hydrated_bloc: ^9.1.0
in_app_review: in_app_review:
path: components/in_app_review path: components/in_app_review
intl: ^0.18.0 intl: ^0.18.0
linkify: ^5.0.0 linkify: ^5.0.0
logger: ^1.3.0 logger: ^2.0.1
memoize: ^3.0.0 memoize: ^3.0.0
package_info_plus: ^4.0.0 package_info_plus: ^4.0.0
path: ^1.8.2 path: ^1.8.2
@ -69,7 +69,7 @@ dependencies:
shared_preferences: ^2.0.17 shared_preferences: ^2.0.17
shared_preferences_android: ^2.0.15 shared_preferences_android: ^2.0.15
shared_preferences_foundation: ^2.1.3 shared_preferences_foundation: ^2.1.3
shimmer: ^2.0.0 shimmer: ^3.0.0
synced_shared_preferences: synced_shared_preferences:
path: components/synced_shared_preferences path: components/synced_shared_preferences
universal_platform: ^1.0.0+1 universal_platform: ^1.0.0+1
@ -89,7 +89,7 @@ dev_dependencies:
sdk: flutter sdk: flutter
integration_test: integration_test:
sdk: flutter sdk: flutter
mocktail: ^0.3.0 mocktail: ^1.0.0
very_good_analysis: ^5.0.0 very_good_analysis: ^5.0.0
flutter: flutter:

View File

@ -85,7 +85,7 @@ void main() {
}, },
expect: () => <AuthState>[ expect: () => <AuthState>[
const AuthState.init().copyWith( const AuthState.init().copyWith(
status: AuthStatus.loaded, status: Status.success,
), ),
], ],
verify: (_) { verify: (_) {
@ -125,25 +125,25 @@ void main() {
const AuthState( const AuthState(
user: User.empty(), user: User.empty(),
isLoggedIn: false, isLoggedIn: false,
status: AuthStatus.loaded, status: Status.success,
agreedToEULA: false, agreedToEULA: false,
), ),
const AuthState( const AuthState(
user: User.empty(), user: User.empty(),
isLoggedIn: false, isLoggedIn: false,
status: AuthStatus.loaded, status: Status.success,
agreedToEULA: true, agreedToEULA: true,
), ),
const AuthState( const AuthState(
user: User.empty(), user: User.empty(),
isLoggedIn: false, isLoggedIn: false,
status: AuthStatus.loading, status: Status.inProgress,
agreedToEULA: true, agreedToEULA: true,
), ),
const AuthState( const AuthState(
user: tUser, user: tUser,
isLoggedIn: true, isLoggedIn: true,
status: AuthStatus.loaded, status: Status.success,
agreedToEULA: true, agreedToEULA: true,
), ),
], ],