Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 156 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,128 +10,196 @@ A [Hacker News](https://news.ycombinator.com/) client built with Flutter.

[<img src="assets/images/app_store_badge.png" height="50">](https://apps.apple.com/us/app/hacki/id1602043763?platform=iphone) [<img src="assets/images/google_play_badge.png" height="50">](https://play.google.com/store/apps/details?id=com.jiaqifeng.hacki&hl=en_US&gl=US) [<img src="assets/images/f_droid_badge.png" height="50">](https://f-droid.org/en/packages/com.jiaqifeng.hacki/)


Features:
- Log in using your Hacker News account.
- Browse stories from various categories.
- Search for stories.
- Submit stories.
- Pin stories.
- Mark stories as favorite.
- Leave comments.
- Collapse comments.
- View parent comments without scrolling up.
- View and participate in polls.
- Browse comments and stories you have posted.
- Vote on comments or stories.
- Get in-app notification when there is new reply to your stories or comments.
- Download stories and comments for offline reading.
- Pick up where you left off.
- Synced favorites and pins across devices. (iOS only)
- Export or import your favorites.
- Launch from system share sheet.
- Share story or comment as image.
# Features
- Hacker News account [login](#login-reply-notification-favorites-sync-and-more)
- [Favorites sync](#login-reply-notification-favorites-sync-and-more)
- [Hacker News Search](#hacker-news-search)
- [In-thread search](#in-thread-local-and-global-search)
- [Ancestor lookup](#ancestor-lookup) so you don't have to scroll back up to regain context
- [In-thread notification for new comments](#new-comments-notification-and-lookup) since your last visit
- [In-app notification for new replies](#login-reply-notification-favorites-sync-and-more) to your comments or stories
- [Offline mode](#settings)
- Synced settings across devices (iOS only)
- [Favorites import and export](#settings)
- Open Hacker News link in Hacki via system share dialog
- [Share story or comment as image](#share-story-or-comment-as-image)
- [Reply](#reply-to-comment-or-story), vote, filter, block
- [Polls](#polls)
- [True dark mode](#true-dark-mode)
- [Tablet support](#tablet-support)
- [Accent color](#thread) and [font customization](#accent-color-and-font-customization)
- And more...

## Home page and story tile customization
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_01.png">
<img width="200" src="assets/new_screenshots/hacki_04.png">
<img width="200" src="assets/new_screenshots/hacki_05.png">
<img width="200" src="assets/new_screenshots/hacki_08.png">
<img width="200" src="assets/new_screenshots/hacki_02.png">
<img width="200" src="assets/new_screenshots/hacki_03.png">
<img width="200" src="assets/new_screenshots/hacki_06.png">
<img width="200" src="assets/new_screenshots/hacki_07.png">
<img width="200" src="assets/new_screenshots/hacki_09.png">
<img width="200" src="assets/new_screenshots/hacki_10.png">
<img width="200" src="assets/new_screenshots/hacki_11.png">
<img width="200" src="assets/new_screenshots/hacki_12.png">
</p>

## Thread
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_21.png">
<img width="200" src="assets/new_screenshots/hacki_70.png">
<img width="200" src="assets/new_screenshots/hacki_22.png">
<img width="200" src="assets/new_screenshots/hacki_69.png">
</p>

# Home page and story tile customization
## New comments notification and lookup
<p align="center">
<img width="200" alt="01" src="assets/new_screenshots/hacki_01.png">
<img width="200" alt="07" src="assets/new_screenshots/hacki_04.png">
<img width="200" alt="03" src="assets/new_screenshots/hacki_05.png">
<img width="200" alt="09" src="assets/new_screenshots/hacki_08.png">
<img width="200" alt="06" src="assets/new_screenshots/hacki_02.png">
<img width="200" alt="02" src="assets/new_screenshots/hacki_03.png">
<img width="200" alt="08" src="assets/new_screenshots/hacki_06.png">
<img width="200" alt="04" src="assets/new_screenshots/hacki_07.png">
<img width="200" alt="05" src="assets/new_screenshots/hacki_09.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_10.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_11.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_12.png">
<img width="300" src="assets/new_screenshots/hacki_59.png">
<img width="300" src="assets/new_screenshots/hacki_60.png">
</p>

# Thread reading experience
## In-thread local and global search
<p align="center">
<img width="250" src="assets/new_screenshots/hacki_91.png">
<img width="250" src="assets/new_screenshots/hacki_93.png">
<img width="250" src="assets/new_screenshots/hacki_95.png">
<img width="250" src="assets/new_screenshots/hacki_101.png">
<img width="250" src="assets/new_screenshots/hacki_97.png">
<img width="250" src="assets/new_screenshots/hacki_99.png">
</p>
<p align="center">
<img width="250" src="assets/new_screenshots/hacki_92.png">
<img width="250" src="assets/new_screenshots/hacki_94.png">
<img width="250" src="assets/new_screenshots/hacki_96.png">
<img width="250" src="assets/new_screenshots/hacki_102.png">
<img width="250" src="assets/new_screenshots/hacki_98.png">
<img width="250" src="assets/new_screenshots/hacki_100.png">
</p>

## Ancestor lookup
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_61.png">
<img width="200" src="assets/new_screenshots/hacki_64.png">
<img width="200" src="assets/new_screenshots/hacki_65.png">
<img width="200" src="assets/new_screenshots/hacki_68.png">
</p>
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_62.png">
<img width="200" src="assets/new_screenshots/hacki_63.png">
<img width="200" src="assets/new_screenshots/hacki_66.png">
<img width="200" src="assets/new_screenshots/hacki_67.png">
</p>

### Thread
## Share story or comment as image
<p align="center">
<img width="200" alt="01" src="assets/new_screenshots/hacki_21.png">
<img width="200" alt="06" src="assets/new_screenshots/hacki_22.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_69.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_70.png">
<img width="250" src="assets/new_screenshots/hacki_103.png">
<img width="250" src="assets/new_screenshots/hacki_105.png">
<img width="250" src="assets/new_screenshots/hacki_107.png">
<img width="250" src="assets/new_screenshots/hacki_109.png">
<img width="250" src="assets/new_screenshots/hacki_111.png">
<img width="250" src="assets/new_screenshots/hacki_113.png">
</p>

### New comments notification and lookup
<p align="center">
<img width="300" alt="10" src="assets/new_screenshots/hacki_59.png">
<img width="300" alt="10" src="assets/new_screenshots/hacki_60.png">
<img width="250" src="assets/new_screenshots/hacki_104.png">
<img width="250" src="assets/new_screenshots/hacki_106.png">
<img width="250" src="assets/new_screenshots/hacki_108.png">
<img width="250" src="assets/new_screenshots/hacki_110.png">
<img width="250" src="assets/new_screenshots/hacki_112.png">
<img width="250" src="assets/new_screenshots/hacki_114.png">
</p>

### In-thread search and other actions
## Reply to comment or story
<p align="center">
<img width="200" alt="02" src="assets/new_screenshots/hacki_23.png">
<img width="200" alt="03" src="assets/new_screenshots/hacki_25.png">
<img width="200" alt="09" src="assets/new_screenshots/hacki_28.png">
<img width="200" alt="05" src="assets/new_screenshots/hacki_29.png">
<img width="200" alt="07" src="assets/new_screenshots/hacki_24.png">
<img width="200" alt="08" src="assets/new_screenshots/hacki_26.png">
<img width="200" alt="04" src="assets/new_screenshots/hacki_27.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_30.png">
<img width="200" src="assets/new_screenshots/hacki_115.png">
<img width="200" src="assets/new_screenshots/hacki_117.png">
<img width="200" src="assets/new_screenshots/hacki_119.png">
<img width="200" src="assets/new_screenshots/hacki_121.png">
</p>
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_116.png">
<img width="200" src="assets/new_screenshots/hacki_118.png">
<img width="200" src="assets/new_screenshots/hacki_120.png">
<img width="200" src="assets/new_screenshots/hacki_122.png">
</p>

### Ancestor lookup
## Open comment in separate thread
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_135.png">
<img width="200" src="assets/new_screenshots/hacki_137.png">
<img width="200" src="assets/new_screenshots/hacki_139.png">
<img width="200" src="assets/new_screenshots/hacki_141.png">
</p>
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_61.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_64.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_65.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_68.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_62.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_63.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_66.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_67.png">
<img width="200" src="assets/new_screenshots/hacki_136.png">
<img width="200" src="assets/new_screenshots/hacki_138.png">
<img width="200" src="assets/new_screenshots/hacki_140.png">
<img width="200" src="assets/new_screenshots/hacki_142.png">
</p>

### Story and comment sharing
# Hacker News search
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_85.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_88.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_89.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_84.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_86.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_87.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_90.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_83.png">
<img width="250" src="assets/new_screenshots/hacki_129.png">
<img width="250" src="assets/new_screenshots/hacki_131.png">
<img width="250" src="assets/new_screenshots/hacki_133.png">
</p>
<p align="center">
<img width="250" src="assets/new_screenshots/hacki_130.png">
<img width="250" src="assets/new_screenshots/hacki_132.png">
<img width="250" src="assets/new_screenshots/hacki_134.png">
</p>

# Login, reply notification, favorites sync and more
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_37.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_39.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_47.png">
<img width="250" src="assets/new_screenshots/hacki_37.png">
<img width="250" src="assets/new_screenshots/hacki_39.png">
<img width="250" src="assets/new_screenshots/hacki_47.png">
</p>
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_38.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_40.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_48.png">
<img width="250" src="assets/new_screenshots/hacki_38.png">
<img width="250" src="assets/new_screenshots/hacki_40.png">
<img width="250" src="assets/new_screenshots/hacki_48.png">
</p>

# Settings
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_71.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_74.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_75.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_78.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_72.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_73.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_76.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_77.png">
<img width="200" src="assets/new_screenshots/hacki_71.png">
<img width="200" src="assets/new_screenshots/hacki_74.png">
<img width="200" src="assets/new_screenshots/hacki_75.png">
<img width="200" src="assets/new_screenshots/hacki_78.png">
</p>

<p align="center">
<img width="200" src="assets/new_screenshots/hacki_72.png">
<img width="200" src="assets/new_screenshots/hacki_73.png">
<img width="200" src="assets/new_screenshots/hacki_76.png">
<img width="200" src="assets/new_screenshots/hacki_77.png">
</p>

# Accent color and font customization
<p align="center">
<img width="200" alt="10" src="assets/new_screenshots/hacki_79.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_80.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_81.png">
<img width="200" alt="10" src="assets/new_screenshots/hacki_82.png">
<img width="200" src="assets/new_screenshots/hacki_79.png">
<img width="200" src="assets/new_screenshots/hacki_80.png">
<img width="200" src="assets/new_screenshots/hacki_81.png">
<img width="200" src="assets/new_screenshots/hacki_82.png">
</p>

# True dark mode
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_143.png">
<img width="200" src="assets/new_screenshots/hacki_145.png">
<img width="200" src="assets/new_screenshots/hacki_144.png">
<img width="200" src="assets/new_screenshots/hacki_146.png">
</p>

# Polls
<p align="center">
<img width="200" src="assets/new_screenshots/hacki_147.png">
<img width="200" src="assets/new_screenshots/hacki_148.png">
<img width="200" src="assets/new_screenshots/hacki_149.png">
<img width="200" src="assets/new_screenshots/hacki_150.png">
</p>

# Tablet support
Expand Down
Binary file added assets/new_screenshots/hacki_100.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_101.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_102.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_103.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_104.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_105.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_106.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_107.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_108.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_109.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_110.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_111.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_112.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_113.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_114.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_115.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_116.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_117.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_118.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_119.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_120.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_121.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_122.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_123.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_124.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_screenshots/hacki_125.png
Binary file added assets/new_screenshots/hacki_126.png
Binary file added assets/new_screenshots/hacki_127.png
Binary file added assets/new_screenshots/hacki_128.png
Binary file added assets/new_screenshots/hacki_129.png
Binary file added assets/new_screenshots/hacki_130.png
Binary file added assets/new_screenshots/hacki_131.png
Binary file added assets/new_screenshots/hacki_132.png
Binary file added assets/new_screenshots/hacki_133.png
Binary file added assets/new_screenshots/hacki_134.png
Binary file added assets/new_screenshots/hacki_135.png
Binary file added assets/new_screenshots/hacki_136.png
Binary file added assets/new_screenshots/hacki_137.png
Binary file added assets/new_screenshots/hacki_138.png
Binary file added assets/new_screenshots/hacki_139.png
Binary file added assets/new_screenshots/hacki_140.png
Binary file added assets/new_screenshots/hacki_141.png
Binary file added assets/new_screenshots/hacki_142.png
Binary file added assets/new_screenshots/hacki_143.png
Binary file added assets/new_screenshots/hacki_144.png
Binary file added assets/new_screenshots/hacki_145.png
Binary file added assets/new_screenshots/hacki_146.png
Binary file added assets/new_screenshots/hacki_147.png
Binary file added assets/new_screenshots/hacki_148.png
Binary file added assets/new_screenshots/hacki_149.png
Binary file added assets/new_screenshots/hacki_150.png
Binary file added assets/new_screenshots/hacki_91.png
Binary file added assets/new_screenshots/hacki_92.png
Binary file added assets/new_screenshots/hacki_93.png
Binary file added assets/new_screenshots/hacki_94.png
Binary file added assets/new_screenshots/hacki_95.png
Binary file added assets/new_screenshots/hacki_96.png
Binary file added assets/new_screenshots/hacki_97.png
Binary file added assets/new_screenshots/hacki_98.png
Binary file added assets/new_screenshots/hacki_99.png
2 changes: 2 additions & 0 deletions lib/screens/item/item_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ class _ItemScreenState extends State<ItemScreen>
rect,
parent: item,
onSearchInThreadTapped: () {
context.pop();
context.read<CommentsCubit>()
..search(item.by)
..openInThreadSearch?.call();
Expand Down Expand Up @@ -418,6 +419,7 @@ class _ItemScreenState extends State<ItemScreen>
rect,
parent: widget.item,
onSearchInThreadTapped: () {
context.pop();
context.read<CommentsCubit>()
..search(item.by)
..openInThreadSearch?.call();
Expand Down
2 changes: 1 addition & 1 deletion lib/screens/item/widgets/item_screen_background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class _ItemScreenBackgroundState extends State<ItemScreenBackground> {

unawaited(
Future<void>.delayed(
AppDurations.oneAndHalfSeconds,
AppDurations.oneSecond,
() {
if (mounted) {
setState(() {
Expand Down
9 changes: 4 additions & 5 deletions lib/screens/item/widgets/main_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ class _ParentItemSection extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.only(
left: Dimens.pt8,
bottom: Dimens.pt8,
),
child: ItemText(
item: item,
Expand All @@ -488,20 +489,18 @@ class _ParentItemSection extends StatelessWidget {
);
},
),
if (item is Story && item.isPoll)
if (item is Story && item.isPoll) ...<Widget>[
BlocProvider<PollCubit>(
create: (BuildContext context) =>
PollCubit(story: item)..init(),
child: const PollView(),
),
SizedBoxes.pt6,
],
],
),
),
),
if (item.text.isNotEmpty)
const SizedBox(
height: Dimens.pt8,
),
const Divider(
height: Dimens.zero,
),
Expand Down
3 changes: 0 additions & 3 deletions lib/screens/item/widgets/poll_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ class _PollViewState extends State<PollView> with ItemActionMixin {
builder: (BuildContext context, PollState state) {
return Column(
children: <Widget>[
const SizedBox(
height: Dimens.pt24,
),
if (state.status == Status.inProgress) ...<Widget>[
const LinearProgressIndicator(),
const SizedBox(
Expand Down
2 changes: 1 addition & 1 deletion lib/screens/item/widgets/reply_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class _ReplyBoxState extends State<ReplyBox> with ItemActionMixin {
),
if (!isLoading) ...<Widget>[
...<Widget>[
if (replyingTo != null)
if (replyingTo != null && replyingTo is Comment)
AnimatedOpacity(
opacity:
expanded ? NumSwitch.on : NumSwitch.off,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: hacki
description: A Hacker News client.
version: 3.5.2+352
version: 3.6.0+360
publish_to: none

environment:
Expand Down