mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-06 18:24:42 +08:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
764ff09345 | |||
ab449adce2 | |||
2ec41b26f2 |
@ -1,14 +1,13 @@
|
||||
|
||||
# <img width="64" src="https://user-images.githubusercontent.com/7277662/167775086-0b234f28-dee4-44f6-aae4-14a28ed4bbb6.png"> Hacki for Hacker News
|
||||
|
||||
A simple noiseless [Hacker News](https://news.ycombinator.com/) client made with Flutter that is just enough.
|
||||
A [Hacker News](https://news.ycombinator.com/) client made with Flutter that is just enough.
|
||||
|
||||
[](https://apps.apple.com/us/app/hacki/id1602043763?platform=iphone)
|
||||
[](https://f-droid.org/en/packages/com.jiaqifeng.hacki/)
|
||||
[](https://github.com/Livinglist/Hacki/releases/latest)
|
||||
[](https://badges.pufler.dev)
|
||||
[](https://img.shields.io/github/stars/livinglist/Hacki?style=social)
|
||||
[](https://pub.dev/packages/effective_dart)
|
||||
[](https://img.shields.io/github/stars/livinglist/Hacki?style=social)
|
||||
|
||||
[<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/)
|
||||
|
||||
|
3
fastlane/metadata/android/en-US/changelogs/71.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/71.txt
Normal file
@ -0,0 +1,3 @@
|
||||
- Lazy loading.
|
||||
- Offline mode now includes web pages.
|
||||
- You can now sort comments in story screen.
|
3
fastlane/metadata/android/en-US/changelogs/72.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/72.txt
Normal file
@ -0,0 +1,3 @@
|
||||
- Lazy loading.
|
||||
- Offline mode now includes web pages.
|
||||
- You can now sort comments in story screen.
|
@ -568,7 +568,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@ -577,7 +577,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 0.2.28;
|
||||
MARKETING_VERSION = 0.2.29;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@ -705,7 +705,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@ -714,7 +714,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 0.2.28;
|
||||
MARKETING_VERSION = 0.2.29;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@ -736,7 +736,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@ -745,7 +745,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 0.2.28;
|
||||
MARKETING_VERSION = 0.2.29;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -33,7 +33,8 @@ class NotificationCubit extends Cubit<NotificationState> {
|
||||
_preferenceRepository.shouldShowNotification
|
||||
.then((bool showNotification) {
|
||||
if (showNotification) {
|
||||
init();
|
||||
// Delaying the initialization to prevent janks in home screen.
|
||||
Future<void>.delayed(const Duration(seconds: 2), init);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hacki/config/locator.dart';
|
||||
import 'package:hacki/cubits/comments/comments_cubit.dart';
|
||||
import 'package:hacki/repositories/repositories.dart';
|
||||
@ -82,12 +83,14 @@ class PreferenceCubit extends Cubit<PreferenceState> {
|
||||
|
||||
void selectFetchMode(FetchMode? fetchMode) {
|
||||
if (fetchMode == null || state.fetchMode == fetchMode) return;
|
||||
HapticFeedback.lightImpact();
|
||||
emit(state.copyWith(fetchMode: fetchMode));
|
||||
_preferenceRepository.selectFetchMode(fetchMode);
|
||||
}
|
||||
|
||||
void selectCommentsOrder(CommentsOrder? order) {
|
||||
if (order == null || state.order == order) return;
|
||||
HapticFeedback.lightImpact();
|
||||
emit(state.copyWith(order: order));
|
||||
_preferenceRepository.selectCommentsOrder(order);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
extension TryReadContext on BuildContext {
|
||||
extension ContextExtension on BuildContext {
|
||||
T? tryRead<T>() {
|
||||
try {
|
||||
return read<T>();
|
||||
|
@ -7,10 +7,8 @@ extension DateTimeExtension on DateTime {
|
||||
return '$gap year${gap == 1 ? '' : 's'} ago';
|
||||
} else if (diff.inDays > 30) {
|
||||
int gap = now.month - month;
|
||||
if (gap == 0) {
|
||||
gap = 1;
|
||||
} else if (gap < 0) {
|
||||
gap = now.month + (12 - month);
|
||||
if (gap <= 0) {
|
||||
gap = now.month + 12 - month;
|
||||
}
|
||||
return '$gap month${gap == 1 ? '' : 's'} ago';
|
||||
} else if (diff.inDays >= 1) {
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class User {
|
||||
@ -39,8 +37,6 @@ class User {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final String prettyString =
|
||||
const JsonEncoder.withIndent(' ').convert(this);
|
||||
return 'User $prettyString';
|
||||
return 'User $about, $created, $delay, $id, $karma';
|
||||
}
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
Text(
|
||||
'''${state.item.score} karma, ${state.item.descendants} comment${state.item.descendants > 1 ? 's' : ''}''',
|
||||
style: const TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
] else ...<Widget>[
|
||||
@ -526,7 +526,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
: const Text(
|
||||
'View parent thread',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -542,7 +542,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
child: Text(
|
||||
'Lazy',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -551,7 +551,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
child: Text(
|
||||
'Eager',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -573,7 +573,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
child: Text(
|
||||
'Natural',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -582,7 +582,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
child: Text(
|
||||
'Newest first',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -591,7 +591,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
||||
child: Text(
|
||||
'Oldest first',
|
||||
style: TextStyle(
|
||||
fontSize: TextDimens.pt12,
|
||||
fontSize: TextDimens.pt13,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -526,7 +526,7 @@ class _ProfileScreenState extends State<ProfileScreen>
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
applicationName: 'Hacki',
|
||||
applicationVersion: 'v0.2.28',
|
||||
applicationVersion: 'v0.2.29',
|
||||
applicationIcon: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(
|
||||
|
@ -27,6 +27,7 @@ abstract class TextDimens {
|
||||
static const double pt8 = 8;
|
||||
static const double pt10 = 10;
|
||||
static const double pt12 = 12;
|
||||
static const double pt13 = 13;
|
||||
static const double pt14 = 14;
|
||||
static const double pt15 = 15;
|
||||
static const double pt16 = 16;
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: hacki
|
||||
description: A Hacker News reader.
|
||||
version: 0.2.28+70
|
||||
version: 0.2.29+72
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
Reference in New Issue
Block a user