mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-06 18:24:42 +08:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
a2c66a0075 | |||
5f43fd6968 | |||
d83381a7fd | |||
764ff09345 | |||
ab449adce2 | |||
2ec41b26f2 |
4
.github/workflows/github-actions.yml
vendored
4
.github/workflows/github-actions.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: "11.0"
|
JAVA_VERSION: "11.0"
|
||||||
FLUTTER_VERSION: "3.0.3"
|
FLUTTER_VERSION: "3.3.2"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v2
|
- uses: actions/setup-java@v2
|
||||||
@ -20,7 +20,7 @@ jobs:
|
|||||||
java-version: '17'
|
java-version: '17'
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
flutter-version: '3.0.3'
|
flutter-version: '3.3.2'
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter analyze
|
- run: flutter analyze
|
||||||
|
@ -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
|
# <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://apps.apple.com/us/app/hacki/id1602043763?platform=iphone)
|
||||||
[](https://f-droid.org/en/packages/com.jiaqifeng.hacki/)
|
[](https://f-droid.org/en/packages/com.jiaqifeng.hacki/)
|
||||||
[](https://github.com/Livinglist/Hacki/releases/latest)
|
[](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://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/)
|
[<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/)
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ if (keystorePropertiesFile.exists()) {
|
|||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 32
|
compileSdkVersion 33
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
@ -51,7 +51,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.jiaqifeng.hacki"
|
applicationId "com.jiaqifeng.hacki"
|
||||||
minSdkVersion 26
|
minSdkVersion 26
|
||||||
targetSdkVersion 32
|
targetSdkVersion 33
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
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.
|
3
fastlane/metadata/android/en-US/changelogs/73.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/73.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Lazy loading.
|
||||||
|
- Offline mode now includes web pages.
|
||||||
|
- You can now sort comments in story screen.
|
2
fastlane/metadata/android/en-US/changelogs/74.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/74.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Bumped Flutter version.
|
||||||
|
- Updated navigation bar background color.
|
@ -1,46 +0,0 @@
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:hacki/main.dart' as app;
|
|
||||||
import 'package:hacki/screens/widgets/story_tile.dart';
|
|
||||||
import 'package:integration_test/integration_test.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
|
|
||||||
group('performance test', () {
|
|
||||||
testWidgets('scrolling performance on ItemScreen',
|
|
||||||
(WidgetTester tester) async {
|
|
||||||
await app.main(testing: true);
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
final Finder bestStoryTabFinder = find.text('BEST');
|
|
||||||
|
|
||||||
await tester.tap(bestStoryTabFinder);
|
|
||||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
|
||||||
|
|
||||||
final Finder storyTileFinder = find.byType(StoryTile);
|
|
||||||
|
|
||||||
await tester.tap(storyTileFinder.first);
|
|
||||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
|
||||||
|
|
||||||
TestGesture gesture = await tester.startGesture(const Offset(0, 300));
|
|
||||||
await gesture.moveBy(const Offset(0, -300));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
gesture = await tester.startGesture(const Offset(0, 300));
|
|
||||||
await gesture.moveBy(const Offset(0, -300));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
gesture = await tester.startGesture(const Offset(0, 300));
|
|
||||||
await gesture.moveBy(const Offset(0, -300));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
gesture = await tester.startGesture(const Offset(0, 300));
|
|
||||||
await gesture.moveBy(const Offset(0, 900));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
gesture = await tester.startGesture(const Offset(0, 300));
|
|
||||||
await gesture.moveBy(const Offset(0, -900));
|
|
||||||
await tester.pump();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
68
integration_test/scrolling_test.dart
Normal file
68
integration_test/scrolling_test.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:hacki/main.dart' as app;
|
||||||
|
import 'package:hacki/screens/widgets/widgets.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final IntegrationTestWidgetsFlutterBinding binding =
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
testWidgets('Scrolling test', (WidgetTester tester) async {
|
||||||
|
await app.main(testing: true);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
final Finder bestTabFinder = find.widgetWithText(Tab, 'BEST');
|
||||||
|
|
||||||
|
expect(bestTabFinder, findsOneWidget);
|
||||||
|
|
||||||
|
Future<void> scrollDown(WidgetTester tester) async {
|
||||||
|
await tester.timedDragFrom(
|
||||||
|
const Offset(100, 200),
|
||||||
|
const Offset(100, -700),
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> scrollUp(WidgetTester tester) async {
|
||||||
|
await tester.timedDragFrom(
|
||||||
|
const Offset(100, 200),
|
||||||
|
const Offset(100, 700),
|
||||||
|
const Duration(seconds: 1),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
}
|
||||||
|
|
||||||
|
await binding.traceAction(
|
||||||
|
() async {
|
||||||
|
await tester.tap(bestTabFinder);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
const int count = 10;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
await scrollDown(tester);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count - 3; i++) {
|
||||||
|
await scrollUp(tester);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
final Finder storyFinder = find.byType(StoryTile);
|
||||||
|
|
||||||
|
expect(storyFinder, findsWidgets);
|
||||||
|
|
||||||
|
final Finder firstStoryFinder = storyFinder.first;
|
||||||
|
|
||||||
|
expect(firstStoryFinder, findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(firstStoryFinder);
|
||||||
|
await tester.pump(const Duration(seconds: 4));
|
||||||
|
},
|
||||||
|
reportKey: 'scrolling_timeline',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>9.0</string>
|
<string>11.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '13.0'
|
# platform :ios, '11.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
@ -37,8 +37,5 @@ end
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
target.build_configurations.each do |config|
|
|
||||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -108,7 +108,7 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
|
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
||||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
@ -128,6 +128,6 @@ SPEC CHECKSUMS:
|
|||||||
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
|
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
|
||||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||||
|
|
||||||
PODFILE CHECKSUM: e4c97c7a9aacaeda4b952f7ef9ea29e47660f622
|
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||||
|
|
||||||
COCOAPODS: 1.11.2
|
COCOAPODS: 1.11.2
|
||||||
|
@ -549,7 +549,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@ -568,16 +568,16 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.2.28;
|
MARKETING_VERSION = 0.2.31;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@ -635,7 +635,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@ -684,7 +684,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@ -705,16 +705,16 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.2.28;
|
MARKETING_VERSION = 0.2.31;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@ -736,16 +736,16 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
DEVELOPMENT_TEAM = QMWX3X2NF7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.2.28;
|
MARKETING_VERSION = 0.2.31;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jiaqi.hacki;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
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/extensions/extensions.dart';
|
||||||
import 'package:hacki/models/models.dart';
|
import 'package:hacki/models/models.dart';
|
||||||
import 'package:hacki/services/services.dart';
|
import 'package:hacki/services/services.dart';
|
||||||
import 'package:hacki/utils/debouncer.dart';
|
import 'package:hacki/utils/debouncer.dart';
|
||||||
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
|
|
||||||
part 'edit_state.dart';
|
part 'edit_state.dart';
|
||||||
|
|
||||||
class EditCubit extends Cubit<EditState> {
|
class EditCubit extends HydratedCubit<EditState> {
|
||||||
EditCubit({DraftCache? draftCache})
|
EditCubit({DraftCache? draftCache})
|
||||||
: _draftCache = draftCache ?? locator.get<DraftCache>(),
|
: _draftCache = draftCache ?? locator.get<DraftCache>(),
|
||||||
_debouncer = Debouncer(delay: const Duration(seconds: 1)),
|
_debouncer = Debouncer(delay: const Duration(seconds: 1)),
|
||||||
@ -47,6 +48,7 @@ class EditCubit extends Cubit<EditState> {
|
|||||||
_draftCache.removeDraft(replyingTo: state.replyingTo!.id);
|
_draftCache.removeDraft(replyingTo: state.replyingTo!.id);
|
||||||
}
|
}
|
||||||
emit(const EditState.init());
|
emit(const EditState.init());
|
||||||
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTextChanged(String text) {
|
void onTextChanged(String text) {
|
||||||
@ -61,4 +63,54 @@ class EditCubit extends Cubit<EditState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deleteDraft() => clear();
|
||||||
|
|
||||||
|
bool called = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
EditState? fromJson(Map<String, dynamic> json) {
|
||||||
|
final String text = json['text'] as String? ?? '';
|
||||||
|
final Map<String, dynamic>? itemJson =
|
||||||
|
json['item'] as Map<String, dynamic>?;
|
||||||
|
final Item? replyingTo = itemJson == null ? null : Item.fromJson(itemJson);
|
||||||
|
|
||||||
|
if (replyingTo != null && text.isNotEmpty) {
|
||||||
|
_draftCache.cacheDraft(text: text, replyingTo: replyingTo.id);
|
||||||
|
|
||||||
|
final EditState state = EditState(
|
||||||
|
text: text,
|
||||||
|
replyingTo: replyingTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
_cachedState = state;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic>? toJson(EditState state) {
|
||||||
|
EditState selected = state;
|
||||||
|
|
||||||
|
if (state.replyingTo == null ||
|
||||||
|
(state.replyingTo?.id != _cachedState.replyingTo?.id &&
|
||||||
|
state.text.isNullOrEmpty)) {
|
||||||
|
selected = _cachedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected.text.isNullOrEmpty) {
|
||||||
|
clear();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <String, dynamic>{
|
||||||
|
'text': selected.text ?? '',
|
||||||
|
'item': selected.replyingTo?.toJson(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static EditState _cachedState = const EditState.init();
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,8 @@ class NotificationCubit extends Cubit<NotificationState> {
|
|||||||
_preferenceRepository.shouldShowNotification
|
_preferenceRepository.shouldShowNotification
|
||||||
.then((bool showNotification) {
|
.then((bool showNotification) {
|
||||||
if (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:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:hacki/config/locator.dart';
|
import 'package:hacki/config/locator.dart';
|
||||||
import 'package:hacki/cubits/comments/comments_cubit.dart';
|
import 'package:hacki/cubits/comments/comments_cubit.dart';
|
||||||
import 'package:hacki/repositories/repositories.dart';
|
import 'package:hacki/repositories/repositories.dart';
|
||||||
@ -82,12 +83,14 @@ class PreferenceCubit extends Cubit<PreferenceState> {
|
|||||||
|
|
||||||
void selectFetchMode(FetchMode? fetchMode) {
|
void selectFetchMode(FetchMode? fetchMode) {
|
||||||
if (fetchMode == null || state.fetchMode == fetchMode) return;
|
if (fetchMode == null || state.fetchMode == fetchMode) return;
|
||||||
|
HapticFeedback.lightImpact();
|
||||||
emit(state.copyWith(fetchMode: fetchMode));
|
emit(state.copyWith(fetchMode: fetchMode));
|
||||||
_preferenceRepository.selectFetchMode(fetchMode);
|
_preferenceRepository.selectFetchMode(fetchMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectCommentsOrder(CommentsOrder? order) {
|
void selectCommentsOrder(CommentsOrder? order) {
|
||||||
if (order == null || state.order == order) return;
|
if (order == null || state.order == order) return;
|
||||||
|
HapticFeedback.lightImpact();
|
||||||
emit(state.copyWith(order: order));
|
emit(state.copyWith(order: order));
|
||||||
_preferenceRepository.selectCommentsOrder(order);
|
_preferenceRepository.selectCommentsOrder(order);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ 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';
|
||||||
|
|
||||||
extension TryReadContext on BuildContext {
|
extension ContextExtension on BuildContext {
|
||||||
T? tryRead<T>() {
|
T? tryRead<T>() {
|
||||||
try {
|
try {
|
||||||
return read<T>();
|
return read<T>();
|
||||||
@ -22,7 +22,7 @@ extension TryReadContext on BuildContext {
|
|||||||
static double _screenWidth = 0;
|
static double _screenWidth = 0;
|
||||||
static double _storyTileHeight = 0;
|
static double _storyTileHeight = 0;
|
||||||
static int _storyTileMaxLines = 4;
|
static int _storyTileMaxLines = 4;
|
||||||
static const double _screenWidthLowerBound = 428,
|
static const double _screenWidthLowerBound = 430,
|
||||||
_screenWidthUpperBound = 850,
|
_screenWidthUpperBound = 850,
|
||||||
_picHeightLowerBound = 110,
|
_picHeightLowerBound = 110,
|
||||||
_picHeightUpperBound = 128,
|
_picHeightUpperBound = 128,
|
||||||
|
@ -7,10 +7,8 @@ extension DateTimeExtension on DateTime {
|
|||||||
return '$gap year${gap == 1 ? '' : 's'} ago';
|
return '$gap year${gap == 1 ? '' : 's'} ago';
|
||||||
} else if (diff.inDays > 30) {
|
} else if (diff.inDays > 30) {
|
||||||
int gap = now.month - month;
|
int gap = now.month - month;
|
||||||
if (gap == 0) {
|
if (gap <= 0) {
|
||||||
gap = 1;
|
gap = now.month + 12 - month;
|
||||||
} else if (gap < 0) {
|
|
||||||
gap = now.month + (12 - month);
|
|
||||||
}
|
}
|
||||||
return '$gap month${gap == 1 ? '' : 's'} ago';
|
return '$gap month${gap == 1 ? '' : 's'} ago';
|
||||||
} else if (diff.inDays >= 1) {
|
} else if (diff.inDays >= 1) {
|
||||||
|
@ -13,3 +13,12 @@ extension StringExtension on String {
|
|||||||
return replaceAllMapped(regex, (_) => '');
|
return replaceAllMapped(regex, (_) => '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension OptionalStringExtension on String? {
|
||||||
|
bool get isNullOrEmpty {
|
||||||
|
if (this == null) return true;
|
||||||
|
return this!.trim().isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get isNotNullOrEmpty => !isNullOrEmpty;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:feature_discovery/feature_discovery.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:flutter_siri_suggestions/flutter_siri_suggestions.dart';
|
import 'package:flutter_siri_suggestions/flutter_siri_suggestions.dart';
|
||||||
@ -19,6 +20,7 @@ import 'package:hacki/services/custom_bloc_observer.dart';
|
|||||||
import 'package:hacki/services/fetcher.dart';
|
import 'package:hacki/services/fetcher.dart';
|
||||||
import 'package:hacki/styles/styles.dart';
|
import 'package:hacki/styles/styles.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:rxdart/rxdart.dart' show BehaviorSubject;
|
import 'package:rxdart/rxdart.dart' show BehaviorSubject;
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -39,6 +41,12 @@ Future<void> main({bool testing = false}) async {
|
|||||||
|
|
||||||
isTesting = testing;
|
isTesting = testing;
|
||||||
|
|
||||||
|
final HydratedStorage storage = await HydratedStorage.build(
|
||||||
|
storageDirectory: kIsWeb
|
||||||
|
? HydratedStorage.webStorageDirectory
|
||||||
|
: await getTemporaryDirectory(),
|
||||||
|
);
|
||||||
|
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
unawaited(
|
unawaited(
|
||||||
Workmanager().initialize(
|
Workmanager().initialize(
|
||||||
@ -79,6 +87,19 @@ Future<void> main({bool testing = false}) async {
|
|||||||
siriSuggestionSubject.add(storyId);
|
siriSuggestionSubject.add(storyId);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else if (Platform.isAndroid) {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(
|
||||||
|
const SystemUiOverlayStyle(
|
||||||
|
statusBarColor: Colors.transparent,
|
||||||
|
systemNavigationBarColor: Colors.transparent,
|
||||||
|
systemNavigationBarDividerColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await SystemChrome.setEnabledSystemUIMode(
|
||||||
|
SystemUiMode.edgeToEdge,
|
||||||
|
overlays: <SystemUiOverlay>[SystemUiOverlay.top],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Directory tempDir = await getTemporaryDirectory();
|
final Directory tempDir = await getTemporaryDirectory();
|
||||||
@ -92,26 +113,15 @@ Future<void> main({bool testing = false}) async {
|
|||||||
final bool trueDarkMode =
|
final bool trueDarkMode =
|
||||||
prefs.getBool(PreferenceRepository.trueDarkModeKey) ?? false;
|
prefs.getBool(PreferenceRepository.trueDarkModeKey) ?? false;
|
||||||
|
|
||||||
if (kReleaseMode) {
|
Bloc.observer = CustomBlocObserver();
|
||||||
|
HydratedBloc.storage = storage;
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
HackiApp(
|
HackiApp(
|
||||||
savedThemeMode: savedThemeMode,
|
savedThemeMode: savedThemeMode,
|
||||||
trueDarkMode: trueDarkMode,
|
trueDarkMode: trueDarkMode,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
BlocOverrides.runZoned(
|
|
||||||
() {
|
|
||||||
runApp(
|
|
||||||
HackiApp(
|
|
||||||
savedThemeMode: savedThemeMode,
|
|
||||||
trueDarkMode: trueDarkMode,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
blocObserver: CustomBlocObserver(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HackiApp extends StatelessWidget {
|
class HackiApp extends StatelessWidget {
|
||||||
@ -187,6 +197,10 @@ class HackiApp extends StatelessWidget {
|
|||||||
lazy: false,
|
lazy: false,
|
||||||
create: (BuildContext context) => PostCubit(),
|
create: (BuildContext context) => PostCubit(),
|
||||||
),
|
),
|
||||||
|
BlocProvider<EditCubit>(
|
||||||
|
lazy: false,
|
||||||
|
create: (BuildContext context) => EditCubit(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: AdaptiveTheme(
|
child: AdaptiveTheme(
|
||||||
light: ThemeData(
|
light: ThemeData(
|
||||||
|
@ -59,6 +59,7 @@ class Comment extends Item {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, dynamic> toJson() => <String, dynamic>{
|
Map<String, dynamic> toJson() => <String, dynamic>{
|
||||||
'id': id,
|
'id': id,
|
||||||
'time': time,
|
'time': time,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:hacki/extensions/date_time_extension.dart';
|
import 'package:hacki/extensions/date_time_extension.dart';
|
||||||
|
|
||||||
abstract class Item extends Equatable {
|
class Item extends Equatable {
|
||||||
const Item({
|
const Item({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.deleted,
|
required this.deleted,
|
||||||
@ -35,6 +35,22 @@ abstract class Item extends Equatable {
|
|||||||
text = '',
|
text = '',
|
||||||
type = '';
|
type = '';
|
||||||
|
|
||||||
|
Item.fromJson(Map<String, dynamic> json)
|
||||||
|
: id = json['id'] as int? ?? 0,
|
||||||
|
score = json['score'] as int? ?? 0,
|
||||||
|
descendants = json['descendants'] as int? ?? 0,
|
||||||
|
time = json['time'] as int? ?? 0,
|
||||||
|
by = json['by'] as String? ?? '',
|
||||||
|
title = json['title'] as String? ?? '',
|
||||||
|
text = json['text'] as String? ?? '',
|
||||||
|
url = json['url'] as String? ?? '',
|
||||||
|
kids = <int>[],
|
||||||
|
dead = json['dead'] as bool? ?? false,
|
||||||
|
deleted = json['deleted'] as bool? ?? false,
|
||||||
|
parent = json['parent'] as int? ?? 0,
|
||||||
|
parts = <int>[],
|
||||||
|
type = json['type'] as String? ?? '';
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
final int time;
|
final int time;
|
||||||
final int score;
|
final int score;
|
||||||
@ -65,4 +81,40 @@ abstract class Item extends Equatable {
|
|||||||
bool get isJob => type == 'job';
|
bool get isJob => type == 'job';
|
||||||
|
|
||||||
bool get isComment => type == 'comment';
|
bool get isComment => type == 'comment';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return <String, dynamic>{
|
||||||
|
'descendants': descendants,
|
||||||
|
'id': id,
|
||||||
|
'score': score,
|
||||||
|
'time': time,
|
||||||
|
'by': by,
|
||||||
|
'title': title,
|
||||||
|
'url': url,
|
||||||
|
'kids': kids,
|
||||||
|
'text': text,
|
||||||
|
'dead': dead,
|
||||||
|
'deleted': deleted,
|
||||||
|
'type': type,
|
||||||
|
'parts': parts,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => <Object?>[
|
||||||
|
id,
|
||||||
|
deleted,
|
||||||
|
by,
|
||||||
|
time,
|
||||||
|
text,
|
||||||
|
dead,
|
||||||
|
parent,
|
||||||
|
kids,
|
||||||
|
url,
|
||||||
|
score,
|
||||||
|
title,
|
||||||
|
type,
|
||||||
|
parts,
|
||||||
|
descendants,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@ class PollOption extends Item {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'descendants': descendants,
|
'descendants': descendants,
|
||||||
|
@ -91,6 +91,7 @@ class Story extends Item {
|
|||||||
String get simpleMetadata =>
|
String get simpleMetadata =>
|
||||||
'''$score point${score > 1 ? 's' : ''} $descendants comment${descendants > 1 ? 's' : ''} $postedDate''';
|
'''$score point${score > 1 ? 's' : ''} $descendants comment${descendants > 1 ? 's' : ''} $postedDate''';
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'descendants': descendants,
|
'descendants': descendants,
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class User {
|
class User {
|
||||||
@ -39,8 +37,6 @@ class User {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
final String prettyString =
|
return 'User $about, $created, $delay, $id, $karma';
|
||||||
const JsonEncoder.withIndent(' ').convert(this);
|
|
||||||
return 'User $prettyString';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,10 +96,6 @@ class ItemScreen extends StatefulWidget {
|
|||||||
useCommentCache: args.useCommentCache,
|
useCommentCache: args.useCommentCache,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<EditCubit>(
|
|
||||||
lazy: false,
|
|
||||||
create: (BuildContext context) => EditCubit(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
child: ItemScreen(
|
child: ItemScreen(
|
||||||
item: args.item,
|
item: args.item,
|
||||||
@ -141,10 +137,6 @@ class ItemScreen extends StatefulWidget {
|
|||||||
targetParents: args.targetComments,
|
targetParents: args.targetComments,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<EditCubit>(
|
|
||||||
lazy: false,
|
|
||||||
create: (BuildContext context) => EditCubit(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
child: ItemScreen(
|
child: ItemScreen(
|
||||||
item: args.item,
|
item: args.item,
|
||||||
@ -164,7 +156,7 @@ class ItemScreen extends StatefulWidget {
|
|||||||
_ItemScreenState createState() => _ItemScreenState();
|
_ItemScreenState createState() => _ItemScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ItemScreenState extends State<ItemScreen> {
|
class _ItemScreenState extends State<ItemScreen> with RouteAware {
|
||||||
final TextEditingController commentEditingController =
|
final TextEditingController commentEditingController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
@ -185,11 +177,20 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
static const Duration _featureDiscoveryDismissThrottleDelay =
|
static const Duration _featureDiscoveryDismissThrottleDelay =
|
||||||
Duration(seconds: 1);
|
Duration(seconds: 1);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didPop() {
|
||||||
|
super.didPop();
|
||||||
|
if (context.read<EditCubit>().state.text.isNullOrEmpty) {
|
||||||
|
context.read<EditCubit>().onReplyBoxClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
SchedulerBinding.instance
|
||||||
|
..addPostFrameCallback((_) {
|
||||||
if (!isTesting) {
|
if (!isTesting) {
|
||||||
FeatureDiscovery.discoverFeatures(
|
FeatureDiscovery.discoverFeatures(
|
||||||
context,
|
context,
|
||||||
@ -200,6 +201,15 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
..addPostFrameCallback((_) {
|
||||||
|
final ModalRoute<dynamic>? route = ModalRoute.of(context);
|
||||||
|
|
||||||
|
if (route == null) return;
|
||||||
|
|
||||||
|
locator
|
||||||
|
.get<RouteObserver<ModalRoute<dynamic>>>()
|
||||||
|
.subscribe(this, route);
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollController.addListener(() {
|
scrollController.addListener(() {
|
||||||
@ -208,6 +218,8 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
context.read<EditCubit>().onScrolled();
|
context.read<EditCubit>().onScrolled();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
commentEditingController.text = context.read<EditCubit>().state.text ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -502,7 +514,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
Text(
|
Text(
|
||||||
'''${state.item.score} karma, ${state.item.descendants} comment${state.item.descendants > 1 ? 's' : ''}''',
|
'''${state.item.score} karma, ${state.item.descendants} comment${state.item.descendants > 1 ? 's' : ''}''',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
] else ...<Widget>[
|
] else ...<Widget>[
|
||||||
@ -526,7 +538,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
: const Text(
|
: const Text(
|
||||||
'View parent thread',
|
'View parent thread',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -542,7 +554,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Lazy',
|
'Lazy',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -551,7 +563,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Eager',
|
'Eager',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -573,7 +585,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Natural',
|
'Natural',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -582,7 +594,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Newest first',
|
'Newest first',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -591,7 +603,7 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Oldest first',
|
'Oldest first',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: TextDimens.pt12,
|
fontSize: TextDimens.pt13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -685,7 +697,8 @@ class _ItemScreenState extends State<ItemScreen> {
|
|||||||
return BlocListener<EditCubit, EditState>(
|
return BlocListener<EditCubit, EditState>(
|
||||||
listenWhen: (EditState previous, EditState current) {
|
listenWhen: (EditState previous, EditState current) {
|
||||||
return previous.replyingTo != current.replyingTo ||
|
return previous.replyingTo != current.replyingTo ||
|
||||||
previous.itemBeingEdited != current.itemBeingEdited;
|
previous.itemBeingEdited != current.itemBeingEdited ||
|
||||||
|
commentEditingController.text != current.text;
|
||||||
},
|
},
|
||||||
listener: (BuildContext context, EditState editState) {
|
listener: (BuildContext context, EditState editState) {
|
||||||
if (editState.replyingTo != null ||
|
if (editState.replyingTo != null ||
|
||||||
|
@ -5,7 +5,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||||
import 'package:hacki/cubits/cubits.dart';
|
import 'package:hacki/cubits/cubits.dart';
|
||||||
|
import 'package:hacki/extensions/extensions.dart';
|
||||||
import 'package:hacki/models/item.dart';
|
import 'package:hacki/models/item.dart';
|
||||||
|
import 'package:hacki/screens/screens.dart';
|
||||||
import 'package:hacki/styles/styles.dart';
|
import 'package:hacki/styles/styles.dart';
|
||||||
import 'package:hacki/utils/link_util.dart';
|
import 'package:hacki/utils/link_util.dart';
|
||||||
|
|
||||||
@ -145,6 +147,39 @@ class _ReplyBoxState extends State<ReplyBox> {
|
|||||||
color: Palette.orange,
|
color: Palette.orange,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final EditState state =
|
||||||
|
context.read<EditCubit>().state;
|
||||||
|
if (state.replyingTo != null &&
|
||||||
|
state.text.isNotNullOrEmpty) {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) =>
|
||||||
|
AlertDialog(
|
||||||
|
title: const Text('Save draft?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
context
|
||||||
|
.read<EditCubit>()
|
||||||
|
.deleteDraft();
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
'No',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Palette.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.pop(context),
|
||||||
|
child: const Text('Yes'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
widget.onCloseTapped();
|
widget.onCloseTapped();
|
||||||
expanded = false;
|
expanded = false;
|
||||||
},
|
},
|
||||||
@ -222,7 +257,6 @@ class _ReplyBoxState extends State<ReplyBox> {
|
|||||||
|
|
||||||
showDialog<void>(
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: true,
|
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
insetPadding: const EdgeInsets.symmetric(
|
insetPadding: const EdgeInsets.symmetric(
|
||||||
@ -249,8 +283,31 @@ class _ReplyBoxState extends State<ReplyBox> {
|
|||||||
style: const TextStyle(color: Palette.grey),
|
style: const TextStyle(color: Palette.grey),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
if (replyingTo != null)
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Copy All'),
|
child: const Text('View thread'),
|
||||||
|
onPressed: () {
|
||||||
|
HapticFeedback.lightImpact();
|
||||||
|
setState(() {
|
||||||
|
expanded = false;
|
||||||
|
});
|
||||||
|
Navigator.popUntil(
|
||||||
|
context,
|
||||||
|
(Route<dynamic> route) =>
|
||||||
|
route.settings.name == ItemScreen.routeName ||
|
||||||
|
route.isFirst,
|
||||||
|
);
|
||||||
|
goToItemScreen(
|
||||||
|
args: ItemScreenArgs(
|
||||||
|
item: replyingTo,
|
||||||
|
useCommentCache: true,
|
||||||
|
),
|
||||||
|
forceNewScreen: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Copy all'),
|
||||||
onPressed: () => FlutterClipboard.copy(
|
onPressed: () => FlutterClipboard.copy(
|
||||||
replyingTo?.text ?? '',
|
replyingTo?.text ?? '',
|
||||||
).then((_) => HapticFeedback.selectionClick()),
|
).then((_) => HapticFeedback.selectionClick()),
|
||||||
|
@ -20,7 +20,7 @@ class _ScrollUpIconButtonState extends State<ScrollUpIconButton> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
widget.scrollController.addListener(() {
|
widget.scrollController.addListener(() {
|
||||||
if (widget.scrollController.offset <= 1000) {
|
if (widget.scrollController.offset <= 1000 && mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -526,7 +526,7 @@ class _ProfileScreenState extends State<ProfileScreen>
|
|||||||
showAboutDialog(
|
showAboutDialog(
|
||||||
context: context,
|
context: context,
|
||||||
applicationName: 'Hacki',
|
applicationName: 'Hacki',
|
||||||
applicationVersion: 'v0.2.28',
|
applicationVersion: 'v0.2.31',
|
||||||
applicationIcon: ClipRRect(
|
applicationIcon: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(
|
borderRadius: const BorderRadius.all(
|
||||||
Radius.circular(
|
Radius.circular(
|
||||||
|
@ -289,8 +289,21 @@ class CommentTile extends StatelessWidget {
|
|||||||
.read<CommentsCubit>()
|
.read<CommentsCubit>()
|
||||||
.state
|
.state
|
||||||
.commentIds
|
.commentIds
|
||||||
.contains(comment.kids.first))
|
.contains(comment.kids.first) &&
|
||||||
|
!context
|
||||||
|
.read<CommentsCubit>()
|
||||||
|
.state
|
||||||
|
.onlyShowTargetComment)
|
||||||
Center(
|
Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: Dimens.pt12,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
@ -306,6 +319,10 @@ class CommentTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const Divider(
|
const Divider(
|
||||||
height: Dimens.zero,
|
height: Dimens.zero,
|
||||||
),
|
),
|
||||||
|
@ -33,7 +33,7 @@ class _CountDownReminderState extends State<CountdownReminder>
|
|||||||
bool isVisible = false;
|
bool isVisible = false;
|
||||||
|
|
||||||
static const Duration countdownDuration = Duration(seconds: 8);
|
static const Duration countdownDuration = Duration(seconds: 8);
|
||||||
static const Duration visibilityCountdownDuration = Duration(seconds: 3);
|
static const Duration visibilityCountdownDuration = Duration.zero;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -86,7 +86,7 @@ class _OnboardingViewState extends State<OnboardingView> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
primary: Palette.orange,
|
backgroundColor: Palette.orange,
|
||||||
padding: const EdgeInsets.all(
|
padding: const EdgeInsets.all(
|
||||||
Dimens.pt18,
|
Dimens.pt18,
|
||||||
),
|
),
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:hacki/blocs/blocs.dart';
|
||||||
import 'package:hacki/config/locator.dart';
|
import 'package:hacki/config/locator.dart';
|
||||||
|
import 'package:hacki/cubits/cubits.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
class CustomBlocObserver extends BlocObserver {
|
class CustomBlocObserver extends BlocObserver {
|
||||||
@override
|
@override
|
||||||
void onCreate(BlocBase<dynamic> bloc) {
|
void onCreate(BlocBase<dynamic> bloc) {
|
||||||
|
if (bloc is! CollapseCubit) {
|
||||||
locator.get<Logger>().v('$bloc created');
|
locator.get<Logger>().v('$bloc created');
|
||||||
|
}
|
||||||
|
|
||||||
super.onCreate(bloc);
|
super.onCreate(bloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,7 +19,10 @@ class CustomBlocObserver extends BlocObserver {
|
|||||||
Bloc<dynamic, dynamic> bloc,
|
Bloc<dynamic, dynamic> bloc,
|
||||||
Object? event,
|
Object? event,
|
||||||
) {
|
) {
|
||||||
|
if (event is! StoriesEvent) {
|
||||||
locator.get<Logger>().v(event);
|
locator.get<Logger>().v(event);
|
||||||
|
}
|
||||||
|
|
||||||
super.onEvent(bloc, event);
|
super.onEvent(bloc, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +31,10 @@ class CustomBlocObserver extends BlocObserver {
|
|||||||
Bloc<dynamic, dynamic> bloc,
|
Bloc<dynamic, dynamic> bloc,
|
||||||
Transition<dynamic, dynamic> transition,
|
Transition<dynamic, dynamic> transition,
|
||||||
) {
|
) {
|
||||||
|
if (bloc is! StoriesBloc) {
|
||||||
locator.get<Logger>().v(transition);
|
locator.get<Logger>().v(transition);
|
||||||
|
}
|
||||||
|
|
||||||
super.onTransition(bloc, transition);
|
super.onTransition(bloc, transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +45,8 @@ class CustomBlocObserver extends BlocObserver {
|
|||||||
StackTrace stackTrace,
|
StackTrace stackTrace,
|
||||||
) {
|
) {
|
||||||
locator.get<Logger>().e(error);
|
locator.get<Logger>().e(error);
|
||||||
|
locator.get<Logger>().e(stackTrace);
|
||||||
|
|
||||||
super.onError(bloc, error, stackTrace);
|
super.onError(bloc, error, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ abstract class TextDimens {
|
|||||||
static const double pt8 = 8;
|
static const double pt8 = 8;
|
||||||
static const double pt10 = 10;
|
static const double pt10 = 10;
|
||||||
static const double pt12 = 12;
|
static const double pt12 = 12;
|
||||||
|
static const double pt13 = 13;
|
||||||
static const double pt14 = 14;
|
static const double pt14 = 14;
|
||||||
static const double pt15 = 15;
|
static const double pt15 = 15;
|
||||||
static const double pt16 = 16;
|
static const double pt16 = 16;
|
||||||
|
154
pubspec.lock
154
pubspec.lock
@ -7,28 +7,28 @@ packages:
|
|||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "40.0.0"
|
version: "47.0.0"
|
||||||
adaptive_theme:
|
adaptive_theme:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: adaptive_theme
|
name: adaptive_theme
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.1"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "4.7.0"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.11"
|
version: "3.3.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -42,7 +42,7 @@ packages:
|
|||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.9.0"
|
||||||
badges:
|
badges:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -56,14 +56,14 @@ packages:
|
|||||||
name: bloc
|
name: bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.0.3"
|
version: "8.1.0"
|
||||||
bloc_test:
|
bloc_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: bloc_test
|
name: bloc_test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.0.3"
|
version: "9.1.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -77,35 +77,28 @@ packages:
|
|||||||
name: cached_network_image
|
name: cached_network_image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.2"
|
||||||
cached_network_image_platform_interface:
|
cached_network_image_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cached_network_image_platform_interface
|
name: cached_network_image_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "2.0.0"
|
||||||
cached_network_image_web:
|
cached_network_image_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cached_network_image_web
|
name: cached_network_image_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.2"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
clipboard:
|
clipboard:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -119,7 +112,7 @@ packages:
|
|||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -133,7 +126,7 @@ packages:
|
|||||||
name: connectivity_plus
|
name: connectivity_plus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.5"
|
version: "2.3.7"
|
||||||
connectivity_plus_linux:
|
connectivity_plus_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -161,7 +154,7 @@ packages:
|
|||||||
name: connectivity_plus_web
|
name: connectivity_plus_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.2.3"
|
||||||
connectivity_plus_windows:
|
connectivity_plus_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -182,14 +175,14 @@ packages:
|
|||||||
name: coverage
|
name: coverage
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.5.0"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
csslib:
|
csslib:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -203,7 +196,7 @@ packages:
|
|||||||
name: dbus
|
name: dbus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.6"
|
version: "0.7.8"
|
||||||
diff_match_patch:
|
diff_match_patch:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -224,14 +217,14 @@ packages:
|
|||||||
name: equatable
|
name: equatable
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.5"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
fast_gbk:
|
fast_gbk:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -273,7 +266,7 @@ packages:
|
|||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.0.1"
|
version: "8.1.1"
|
||||||
flutter_blurhash:
|
flutter_blurhash:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -310,9 +303,11 @@ packages:
|
|||||||
flutter_inappwebview:
|
flutter_inappwebview:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_inappwebview
|
path: "."
|
||||||
url: "https://pub.dartlang.org"
|
ref: master
|
||||||
source: hosted
|
resolved-ref: e81d9b76aa8cbbdec65429a84a9edaf370715e90
|
||||||
|
url: "https://github.com/vocsyinfotech/flutter_inappwebview"
|
||||||
|
source: git
|
||||||
version: "5.4.3+7"
|
version: "5.4.3+7"
|
||||||
flutter_linkify:
|
flutter_linkify:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@ -327,14 +322,14 @@ packages:
|
|||||||
name: flutter_local_notifications
|
name: flutter_local_notifications
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.6.1"
|
version: "9.9.1"
|
||||||
flutter_local_notifications_linux:
|
flutter_local_notifications_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications_linux
|
name: flutter_local_notifications_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0+1"
|
version: "0.5.1"
|
||||||
flutter_local_notifications_platform_interface:
|
flutter_local_notifications_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -348,21 +343,21 @@ packages:
|
|||||||
name: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.2"
|
version: "6.0.0"
|
||||||
flutter_secure_storage_linux:
|
flutter_secure_storage_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_linux
|
name: flutter_secure_storage_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
flutter_secure_storage_macos:
|
flutter_secure_storage_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_macos
|
name: flutter_secure_storage_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
flutter_secure_storage_platform_interface:
|
flutter_secure_storage_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -397,7 +392,7 @@ packages:
|
|||||||
name: flutter_slidable
|
name: flutter_slidable
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.2"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -454,7 +449,7 @@ packages:
|
|||||||
name: hive
|
name: hive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.3"
|
||||||
html:
|
html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -475,7 +470,7 @@ packages:
|
|||||||
name: http
|
name: http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.4"
|
version: "0.13.5"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -490,6 +485,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.1"
|
||||||
|
hydrated_bloc:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: hydrated_bloc
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "9.0.0-dev.3"
|
||||||
integration_test:
|
integration_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -543,21 +545,21 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.12"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.4"
|
version: "0.1.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.8.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -613,7 +615,7 @@ packages:
|
|||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -627,14 +629,14 @@ packages:
|
|||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.16"
|
version: "2.0.20"
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider_ios
|
name: path_provider_ios
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.10"
|
version: "2.0.11"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -662,7 +664,7 @@ packages:
|
|||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.3"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -748,28 +750,28 @@ packages:
|
|||||||
name: responsive_builder
|
name: responsive_builder
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.2"
|
version: "0.4.3"
|
||||||
rxdart:
|
rxdart:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: rxdart
|
name: rxdart
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.27.4"
|
version: "0.27.5"
|
||||||
sembast:
|
sembast:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: sembast
|
name: sembast
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.0+1"
|
version: "3.3.0"
|
||||||
share_plus:
|
share_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.10"
|
version: "4.1.0"
|
||||||
share_plus_linux:
|
share_plus_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -818,7 +820,7 @@ packages:
|
|||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.12"
|
version: "2.0.13"
|
||||||
shared_preferences_ios:
|
shared_preferences_ios:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -846,7 +848,7 @@ packages:
|
|||||||
name: shared_preferences_platform_interface
|
name: shared_preferences_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.0"
|
||||||
shared_preferences_web:
|
shared_preferences_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -867,7 +869,7 @@ packages:
|
|||||||
name: shelf
|
name: shelf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.2"
|
||||||
shelf_packages_handler:
|
shelf_packages_handler:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -921,14 +923,14 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.9.0"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqflite
|
name: sqflite
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2+1"
|
version: "2.0.3+1"
|
||||||
sqflite_common:
|
sqflite_common:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -956,14 +958,14 @@ packages:
|
|||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
sync_http:
|
sync_http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sync_http
|
name: sync_http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.1"
|
||||||
synced_shared_preferences:
|
synced_shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -977,35 +979,35 @@ packages:
|
|||||||
name: synchronized
|
name: synchronized
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0+2"
|
version: "3.0.0+3"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
test:
|
test:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.21.1"
|
version: "1.21.4"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.12"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.13"
|
version: "0.4.16"
|
||||||
timezone:
|
timezone:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1026,7 +1028,7 @@ packages:
|
|||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
universal_platform:
|
universal_platform:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1040,14 +1042,14 @@ packages:
|
|||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.4"
|
version: "6.1.5"
|
||||||
url_launcher_android:
|
url_launcher_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.17"
|
version: "6.0.19"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1082,7 +1084,7 @@ packages:
|
|||||||
name: url_launcher_web
|
name: url_launcher_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.12"
|
version: "2.0.13"
|
||||||
url_launcher_windows:
|
url_launcher_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1117,14 +1119,14 @@ packages:
|
|||||||
name: vm_service
|
name: vm_service
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.2.2"
|
version: "9.0.0"
|
||||||
wakelock:
|
wakelock:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: wakelock
|
name: wakelock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.1+2"
|
version: "0.6.2"
|
||||||
wakelock_macos:
|
wakelock_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1152,7 +1154,7 @@ packages:
|
|||||||
name: wakelock_windows
|
name: wakelock_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.1"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1180,7 +1182,7 @@ packages:
|
|||||||
name: webkit_inspection_protocol
|
name: webkit_inspection_protocol
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.0"
|
||||||
webview_flutter:
|
webview_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1194,28 +1196,28 @@ packages:
|
|||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.14"
|
version: "2.10.1"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_platform_interface
|
name: webview_flutter_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.9.3"
|
||||||
webview_flutter_wkwebview:
|
webview_flutter_wkwebview:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_wkwebview
|
name: webview_flutter_wkwebview
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.1"
|
version: "2.9.4"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.0"
|
version: "3.0.0"
|
||||||
workmanager:
|
workmanager:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1229,7 +1231,7 @@ packages:
|
|||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0+1"
|
version: "0.2.0+2"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1245,5 +1247,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.17.0 <3.0.0"
|
dart: ">=2.18.0 <3.0.0"
|
||||||
flutter: ">=3.0.3"
|
flutter: ">=3.3.2"
|
||||||
|
23
pubspec.yaml
23
pubspec.yaml
@ -1,22 +1,22 @@
|
|||||||
name: hacki
|
name: hacki
|
||||||
description: A Hacker News reader.
|
description: A Hacker News reader.
|
||||||
version: 0.2.28+70
|
version: 0.2.31+74
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
flutter: "3.0.3"
|
flutter: "3.3.2"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
adaptive_theme: ^3.0.0
|
adaptive_theme: ^3.0.0
|
||||||
badges: ^2.0.2
|
badges: ^2.0.2
|
||||||
bloc: ^8.0.3
|
bloc: ^8.1.0
|
||||||
cached_network_image: ^3.2.1
|
cached_network_image: ^3.2.1
|
||||||
clipboard: ^0.1.3
|
clipboard: ^0.1.3
|
||||||
collection: ^1.16.0
|
collection: ^1.16.0
|
||||||
connectivity_plus: ^2.2.1
|
connectivity_plus: ^2.3.7
|
||||||
dio: ^4.0.4
|
dio: ^4.0.4
|
||||||
equatable: 2.0.3
|
equatable: ^2.0.5
|
||||||
fast_gbk: ^1.0.0
|
fast_gbk: ^1.0.0
|
||||||
# feature_discovery: ^0.14.0
|
# feature_discovery: ^0.14.0
|
||||||
feature_discovery:
|
feature_discovery:
|
||||||
@ -25,14 +25,18 @@ dependencies:
|
|||||||
ref: flutter3_compatibility
|
ref: flutter3_compatibility
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_bloc: ^8.0.1
|
flutter_bloc: ^8.1.1
|
||||||
flutter_cache_manager: ^3.3.0
|
flutter_cache_manager: ^3.3.0
|
||||||
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.4.3+4
|
# flutter_inappwebview: ^5.4.3+7
|
||||||
|
flutter_inappwebview:
|
||||||
|
git:
|
||||||
|
url: https://github.com/vocsyinfotech/flutter_inappwebview
|
||||||
|
ref: master
|
||||||
flutter_linkify: ^5.0.2
|
flutter_linkify: ^5.0.2
|
||||||
flutter_local_notifications: ^9.5.0
|
flutter_local_notifications: ^9.5.0
|
||||||
flutter_secure_storage: ^5.0.2
|
flutter_secure_storage: ^6.0.0
|
||||||
flutter_siri_suggestions: ^2.1.0
|
flutter_siri_suggestions: ^2.1.0
|
||||||
flutter_slidable: ^1.2.1
|
flutter_slidable: ^1.2.1
|
||||||
font_awesome_flutter: ^9.2.0
|
font_awesome_flutter: ^9.2.0
|
||||||
@ -42,6 +46,7 @@ dependencies:
|
|||||||
html: ^0.15.0
|
html: ^0.15.0
|
||||||
html_unescape: ^2.0.0
|
html_unescape: ^2.0.0
|
||||||
http: ^0.13.3
|
http: ^0.13.3
|
||||||
|
hydrated_bloc: ^9.0.0-dev.3
|
||||||
intl: ^0.17.0
|
intl: ^0.17.0
|
||||||
logger: ^1.1.0
|
logger: ^1.1.0
|
||||||
path: ^1.8.0
|
path: ^1.8.0
|
||||||
@ -72,7 +77,7 @@ dependencies:
|
|||||||
workmanager: ^0.5.0
|
workmanager: ^0.5.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
bloc_test: ^9.0.3
|
bloc_test: ^9.1.0
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
integration_test:
|
integration_test:
|
||||||
|
29
test_driver/perf_driver.dart
Normal file
29
test_driver/perf_driver.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter_driver/flutter_driver.dart' as driver;
|
||||||
|
import 'package:integration_test/integration_test_driver.dart';
|
||||||
|
|
||||||
|
Future<void> main() {
|
||||||
|
return integrationDriver(
|
||||||
|
responseDataCallback: (Map<String, dynamic>? data) async {
|
||||||
|
if (data != null) {
|
||||||
|
final driver.Timeline timeline = driver.Timeline.fromJson(
|
||||||
|
data['scrolling_timeline'] as Map<String, dynamic>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert the Timeline into a TimelineSummary that's easier to
|
||||||
|
// read and understand.
|
||||||
|
final driver.TimelineSummary summary =
|
||||||
|
driver.TimelineSummary.summarize(timeline);
|
||||||
|
|
||||||
|
// Then, write the entire timeline to disk in a json format.
|
||||||
|
// This file can be opened in the Chrome browser's tracing tools
|
||||||
|
// found by navigating to chrome://tracing.
|
||||||
|
// Optionally, save the summary to disk by setting includeSummary
|
||||||
|
// to true
|
||||||
|
await summary.writeTimelineToFile(
|
||||||
|
'scrolling_timeline',
|
||||||
|
pretty: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user