mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-06 18:24:42 +08:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe162208ca |
@ -3,7 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:hacki/config/locator.dart';
|
import 'package:hacki/config/locator.dart';
|
||||||
import 'package:hacki/models/models.dart';
|
import 'package:hacki/models/models.dart';
|
||||||
import 'package:hacki/repositories/postable_repository.dart';
|
import 'package:hacki/repositories/postable_repository.dart';
|
||||||
import 'package:hacki/repositories/repositories.dart';
|
import 'package:hacki/repositories/preference_repository.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
class AuthRepository extends PostableRepository {
|
class AuthRepository extends PostableRepository {
|
||||||
@ -18,8 +18,6 @@ class AuthRepository extends PostableRepository {
|
|||||||
final PreferenceRepository _preferenceRepository;
|
final PreferenceRepository _preferenceRepository;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
|
|
||||||
static const String _authority = 'news.ycombinator.com';
|
|
||||||
|
|
||||||
Future<bool> get loggedIn async => _preferenceRepository.loggedIn;
|
Future<bool> get loggedIn async => _preferenceRepository.loggedIn;
|
||||||
|
|
||||||
Future<String?> get username async => _preferenceRepository.username;
|
Future<String?> get username async => _preferenceRepository.username;
|
||||||
@ -30,7 +28,7 @@ class AuthRepository extends PostableRepository {
|
|||||||
required String username,
|
required String username,
|
||||||
required String password,
|
required String password,
|
||||||
}) async {
|
}) async {
|
||||||
final Uri uri = Uri.https(_authority, 'login');
|
final Uri uri = Uri.https(authority, 'login');
|
||||||
final PostDataMixin data = LoginPostData(
|
final PostDataMixin data = LoginPostData(
|
||||||
acct: username,
|
acct: username,
|
||||||
pw: password,
|
pw: password,
|
||||||
@ -64,7 +62,7 @@ class AuthRepository extends PostableRepository {
|
|||||||
required int id,
|
required int id,
|
||||||
required bool flag,
|
required bool flag,
|
||||||
}) async {
|
}) async {
|
||||||
final Uri uri = Uri.https(_authority, 'flag');
|
final Uri uri = Uri.https(authority, 'flag');
|
||||||
final String? username = await _preferenceRepository.username;
|
final String? username = await _preferenceRepository.username;
|
||||||
final String? password = await _preferenceRepository.password;
|
final String? password = await _preferenceRepository.password;
|
||||||
final PostDataMixin data = FlagPostData(
|
final PostDataMixin data = FlagPostData(
|
||||||
@ -81,7 +79,7 @@ class AuthRepository extends PostableRepository {
|
|||||||
required int id,
|
required int id,
|
||||||
required bool favorite,
|
required bool favorite,
|
||||||
}) async {
|
}) async {
|
||||||
final Uri uri = Uri.https(_authority, 'fave');
|
final Uri uri = Uri.https(authority, 'fave');
|
||||||
final String? username = await _preferenceRepository.username;
|
final String? username = await _preferenceRepository.username;
|
||||||
final String? password = await _preferenceRepository.password;
|
final String? password = await _preferenceRepository.password;
|
||||||
final PostDataMixin data = FavoritePostData(
|
final PostDataMixin data = FavoritePostData(
|
||||||
@ -98,7 +96,7 @@ class AuthRepository extends PostableRepository {
|
|||||||
required int id,
|
required int id,
|
||||||
required bool upvote,
|
required bool upvote,
|
||||||
}) async {
|
}) async {
|
||||||
final Uri uri = Uri.https(_authority, 'vote');
|
final Uri uri = Uri.https(authority, 'vote');
|
||||||
final String? username = await _preferenceRepository.username;
|
final String? username = await _preferenceRepository.username;
|
||||||
final String? password = await _preferenceRepository.password;
|
final String? password = await _preferenceRepository.password;
|
||||||
final PostDataMixin data = VotePostData(
|
final PostDataMixin data = VotePostData(
|
||||||
@ -115,7 +113,7 @@ class AuthRepository extends PostableRepository {
|
|||||||
required int id,
|
required int id,
|
||||||
required bool downvote,
|
required bool downvote,
|
||||||
}) async {
|
}) async {
|
||||||
final Uri uri = Uri.https(_authority, 'vote');
|
final Uri uri = Uri.https(authority, 'vote');
|
||||||
final String? username = await _preferenceRepository.username;
|
final String? username = await _preferenceRepository.username;
|
||||||
final String? password = await _preferenceRepository.password;
|
final String? password = await _preferenceRepository.password;
|
||||||
final PostDataMixin data = VotePostData(
|
final PostDataMixin data = VotePostData(
|
||||||
|
@ -14,15 +14,13 @@ class PostRepository extends PostableRepository {
|
|||||||
|
|
||||||
final PreferenceRepository _preferenceRepository;
|
final PreferenceRepository _preferenceRepository;
|
||||||
|
|
||||||
static const String _authority = 'news.ycombinator.com';
|
|
||||||
|
|
||||||
Future<bool> comment({
|
Future<bool> comment({
|
||||||
required int parentId,
|
required int parentId,
|
||||||
required String text,
|
required String text,
|
||||||
}) async {
|
}) async {
|
||||||
final String? username = await _preferenceRepository.username;
|
final String? username = await _preferenceRepository.username;
|
||||||
final String? password = await _preferenceRepository.password;
|
final String? password = await _preferenceRepository.password;
|
||||||
final Uri uri = Uri.https(_authority, 'comment');
|
final Uri uri = Uri.https(authority, 'comment');
|
||||||
|
|
||||||
if (username == null || password == null) {
|
if (username == null || password == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -54,7 +52,7 @@ class PostRepository extends PostableRepository {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Response<List<int>> formResponse = await _getFormResponse(
|
final Response<List<int>> formResponse = await getFormResponse(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
path: 'submitlink',
|
path: 'submitlink',
|
||||||
@ -69,7 +67,7 @@ class PostRepository extends PostableRepository {
|
|||||||
final String? cookie =
|
final String? cookie =
|
||||||
formResponse.headers.value(HttpHeaders.setCookieHeader);
|
formResponse.headers.value(HttpHeaders.setCookieHeader);
|
||||||
|
|
||||||
final Uri uri = Uri.https(_authority, 'r');
|
final Uri uri = Uri.https(authority, 'r');
|
||||||
final PostDataMixin data = SubmitPostData(
|
final PostDataMixin data = SubmitPostData(
|
||||||
fnid: formValues['fnid']!,
|
fnid: formValues['fnid']!,
|
||||||
fnop: formValues['fnop']!,
|
fnop: formValues['fnop']!,
|
||||||
@ -97,7 +95,7 @@ class PostRepository extends PostableRepository {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Response<List<int>> formResponse = await _getFormResponse(
|
final Response<List<int>> formResponse = await getFormResponse(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
id: id,
|
id: id,
|
||||||
@ -113,7 +111,7 @@ class PostRepository extends PostableRepository {
|
|||||||
final String? cookie =
|
final String? cookie =
|
||||||
formResponse.headers.value(HttpHeaders.setCookieHeader);
|
formResponse.headers.value(HttpHeaders.setCookieHeader);
|
||||||
|
|
||||||
final Uri uri = Uri.https(_authority, 'xedit');
|
final Uri uri = Uri.https(authority, 'xedit');
|
||||||
final PostDataMixin data = EditPostData(
|
final PostDataMixin data = EditPostData(
|
||||||
hmac: formValues['hmac']!,
|
hmac: formValues['hmac']!,
|
||||||
id: id,
|
id: id,
|
||||||
@ -126,28 +124,4 @@ class PostRepository extends PostableRepository {
|
|||||||
cookie: cookie,
|
cookie: cookie,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Response<List<int>>> _getFormResponse({
|
|
||||||
required String username,
|
|
||||||
required String password,
|
|
||||||
required String path,
|
|
||||||
int? id,
|
|
||||||
}) async {
|
|
||||||
final Uri uri = Uri.https(
|
|
||||||
_authority,
|
|
||||||
path,
|
|
||||||
<String, dynamic>{if (id != null) 'id': id.toString()},
|
|
||||||
);
|
|
||||||
final PostDataMixin data = FormPostData(
|
|
||||||
acct: username,
|
|
||||||
pw: password,
|
|
||||||
id: id,
|
|
||||||
);
|
|
||||||
return performPost(
|
|
||||||
uri,
|
|
||||||
data,
|
|
||||||
responseType: ResponseType.bytes,
|
|
||||||
validateStatus: (int? status) => status == HttpStatus.ok,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,14 @@ import 'package:hacki/utils/service_exception.dart';
|
|||||||
class PostableRepository {
|
class PostableRepository {
|
||||||
PostableRepository({
|
PostableRepository({
|
||||||
Dio? dio,
|
Dio? dio,
|
||||||
|
this.authority = 'news.ycombinator.com',
|
||||||
}) : _dio = dio ?? Dio();
|
}) : _dio = dio ?? Dio();
|
||||||
|
|
||||||
final Dio _dio;
|
final Dio _dio;
|
||||||
|
|
||||||
|
@protected
|
||||||
|
final String authority;
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
Future<bool> performDefaultPost(
|
Future<bool> performDefaultPost(
|
||||||
Uri uri,
|
Uri uri,
|
||||||
@ -60,4 +64,29 @@ class PostableRepository {
|
|||||||
throw ServiceException(e.message);
|
throw ServiceException(e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@protected
|
||||||
|
Future<Response<List<int>>> getFormResponse({
|
||||||
|
required String username,
|
||||||
|
required String password,
|
||||||
|
required String path,
|
||||||
|
int? id,
|
||||||
|
}) async {
|
||||||
|
final Uri uri = Uri.https(
|
||||||
|
authority,
|
||||||
|
path,
|
||||||
|
<String, dynamic>{if (id != null) 'id': id.toString()},
|
||||||
|
);
|
||||||
|
final PostDataMixin data = FormPostData(
|
||||||
|
acct: username,
|
||||||
|
pw: password,
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
return performPost(
|
||||||
|
uri,
|
||||||
|
data,
|
||||||
|
responseType: ResponseType.bytes,
|
||||||
|
validateStatus: (int? status) => status == HttpStatus.ok,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,7 @@ class PollView extends StatelessWidget {
|
|||||||
listener: (BuildContext context, VoteState voteState) {
|
listener: (BuildContext context, VoteState voteState) {
|
||||||
ScaffoldMessenger.of(context).clearSnackBars();
|
ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
if (voteState.status == VoteStatus.submitted) {
|
if (voteState.status == VoteStatus.submitted) {
|
||||||
showSnackBar(
|
context.showSnackBar(
|
||||||
context,
|
|
||||||
content: 'Vote submitted successfully.',
|
content: 'Vote submitted successfully.',
|
||||||
);
|
);
|
||||||
} else if (voteState.status == VoteStatus.canceled) {
|
} else if (voteState.status == VoteStatus.canceled) {
|
||||||
@ -85,8 +84,7 @@ class PollView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
} else if (voteState.status ==
|
} else if (voteState.status ==
|
||||||
VoteStatus.failureBeHumble) {
|
VoteStatus.failureBeHumble) {
|
||||||
showSnackBar(
|
context.showSnackBar(
|
||||||
context,
|
|
||||||
content: 'No voting on your own post! (;`O´)o',
|
content: 'No voting on your own post! (;`O´)o',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -149,26 +147,4 @@ class PollView extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showSnackBar(
|
|
||||||
BuildContext context, {
|
|
||||||
required String content,
|
|
||||||
VoidCallback? action,
|
|
||||||
String? label,
|
|
||||||
}) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
backgroundColor: Palette.deepOrange,
|
|
||||||
content: Text(content),
|
|
||||||
action: action != null && label != null
|
|
||||||
? SnackBarAction(
|
|
||||||
label: label,
|
|
||||||
onPressed: action,
|
|
||||||
textColor: Theme.of(context).textTheme.bodyLarge?.color,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
behavior: SnackBarBehavior.floating,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
48
lib/screens/widgets/centered_text.dart
Normal file
48
lib/screens/widgets/centered_text.dart
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hacki/styles/styles.dart';
|
||||||
|
|
||||||
|
class CenteredText extends StatelessWidget {
|
||||||
|
const CenteredText({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
this.color = Palette.grey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const CenteredText.deleted({Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
text: 'deleted',
|
||||||
|
);
|
||||||
|
|
||||||
|
const CenteredText.dead({Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
text: 'dead',
|
||||||
|
);
|
||||||
|
|
||||||
|
const CenteredText.blocked({Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
text: 'blocked',
|
||||||
|
);
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: Dimens.pt12,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: TextStyle(
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ 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/models/models.dart';
|
||||||
import 'package:hacki/screens/widgets/bloc_builder_3.dart';
|
import 'package:hacki/screens/widgets/bloc_builder_3.dart';
|
||||||
|
import 'package:hacki/screens/widgets/centered_text.dart';
|
||||||
import 'package:hacki/services/services.dart';
|
import 'package:hacki/services/services.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';
|
||||||
@ -40,6 +41,8 @@ class CommentTile extends StatelessWidget {
|
|||||||
final void Function(String) onStoryLinkTapped;
|
final void Function(String) onStoryLinkTapped;
|
||||||
final FetchMode fetchMode;
|
final FetchMode fetchMode;
|
||||||
|
|
||||||
|
static final Map<int, Color> _colors = <int, Color>{};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<CollapseCubit>(
|
return BlocProvider<CollapseCubit>(
|
||||||
@ -163,63 +166,18 @@ class CommentTile extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (actionable && state.collapsed)
|
if (actionable && state.collapsed)
|
||||||
Center(
|
CenteredText(
|
||||||
child: Padding(
|
text:
|
||||||
padding: const EdgeInsets.only(
|
'''collapsed (${state.collapsedCount + 1})''',
|
||||||
bottom: Dimens.pt12,
|
color: Palette.orangeAccent,
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'collapsed '
|
|
||||||
'(${state.collapsedCount + 1})',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Palette.orangeAccent,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else if (comment.deleted)
|
else if (comment.deleted)
|
||||||
const Center(
|
const CenteredText.deleted()
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
bottom: Dimens.pt12,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'deleted',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Palette.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else if (comment.dead)
|
else if (comment.dead)
|
||||||
const Center(
|
const CenteredText.dead()
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
bottom: Dimens.pt12,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'dead',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Palette.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else if (blocklistState.blocklist
|
else if (blocklistState.blocklist
|
||||||
.contains(comment.by))
|
.contains(comment.by))
|
||||||
const Center(
|
const CenteredText.blocked()
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
bottom: Dimens.pt12,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'blocked',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Palette.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
@ -284,55 +242,41 @@ class CommentTile extends StatelessWidget {
|
|||||||
onTap: () => onTextTapped(context),
|
onTap: () => onTextTapped(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!state.collapsed &&
|
|
||||||
fetchMode == FetchMode.lazy &&
|
|
||||||
comment.kids.isNotEmpty &&
|
|
||||||
!context
|
|
||||||
.read<CommentsCubit>()
|
|
||||||
.state
|
|
||||||
.commentIds
|
|
||||||
.contains(comment.kids.first) &&
|
|
||||||
!context
|
|
||||||
.read<CommentsCubit>()
|
|
||||||
.state
|
|
||||||
.onlyShowTargetComment)
|
|
||||||
Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: Dimens.pt12,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
HapticFeedback.selectionClick();
|
|
||||||
context
|
|
||||||
.read<CommentsCubit>()
|
|
||||||
.loadMore(
|
|
||||||
comment: comment,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'''Load ${comment.kids.length} ${comment.kids.length > 1 ? 'replies' : 'reply'}''',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: TextDimens.pt12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
height: Dimens.zero,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
if (_shouldShowLoadButton(context))
|
||||||
|
Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: Dimens.pt12,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
HapticFeedback.selectionClick();
|
||||||
|
context.read<CommentsCubit>().loadMore(
|
||||||
|
comment: comment,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'''Load ${comment.kids.length} ${comment.kids.length > 1 ? 'replies' : 'reply'}''',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: TextDimens.pt12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
height: Dimens.zero,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -391,7 +335,12 @@ class CommentTile extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final Map<int, Color> _colors = <int, Color>{};
|
void onTextTapped(BuildContext context) {
|
||||||
|
if (context.read<PreferenceCubit>().state.tapAnywhereToCollapseEnabled) {
|
||||||
|
HapticFeedback.selectionClick();
|
||||||
|
context.read<CollapseCubit>().collapse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Color _getColor(int level) {
|
Color _getColor(int level) {
|
||||||
final int initialLevel = level;
|
final int initialLevel = level;
|
||||||
@ -421,10 +370,13 @@ class CommentTile extends StatelessWidget {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTextTapped(BuildContext context) {
|
bool _shouldShowLoadButton(BuildContext context) {
|
||||||
if (context.read<PreferenceCubit>().state.tapAnywhereToCollapseEnabled) {
|
final CollapseState collapseState = context.read<CollapseCubit>().state;
|
||||||
HapticFeedback.selectionClick();
|
final CommentsState commentsState = context.read<CommentsCubit>().state;
|
||||||
context.read<CollapseCubit>().collapse();
|
return fetchMode == FetchMode.lazy &&
|
||||||
}
|
comment.kids.isNotEmpty &&
|
||||||
|
collapseState.collapsed == false &&
|
||||||
|
commentsState.commentIds.contains(comment.kids.first) == false &&
|
||||||
|
commentsState.onlyShowTargetComment == false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export 'bloc_builder_3.dart';
|
export 'bloc_builder_3.dart';
|
||||||
|
export 'centered_text.dart';
|
||||||
export 'circle_tab_indicator.dart';
|
export 'circle_tab_indicator.dart';
|
||||||
export 'comment_tile.dart';
|
export 'comment_tile.dart';
|
||||||
export 'countdown_reminder.dart';
|
export 'countdown_reminder.dart';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: hacki
|
name: hacki
|
||||||
description: A Hacker News reader.
|
description: A Hacker News reader.
|
||||||
version: 1.0.9+87
|
version: 1.0.10+88
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
Reference in New Issue
Block a user