Compare commits

...

10 Commits

Author SHA1 Message Date
58139ba7a3 update commit_check.yml (#141) 2023-02-09 15:42:08 -08:00
33a31acbe2 update Fastfile. 2023-02-09 15:20:19 -08:00
0fcfcbb7e3 update Fastfile. (#140) 2023-02-09 15:12:00 -08:00
a98f52c90b update publish_ios.yml 2023-02-09 14:37:11 -08:00
8e8e48c44a update GitHub action. (#139) 2023-02-09 14:28:46 -08:00
603b7cc939 bump flutter to 3.7.3 (#138) 2023-02-09 11:27:03 -08:00
649fa33df3 fix err msg. (#137) 2023-02-09 00:19:34 -08:00
81d4a0f2df banner cleanup. (#136) 2023-02-08 23:44:15 -08:00
24112a471e add collapse/expand animation to comment tile. (#135) 2023-02-08 23:08:09 -08:00
c7824eaef3 bump flutter to 3.7.2 (#134) 2023-02-08 17:43:23 -08:00
25 changed files with 262 additions and 242 deletions

View File

@ -11,15 +11,13 @@ jobs:
name: Check commit name: Check commit
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 30 timeout-minutes: 30
env:
FLUTTER_VERSION: "3.7.1"
steps: steps:
- uses: actions/checkout@v2 - name: checkout all the submodules
- uses: subosito/flutter-action@v2 uses: actions/checkout@v3
with: with:
flutter-version: '3.7.1' submodules: recursive
channel: 'stable' - run: submodules/flutter/bin/flutter doctor
- run: flutter pub get - run: submodules/flutter/bin/flutter pub get
- run: flutter format --set-exit-if-changed . - run: submodules/flutter/bin/dart format --set-exit-if-changed lib test integration_test
- run: flutter analyze - run: submodules/flutter/bin/flutter analyze lib test integration_test
- run: flutter test - run: submodules/flutter/bin/flutter test

View File

@ -20,21 +20,21 @@ jobs:
steps: steps:
- name: Check out from git - name: Check out from git
uses: actions/checkout@v2 uses: actions/checkout@v3
with:
submodules: recursive
- run: submodules/flutter/bin/flutter doctor
- 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/flutter analyze lib test integration_test
- run: submodules/flutter/bin/flutter test
# Configure ruby according to our .ruby-version # Configure ruby according to our .ruby-version
- name: Setup ruby & Bundler - name: Setup ruby & Bundler
uses: ruby/setup-ruby@v1 uses: ruby/setup-ruby@v1
with: with:
bundler-cache: true bundler-cache: true
# Set up flutter (feel free to adjust the version below)
- name: Setup flutter
uses: subosito/flutter-action@v2
with:
cache: true
flutter-version: 3.7.1
- run: flutter pub get
- run: flutter format --set-exit-if-changed .
- run: flutter analyze
# Start an ssh-agent that will provide the SSH key from the # Start an ssh-agent that will provide the SSH key from the
# SSH_PRIVATE_KEY secret to `fastlane match` # SSH_PRIVATE_KEY secret to `fastlane match`
- name: Setup SSH key - name: Setup SSH key
@ -43,8 +43,7 @@ jobs:
run: | run: |
ssh-agent -a $SSH_AUTH_SOCK > /dev/null ssh-agent -a $SSH_AUTH_SOCK > /dev/null
ssh-add - <<< "${{ secrets.SSH_PRIVATE_KEY }}" ssh-add - <<< "${{ secrets.SSH_PRIVATE_KEY }}"
- name: Download dependencies
run: flutter pub get
- name: Build & Publish to TestFlight with Fastlane - name: Build & Publish to TestFlight with Fastlane
env: env:
APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }}

View File

@ -49,7 +49,7 @@ latest_testflight_build_number
# Prep the xcodeproject from Flutter without building (`--config-only`) # Prep the xcodeproject from Flutter without building (`--config-only`)
sh( sh(
"flutter", "build", "ios", "--config-only", "/Users/runner/work/Hacki/Hacki/submodules/flutter/bin/flutter", "build", "ios", "--config-only",
"--release", "--no-pub", "--no-codesign", "--release", "--no-pub", "--no-codesign",
"--build-number", new_build_number.to_s "--build-number", new_build_number.to_s
) )

View File

@ -56,6 +56,8 @@ abstract class Constants {
'ʕ•́ᴥ•̀ʔっ', 'ʕ•́ᴥ•̀ʔっ',
'(ㆆ_ㆆ)', '(ㆆ_ㆆ)',
].pickRandomly()!; ].pickRandomly()!;
static final String errorMessage = 'Something went wrong...$sadFace';
} }
abstract class RegExpConstants { abstract class RegExpConstants {

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hacki/config/constants.dart';
import 'package:hacki/screens/screens.dart'; import 'package:hacki/screens/screens.dart';
/// Custom router. /// Custom router.
@ -39,8 +40,8 @@ class CustomRouter {
appBar: AppBar( appBar: AppBar(
title: const Text('Error'), title: const Text('Error'),
), ),
body: const Center( body: Center(
child: Text('Something went wrong!'), child: Text(Constants.errorMessage),
), ),
), ),
); );

View File

@ -20,7 +20,7 @@ Future<void> setUpLocator() async {
Logger( Logger(
filter: CustomLogFilter(), filter: CustomLogFilter(),
printer: LogUtil.logPrinter, printer: LogUtil.logPrinter,
output: LogUtil.getLogOutput(logOutputFile), output: LogUtil.logOutput(logOutputFile),
), ),
) )
..registerSingleton<StoriesRepository>(StoriesRepository()) ..registerSingleton<StoriesRepository>(StoriesRepository())

View File

@ -2,6 +2,8 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hacki/config/constants.dart';
import 'package:hacki/styles/styles.dart';
extension ContextExtension on BuildContext { extension ContextExtension on BuildContext {
T? tryRead<T>() { T? tryRead<T>() {
@ -12,6 +14,31 @@ extension ContextExtension on BuildContext {
} }
} }
void showSnackBar({
required String content,
VoidCallback? action,
String? label,
}) {
ScaffoldMessenger.of(this).showSnackBar(
SnackBar(
backgroundColor: Palette.deepOrange,
content: Text(content),
action: action != null && label != null
? SnackBarAction(
label: label,
onPressed: action,
textColor: Theme.of(this).textTheme.bodyLarge?.color,
)
: null,
behavior: SnackBarBehavior.floating,
),
);
}
void showErrorSnackBar() => showSnackBar(
content: Constants.errorMessage,
);
Rect? get rect { Rect? get rect {
final RenderBox? box = findRenderObject() as RenderBox?; final RenderBox? box = findRenderObject() as RenderBox?;
final Rect? rect = final Rect? rect =

View File

@ -21,22 +21,15 @@ extension StateExtension on State {
VoidCallback? action, VoidCallback? action,
String? label, String? label,
}) { }) {
ScaffoldMessenger.of(context).showSnackBar( context.showSnackBar(
SnackBar( content: content,
backgroundColor: Palette.deepOrange, action: action,
content: Text(content), label: label,
action: action != null && label != null
? SnackBarAction(
label: label,
onPressed: action,
textColor: Theme.of(context).textTheme.bodyLarge?.color,
)
: null,
behavior: SnackBarBehavior.floating,
),
); );
} }
void showErrorSnackBar() => context.showErrorSnackBar();
Future<void>? goToItemScreen({ Future<void>? goToItemScreen({
required ItemScreenArgs args, required ItemScreenArgs args,
bool forceNewScreen = false, bool forceNewScreen = false,
@ -70,7 +63,6 @@ extension StateExtension on State {
return MorePopupMenu( return MorePopupMenu(
item: item, item: item,
isBlocked: isBlocked, isBlocked: isBlocked,
showSnackBar: showSnackBar,
onStoryLinkTapped: onStoryLinkTapped, onStoryLinkTapped: onStoryLinkTapped,
onLoginTapped: onLoginTapped, onLoginTapped: onLoginTapped,
); );

View File

@ -301,7 +301,7 @@ class _HomeScreenState extends State<HomeScreen>
.fetchStoryBy(storyId) .fetchStoryBy(storyId)
.then((Story? story) { .then((Story? story) {
if (story == null) { if (story == null) {
showSnackBar(content: 'Something went wrong...'); showErrorSnackBar();
return; return;
} }
final ItemScreenArgs args = ItemScreenArgs(item: story); final ItemScreenArgs args = ItemScreenArgs(item: story);
@ -326,7 +326,7 @@ class _HomeScreenState extends State<HomeScreen>
.fetchStoryBy(storyId) .fetchStoryBy(storyId)
.then((Story? story) { .then((Story? story) {
if (story == null) { if (story == null) {
showSnackBar(content: 'Something went wrong...'); showErrorSnackBar();
return; return;
} }
final ItemScreenArgs args = ItemScreenArgs(item: story); final ItemScreenArgs args = ItemScreenArgs(item: story);

View File

@ -239,12 +239,7 @@ class _ItemScreenState extends State<ItemScreen> with RouteAware {
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 == PostStatus.failure) {
showSnackBar( showErrorSnackBar();
content: 'Something went wrong...'
'${Constants.sadFace}',
label: 'Okay',
action: ScaffoldMessenger.of(context).hideCurrentSnackBar,
);
context.read<PostCubit>().reset(); context.read<PostCubit>().reset();
} }
}, },

View File

@ -87,13 +87,13 @@ class LoginDialog extends StatelessWidget {
height: Dimens.pt16, height: Dimens.pt16,
), ),
if (state.status == AuthStatus.failure) if (state.status == AuthStatus.failure)
const Padding( Padding(
padding: EdgeInsets.only( padding: const EdgeInsets.only(
left: Dimens.pt18, left: Dimens.pt18,
), ),
child: Text( child: Text(
'Something went wrong...', Constants.errorMessage,
style: TextStyle( style: const TextStyle(
color: Palette.grey, color: Palette.grey,
fontSize: TextDimens.pt12, fontSize: TextDimens.pt12,
), ),

View File

@ -15,18 +15,12 @@ class MorePopupMenu extends StatelessWidget {
super.key, super.key,
required this.item, required this.item,
required this.isBlocked, required this.isBlocked,
required this.showSnackBar,
required this.onStoryLinkTapped, required this.onStoryLinkTapped,
required this.onLoginTapped, required this.onLoginTapped,
}); });
final Item item; final Item item;
final bool isBlocked; final bool isBlocked;
final void Function({
required String content,
VoidCallback? action,
String? label,
}) showSnackBar;
final ValueChanged<String> onStoryLinkTapped; final ValueChanged<String> onStoryLinkTapped;
final VoidCallback onLoginTapped; final VoidCallback onLoginTapped;
@ -43,24 +37,26 @@ class MorePopupMenu extends StatelessWidget {
}, },
listener: (BuildContext context, VoteState voteState) { listener: (BuildContext context, VoteState voteState) {
if (voteState.status == VoteStatus.submitted) { if (voteState.status == VoteStatus.submitted) {
showSnackBar(content: 'Vote submitted successfully.'); context.showSnackBar(content: 'Vote submitted successfully.');
} else if (voteState.status == VoteStatus.canceled) { } else if (voteState.status == VoteStatus.canceled) {
showSnackBar(content: 'Vote canceled.'); context.showSnackBar(content: 'Vote canceled.');
} else if (voteState.status == VoteStatus.failure) { } else if (voteState.status == VoteStatus.failure) {
showSnackBar(content: 'Something went wrong...'); context.showErrorSnackBar();
} else if (voteState.status == } else if (voteState.status ==
VoteStatus.failureKarmaBelowThreshold) { VoteStatus.failureKarmaBelowThreshold) {
showSnackBar( context.showSnackBar(
content: "You can't downvote because you are karmaly broke.", content: "You can't downvote because you are karmaly broke.",
); );
} else if (voteState.status == VoteStatus.failureNotLoggedIn) { } else if (voteState.status == VoteStatus.failureNotLoggedIn) {
showSnackBar( context.showSnackBar(
content: 'Not logged in, no voting! (;O´)o', content: 'Not logged in, no voting! (;O´)o',
action: onLoginTapped, action: onLoginTapped,
label: 'Log in', label: 'Log in',
); );
} else if (voteState.status == VoteStatus.failureBeHumble) { } else if (voteState.status == VoteStatus.failureBeHumble) {
showSnackBar(content: 'No voting on your own post! (;O´)o'); context.showSnackBar(
content: 'No voting on your own post! (;O´)o',
);
} }
Navigator.pop( Navigator.pop(

View File

@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_fadein/flutter_fadein.dart'; import 'package:flutter_fadein/flutter_fadein.dart';
import 'package:hacki/blocs/auth/auth_bloc.dart'; import 'package:hacki/blocs/auth/auth_bloc.dart';
import 'package:hacki/cubits/cubits.dart'; import 'package:hacki/cubits/cubits.dart';
import 'package:hacki/extensions/context_extension.dart';
import 'package:hacki/models/models.dart'; import 'package:hacki/models/models.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
@ -66,23 +67,18 @@ class PollView extends StatelessWidget {
content: 'Vote submitted successfully.', content: 'Vote submitted successfully.',
); );
} else if (voteState.status == VoteStatus.canceled) { } else if (voteState.status == VoteStatus.canceled) {
showSnackBar(context, content: 'Vote canceled.'); context.showSnackBar(content: 'Vote canceled.');
} else if (voteState.status == VoteStatus.failure) { } else if (voteState.status == VoteStatus.failure) {
showSnackBar( context.showErrorSnackBar();
context,
content: 'Something went wrong...',
);
} else if (voteState.status == } else if (voteState.status ==
VoteStatus.failureKarmaBelowThreshold) { VoteStatus.failureKarmaBelowThreshold) {
showSnackBar( context.showSnackBar(
context,
content: "You can't downvote because" content: "You can't downvote because"
' you are karmaly broke.', ' you are karmaly broke.',
); );
} else if (voteState.status == } else if (voteState.status ==
VoteStatus.failureNotLoggedIn) { VoteStatus.failureNotLoggedIn) {
showSnackBar( context.showSnackBar(
context,
content: 'Not logged in, no voting! (;O´)o', content: 'Not logged in, no voting! (;O´)o',
action: onLoginTapped, action: onLoginTapped,
label: 'Log in', label: 'Log in',

View File

@ -453,13 +453,13 @@ class _ProfileScreenState extends State<ProfileScreen>
height: Dimens.pt16, height: Dimens.pt16,
), ),
if (state.status == AuthStatus.failure) if (state.status == AuthStatus.failure)
const Padding( Padding(
padding: EdgeInsets.only( padding: const EdgeInsets.only(
left: Dimens.pt18, left: Dimens.pt18,
), ),
child: Text( child: Text(
'Something went wrong...', Constants.errorMessage,
style: TextStyle( style: const TextStyle(
color: Palette.grey, color: Palette.grey,
fontSize: TextDimens.pt12, fontSize: TextDimens.pt12,
), ),

View File

@ -50,9 +50,7 @@ class _SubmitScreenState extends State<SubmitScreen> {
content: 'Post submitted successfully.', content: 'Post submitted successfully.',
); );
} else if (state.status == SubmitStatus.failure) { } else if (state.status == SubmitStatus.failure) {
showSnackBar( showErrorSnackBar();
content: 'Something went wrong...',
);
} }
}, },
builder: (BuildContext context, SubmitState state) { builder: (BuildContext context, SubmitState state) {

View File

@ -157,167 +157,182 @@ class CommentTile extends StatelessWidget {
], ],
), ),
), ),
if (actionable && state.collapsed) AnimatedSize(
Center( duration: const Duration(milliseconds: 200),
child: Padding( child: Column(
padding: const EdgeInsets.only( crossAxisAlignment: CrossAxisAlignment.start,
bottom: Dimens.pt12, children: <Widget>[
), if (actionable && state.collapsed)
child: Text( Center(
'collapsed ' child: Padding(
'(${state.collapsedCount + 1})', padding: const EdgeInsets.only(
style: const TextStyle( bottom: Dimens.pt12,
color: Palette.orangeAccent, ),
), child: Text(
), 'collapsed '
), '(${state.collapsedCount + 1})',
) style: const TextStyle(
else if (comment.deleted) color: Palette.orangeAccent,
const Center( ),
child: Padding( ),
padding: EdgeInsets.only( ),
bottom: Dimens.pt12, )
), else if (comment.deleted)
child: Text( const Center(
'deleted', child: Padding(
style: TextStyle( padding: EdgeInsets.only(
color: Palette.grey, bottom: Dimens.pt12,
), ),
), child: Text(
), 'deleted',
)
else if (comment.dead)
const Center(
child: Padding(
padding: EdgeInsets.only(
bottom: Dimens.pt12,
),
child: Text(
'dead',
style: TextStyle(
color: Palette.grey,
),
),
),
)
else if (blocklistState.blocklist.contains(comment.by))
const Center(
child: Padding(
padding: EdgeInsets.only(
bottom: Dimens.pt12,
),
child: Text(
'blocked',
style: TextStyle(
color: Palette.grey,
),
),
),
)
else
Padding(
padding: const EdgeInsets.only(
left: Dimens.pt8,
right: Dimens.pt8,
top: Dimens.pt6,
bottom: Dimens.pt12,
),
child: comment is BuildableComment
? SelectableText.rich(
key: ValueKey<int>(comment.id),
buildTextSpan(
(comment as BuildableComment).elements,
style: TextStyle( style: TextStyle(
fontSize: MediaQuery.of( color: Palette.grey,
context,
).textScaleFactor *
prefState.fontSize.fontSize,
), ),
linkStyle: TextStyle(
fontSize: MediaQuery.of(
context,
).textScaleFactor *
prefState.fontSize.fontSize,
decoration: TextDecoration.underline,
color: Palette.orange,
),
onOpen: (LinkableElement link) {
if (link.url.isStoryLink) {
onStoryLinkTapped.call(link.url);
} else {
LinkUtil.launch(link.url);
}
},
), ),
onTap: () => onTextTapped(context),
)
: SelectableLinkify(
key: ValueKey<int>(comment.id),
text: comment.text,
style: TextStyle(
fontSize: MediaQuery.of(context)
.textScaleFactor *
prefState.fontSize.fontSize,
),
linkStyle: TextStyle(
fontSize: MediaQuery.of(context)
.textScaleFactor *
prefState.fontSize.fontSize,
color: Palette.orange,
),
onOpen: (LinkableElement link) {
if (link.url.isStoryLink) {
onStoryLinkTapped.call(link.url);
} else {
LinkUtil.launch(link.url);
}
},
onTap: () => onTextTapped(context),
), ),
), )
if (!state.collapsed && else if (comment.dead)
fetchMode == FetchMode.lazy && const Center(
comment.kids.isNotEmpty && child: Padding(
!context padding: EdgeInsets.only(
.read<CommentsCubit>() bottom: Dimens.pt12,
.state ),
.commentIds child: Text(
.contains(comment.kids.first) && 'dead',
!context style: TextStyle(
.read<CommentsCubit>() color: Palette.grey,
.state ),
.onlyShowTargetComment) ),
Center( ),
child: Padding( )
padding: const EdgeInsets.symmetric( else if (blocklistState.blocklist
horizontal: Dimens.pt12, .contains(comment.by))
), const Center(
child: Row( child: Padding(
mainAxisAlignment: MainAxisAlignment.center, padding: EdgeInsets.only(
children: <Widget>[ bottom: Dimens.pt12,
Expanded( ),
child: TextButton( child: Text(
onPressed: () { 'blocked',
HapticFeedback.selectionClick(); style: TextStyle(
context.read<CommentsCubit>().loadMore( color: Palette.grey,
comment: comment, ),
); ),
}, ),
child: Text( )
'''Load ${comment.kids.length} ${comment.kids.length > 1 ? 'replies' : 'reply'}''', else
style: const TextStyle( Padding(
fontSize: TextDimens.pt12, padding: const EdgeInsets.only(
left: Dimens.pt8,
right: Dimens.pt8,
top: Dimens.pt6,
bottom: Dimens.pt12,
),
child: comment is BuildableComment
? SelectableText.rich(
key: ValueKey<int>(comment.id),
buildTextSpan(
(comment as BuildableComment)
.elements,
style: TextStyle(
fontSize: MediaQuery.of(
context,
).textScaleFactor *
prefState.fontSize.fontSize,
),
linkStyle: TextStyle(
fontSize: MediaQuery.of(
context,
).textScaleFactor *
prefState.fontSize.fontSize,
decoration:
TextDecoration.underline,
color: Palette.orange,
),
onOpen: (LinkableElement link) {
if (link.url.isStoryLink) {
onStoryLinkTapped
.call(link.url);
} else {
LinkUtil.launch(link.url);
}
},
),
onTap: () => onTextTapped(context),
)
: SelectableLinkify(
key: ValueKey<int>(comment.id),
text: comment.text,
style: TextStyle(
fontSize: MediaQuery.of(context)
.textScaleFactor *
prefState.fontSize.fontSize,
),
linkStyle: TextStyle(
fontSize: MediaQuery.of(context)
.textScaleFactor *
prefState.fontSize.fontSize,
color: Palette.orange,
),
onOpen: (LinkableElement link) {
if (link.url.isStoryLink) {
onStoryLinkTapped.call(link.url);
} else {
LinkUtil.launch(link.url);
}
},
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,
), ),
), ],
), ),
const Divider( )
height: Dimens.zero,
),
], ],
), ),
), ),

View File

@ -111,7 +111,7 @@ class _CountDownReminderState extends State<CountdownReminder>
.fetchStoryBy(state.storyId!) .fetchStoryBy(state.storyId!)
.then((Story? story) { .then((Story? story) {
if (story == null) { if (story == null) {
showSnackBar(content: 'Something went wrong...'); showErrorSnackBar();
return; return;
} }
final ItemScreenArgs args = ItemScreenArgs(item: story); final ItemScreenArgs args = ItemScreenArgs(item: story);

View File

@ -5,7 +5,7 @@ import 'package:hacki/config/constants.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/link_preview/link_view.dart'; import 'package:hacki/screens/widgets/link_preview/link_view.dart';
import 'package:hacki/screens/widgets/link_preview/web_analyzer.dart'; import 'package:hacki/services/services.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -119,7 +119,7 @@ class _LinkPreviewState extends State<LinkPreview> {
@override @override
void initState() { void initState() {
_errorTitle = widget.errorTitle ?? 'Something went wrong!'; _errorTitle = widget.errorTitle ?? Constants.errorMessage;
_errorBody = widget.errorBody ?? _errorBody = widget.errorBody ??
'Oops! Unable to parse the url. We have ' 'Oops! Unable to parse the url. We have '
'sent feedback to our developers & ' 'sent feedback to our developers & '

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hacki/blocs/blocs.dart'; import 'package:hacki/blocs/blocs.dart';
import 'package:hacki/cubits/cubits.dart'; import 'package:hacki/cubits/cubits.dart';
import 'package:hacki/screens/widgets/link_preview/web_analyzer.dart'; import 'package:hacki/services/services.dart';
import 'package:hacki/styles/styles.dart'; import 'package:hacki/styles/styles.dart';
class OfflineBanner extends StatelessWidget { class OfflineBanner extends StatelessWidget {

View File

@ -3,3 +3,4 @@ export 'custom_bloc_observer.dart';
export 'fetcher.dart'; export 'fetcher.dart';
export 'firebase_client.dart'; export 'firebase_client.dart';
export 'local_notification.dart'; export 'local_notification.dart';
export 'web_analyzer.dart';

View File

@ -14,7 +14,7 @@ abstract class LogUtil {
colors: false, colors: false,
); );
static LogOutput getLogOutput(File outputFile) => MultiOutput( static LogOutput logOutput(File outputFile) => MultiOutput(
<LogOutput>[ <LogOutput>[
ConsoleOutput(), ConsoleOutput(),
CustomFileOutput( CustomFileOutput(
@ -43,7 +43,7 @@ abstract class LogUtil {
final Uint8List fileContent = await currentSessionLog.readAsBytes(); final Uint8List fileContent = await currentSessionLog.readAsBytes();
await previousSessionLog.writeAsString( await previousSessionLog.writeAsString(
'Current session logs:', 'Current session logs:\n',
mode: FileMode.append, mode: FileMode.append,
); );
return previousSessionLog.writeAsBytes( return previousSessionLog.writeAsBytes(

View File

@ -1359,4 +1359,4 @@ packages:
version: "3.1.1" version: "3.1.1"
sdks: sdks:
dart: ">=2.18.0 <3.0.0" dart: ">=2.18.0 <3.0.0"
flutter: ">=3.7.1" flutter: ">=3.7.3"

View File

@ -1,11 +1,11 @@
name: hacki name: hacki
description: A Hacker News reader. description: A Hacker News reader.
version: 1.0.7+85 version: 1.0.9+87
publish_to: none publish_to: none
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"
flutter: "3.7.1" flutter: "3.7.3"
dependencies: dependencies:
adaptive_theme: ^3.0.0 adaptive_theme: ^3.0.0