mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-06 18:24:42 +08:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
1e5af07691 | |||
ecf8c902dc |
4
.github/workflows/commit_check.yml
vendored
4
.github/workflows/commit_check.yml
vendored
@ -12,12 +12,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
env:
|
env:
|
||||||
FLUTTER_VERSION: "3.3.10"
|
FLUTTER_VERSION: "3.7.0"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
flutter-version: '3.3.10'
|
flutter-version: '3.7.0'
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter format --set-exit-if-changed .
|
- run: flutter format --set-exit-if-changed .
|
||||||
|
2
.github/workflows/publish_ios.yml
vendored
2
.github/workflows/publish_ios.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
|||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
cache: true
|
cache: true
|
||||||
flutter-version: 3.3.10
|
flutter-version: 3.7.0
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter format --set-exit-if-changed .
|
- run: flutter format --set-exit-if-changed .
|
||||||
- run: flutter analyze
|
- run: flutter analyze
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
include: package:very_good_analysis/analysis_options.3.1.0.yaml
|
||||||
linter:
|
linter:
|
||||||
rules:
|
rules:
|
||||||
parameter_assignments: false
|
parameter_assignments: false
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
include: package:very_good_analysis/analysis_options.3.1.0.yaml
|
||||||
linter:
|
linter:
|
||||||
rules:
|
rules:
|
||||||
parameter_assignments: false
|
parameter_assignments: false
|
||||||
|
0
fastlane/metadata/android/en-US/changelogs/81.txt
Normal file
0
fastlane/metadata/android/en-US/changelogs/81.txt
Normal file
@ -12,7 +12,7 @@ PODS:
|
|||||||
- OrderedSet (~> 5.0)
|
- OrderedSet (~> 5.0)
|
||||||
- flutter_local_notifications (0.0.1):
|
- flutter_local_notifications (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_secure_storage (3.3.1):
|
- flutter_secure_storage (6.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_siri_suggestions (0.0.1):
|
- flutter_siri_suggestions (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -24,6 +24,9 @@ PODS:
|
|||||||
- OrderedSet (5.0.0)
|
- OrderedSet (5.0.0)
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- path_provider_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- ReachabilitySwift (5.0.0)
|
- ReachabilitySwift (5.0.0)
|
||||||
@ -31,6 +34,9 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- shared_preferences_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- shared_preferences_ios (0.0.1):
|
- shared_preferences_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- sqflite (0.0.2):
|
- sqflite (0.0.2):
|
||||||
@ -56,9 +62,11 @@ DEPENDENCIES:
|
|||||||
- flutter_siri_suggestions (from `.symlinks/plugins/flutter_siri_suggestions/ios`)
|
- flutter_siri_suggestions (from `.symlinks/plugins/flutter_siri_suggestions/ios`)
|
||||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||||
- receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`)
|
- receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
|
||||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
- synced_shared_preferences (from `.symlinks/plugins/synced_shared_preferences/ios`)
|
- synced_shared_preferences (from `.symlinks/plugins/synced_shared_preferences/ios`)
|
||||||
@ -90,12 +98,16 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/integration_test/ios"
|
:path: ".symlinks/plugins/integration_test/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
|
path_provider_foundation:
|
||||||
|
:path: ".symlinks/plugins/path_provider_foundation/ios"
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||||
receive_sharing_intent:
|
receive_sharing_intent:
|
||||||
:path: ".symlinks/plugins/receive_sharing_intent/ios"
|
:path: ".symlinks/plugins/receive_sharing_intent/ios"
|
||||||
share_plus:
|
share_plus:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
|
||||||
shared_preferences_ios:
|
shared_preferences_ios:
|
||||||
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
||||||
sqflite:
|
sqflite:
|
||||||
@ -116,20 +128,22 @@ SPEC CHECKSUMS:
|
|||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
||||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||||
flutter_siri_suggestions: 226fb7ef33d25d3fe0d4aa2a8bcf4b72730c466f
|
flutter_siri_suggestions: 226fb7ef33d25d3fe0d4aa2a8bcf4b72730c466f
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
|
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||||
|
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||||
receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1
|
receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1
|
||||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||||
|
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
|
||||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
synced_shared_preferences: f722742b06d65c7315b8e9f56b794c9fbd5597f7
|
synced_shared_preferences: f722742b06d65c7315b8e9f56b794c9fbd5597f7
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
|
||||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
|
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
|
||||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 51;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@ -360,6 +360,7 @@
|
|||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
@ -413,6 +414,7 @@
|
|||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
|
@ -74,5 +74,7 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -84,6 +84,9 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
|
|||||||
const StoriesState.init().copyWith(
|
const StoriesState.init().copyWith(
|
||||||
offlineReading: hasCachedStories,
|
offlineReading: hasCachedStories,
|
||||||
currentPageSize: pageSize,
|
currentPageSize: pageSize,
|
||||||
|
downloadStatus: state.downloadStatus,
|
||||||
|
storiesDownloaded: state.storiesDownloaded,
|
||||||
|
storiesToBeDownloaded: state.storiesToBeDownloaded,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
for (final StoryType type in types) {
|
for (final StoryType type in types) {
|
||||||
@ -374,7 +377,6 @@ class StoriesBloc extends Bloc<StoriesEvent, StoriesState> {
|
|||||||
StoriesPageSizeChanged event,
|
StoriesPageSizeChanged event,
|
||||||
Emitter<StoriesState> emit,
|
Emitter<StoriesState> emit,
|
||||||
) async {
|
) async {
|
||||||
emit(const StoriesState.init());
|
|
||||||
add(StoriesInitialize());
|
add(StoriesInitialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +22,12 @@ extension ContextExtension 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 = 430,
|
static const double _screenWidthLowerBound = 430;
|
||||||
_screenWidthUpperBound = 850,
|
static const double _screenWidthUpperBound = 850;
|
||||||
_picHeightLowerBound = 110,
|
static const double _picHeightLowerBound = 110;
|
||||||
_picHeightUpperBound = 128,
|
static const double _picHeightUpperBound = 128;
|
||||||
_smallPicHeight = 100,
|
static const double _smallPicHeight = 100;
|
||||||
_picHeightFactor = 0.3;
|
static const double _picHeightFactor = 0.3;
|
||||||
|
|
||||||
double get storyTileHeight {
|
double get storyTileHeight {
|
||||||
final double screenWidth =
|
final double screenWidth =
|
||||||
|
@ -19,7 +19,7 @@ extension StateExtension on State {
|
|||||||
? SnackBarAction(
|
? SnackBarAction(
|
||||||
label: label,
|
label: label,
|
||||||
onPressed: action,
|
onPressed: action,
|
||||||
textColor: Theme.of(context).textTheme.bodyText1?.color,
|
textColor: Theme.of(context).textTheme.bodyLarge?.color,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:hacki/config/locator.dart';
|
import 'package:hacki/config/locator.dart';
|
||||||
import 'package:hacki/models/models.dart';
|
import 'package:hacki/models/models.dart';
|
||||||
import 'package:hacki/repositories/postable_repository.dart';
|
import 'package:hacki/repositories/postable_repository.dart';
|
||||||
@ -9,13 +8,12 @@ import 'package:logger/logger.dart';
|
|||||||
|
|
||||||
class AuthRepository extends PostableRepository {
|
class AuthRepository extends PostableRepository {
|
||||||
AuthRepository({
|
AuthRepository({
|
||||||
Dio? dio,
|
super.dio,
|
||||||
PreferenceRepository? preferenceRepository,
|
PreferenceRepository? preferenceRepository,
|
||||||
Logger? logger,
|
Logger? logger,
|
||||||
}) : _preferenceRepository =
|
}) : _preferenceRepository =
|
||||||
preferenceRepository ?? locator.get<PreferenceRepository>(),
|
preferenceRepository ?? locator.get<PreferenceRepository>(),
|
||||||
_logger = logger ?? locator.get<Logger>(),
|
_logger = logger ?? locator.get<Logger>();
|
||||||
super(dio: dio);
|
|
||||||
|
|
||||||
final PreferenceRepository _preferenceRepository;
|
final PreferenceRepository _preferenceRepository;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
|
@ -8,10 +8,9 @@ import 'package:hacki/repositories/preference_repository.dart';
|
|||||||
import 'package:hacki/utils/utils.dart';
|
import 'package:hacki/utils/utils.dart';
|
||||||
|
|
||||||
class PostRepository extends PostableRepository {
|
class PostRepository extends PostableRepository {
|
||||||
PostRepository({Dio? dio, PreferenceRepository? storageRepository})
|
PostRepository({super.dio, PreferenceRepository? storageRepository})
|
||||||
: _preferenceRepository =
|
: _preferenceRepository =
|
||||||
storageRepository ?? locator.get<PreferenceRepository>(),
|
storageRepository ?? locator.get<PreferenceRepository>();
|
||||||
super(dio: dio);
|
|
||||||
|
|
||||||
final PreferenceRepository _preferenceRepository;
|
final PreferenceRepository _preferenceRepository;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:badges/badges.dart';
|
import 'package:badges/badges.dart';
|
||||||
import 'package:feature_discovery/feature_discovery.dart';
|
import 'package:feature_discovery/feature_discovery.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart' hide Badge;
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -182,7 +182,7 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Container(
|
child: ColoredBox(
|
||||||
color: Palette.orangeAccent.withOpacity(0.2),
|
color: Palette.orangeAccent.withOpacity(0.2),
|
||||||
child: StoryTile(
|
child: StoryTile(
|
||||||
key: ValueKey<String>('${story.id}-PinnedStoryTile'),
|
key: ValueKey<String>('${story.id}-PinnedStoryTile'),
|
||||||
@ -508,9 +508,8 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
|
|
||||||
class _MobileHomeScreen extends StatelessWidget {
|
class _MobileHomeScreen extends StatelessWidget {
|
||||||
const _MobileHomeScreen({
|
const _MobileHomeScreen({
|
||||||
Key? key,
|
|
||||||
required this.homeScreen,
|
required this.homeScreen,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Widget homeScreen;
|
final Widget homeScreen;
|
||||||
|
|
||||||
@ -534,9 +533,8 @@ class _MobileHomeScreen extends StatelessWidget {
|
|||||||
|
|
||||||
class _TabletHomeScreen extends StatelessWidget {
|
class _TabletHomeScreen extends StatelessWidget {
|
||||||
const _TabletHomeScreen({
|
const _TabletHomeScreen({
|
||||||
Key? key,
|
|
||||||
required this.homeScreen,
|
required this.homeScreen,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Widget homeScreen;
|
final Widget homeScreen;
|
||||||
|
|
||||||
@ -561,7 +559,7 @@ class _TabletHomeScreen extends StatelessWidget {
|
|||||||
left: Dimens.zero,
|
left: Dimens.zero,
|
||||||
top: Dimens.zero,
|
top: Dimens.zero,
|
||||||
bottom: Dimens.zero,
|
bottom: Dimens.zero,
|
||||||
width: state.expanded ? Dimens.zero : homeScreenWidth,
|
width: homeScreenWidth,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.elasticOut,
|
curve: Curves.elasticOut,
|
||||||
child: homeScreen,
|
child: homeScreen,
|
||||||
@ -592,7 +590,7 @@ class _TabletHomeScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TabletStoryView extends StatelessWidget {
|
class _TabletStoryView extends StatelessWidget {
|
||||||
const _TabletStoryView({Key? key}) : super(key: key);
|
const _TabletStoryView();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -605,7 +603,7 @@ class _TabletStoryView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
child: Container(
|
child: ColoredBox(
|
||||||
color: Theme.of(context).canvasColor,
|
color: Theme.of(context).canvasColor,
|
||||||
child: const Center(
|
child: const Center(
|
||||||
child: Text('Tap on story tile to view comments.'),
|
child: Text('Tap on story tile to view comments.'),
|
||||||
|
@ -7,10 +7,10 @@ import 'package:hacki/styles/styles.dart';
|
|||||||
|
|
||||||
class CustomAppBar extends AppBar {
|
class CustomAppBar extends AppBar {
|
||||||
CustomAppBar({
|
CustomAppBar({
|
||||||
Key? key,
|
super.key,
|
||||||
required ScrollController scrollController,
|
required ScrollController scrollController,
|
||||||
required Item item,
|
required Item item,
|
||||||
required Color backgroundColor,
|
required Color super.backgroundColor,
|
||||||
required Future<bool> Function() onBackgroundTap,
|
required Future<bool> Function() onBackgroundTap,
|
||||||
required Future<bool> Function() onDismiss,
|
required Future<bool> Function() onDismiss,
|
||||||
required VoidCallback onFontSizeTap,
|
required VoidCallback onFontSizeTap,
|
||||||
@ -19,8 +19,6 @@ class CustomAppBar extends AppBar {
|
|||||||
VoidCallback? onZoomTap,
|
VoidCallback? onZoomTap,
|
||||||
bool? expanded,
|
bool? expanded,
|
||||||
}) : super(
|
}) : super(
|
||||||
key: key,
|
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
elevation: Dimens.zero,
|
elevation: Dimens.zero,
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
if (splitViewEnabled) ...<Widget>[
|
if (splitViewEnabled) ...<Widget>[
|
||||||
|
@ -9,15 +9,15 @@ import 'package:hacki/utils/utils.dart';
|
|||||||
|
|
||||||
class LoginDialog extends StatelessWidget {
|
class LoginDialog extends StatelessWidget {
|
||||||
const LoginDialog({
|
const LoginDialog({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.usernameController,
|
required this.usernameController,
|
||||||
required this.passwordController,
|
required this.passwordController,
|
||||||
required this.showSnackBar,
|
required this.showSnackBar,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final TextEditingController usernameController;
|
final TextEditingController usernameController;
|
||||||
final TextEditingController passwordController;
|
final TextEditingController passwordController;
|
||||||
final Function({
|
final void Function({
|
||||||
required String content,
|
required String content,
|
||||||
VoidCallback? action,
|
VoidCallback? action,
|
||||||
String? label,
|
String? label,
|
||||||
|
@ -17,7 +17,7 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
|
|||||||
|
|
||||||
class MainView extends StatelessWidget {
|
class MainView extends StatelessWidget {
|
||||||
const MainView({
|
const MainView({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.scrollController,
|
required this.scrollController,
|
||||||
required this.refreshController,
|
required this.refreshController,
|
||||||
required this.commentEditingController,
|
required this.commentEditingController,
|
||||||
@ -29,7 +29,7 @@ class MainView extends StatelessWidget {
|
|||||||
required this.onStoryLinkTapped,
|
required this.onStoryLinkTapped,
|
||||||
required this.onLoginTapped,
|
required this.onLoginTapped,
|
||||||
required this.onRightMoreTapped,
|
required this.onRightMoreTapped,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final ScrollController scrollController;
|
final ScrollController scrollController;
|
||||||
final RefreshController refreshController;
|
final RefreshController refreshController;
|
||||||
@ -38,11 +38,14 @@ class MainView extends StatelessWidget {
|
|||||||
final FocusNode focusNode;
|
final FocusNode focusNode;
|
||||||
final double topPadding;
|
final double topPadding;
|
||||||
final bool splitViewEnabled;
|
final bool splitViewEnabled;
|
||||||
final Function(Item item, Rect? rect) onMoreTapped;
|
final void Function(Item item, Rect? rect) onMoreTapped;
|
||||||
final ValueChanged<String> onStoryLinkTapped;
|
final ValueChanged<String> onStoryLinkTapped;
|
||||||
final VoidCallback onLoginTapped;
|
final VoidCallback onLoginTapped;
|
||||||
final ValueChanged<Comment> onRightMoreTapped;
|
final ValueChanged<Comment> onRightMoreTapped;
|
||||||
|
|
||||||
|
static const int _loadingIndicatorOpacityAnimationDuration = 300;
|
||||||
|
static const double _trailingBoxHeight = 240;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Stack(
|
return Stack(
|
||||||
@ -130,7 +133,7 @@ class MainView extends StatelessWidget {
|
|||||||
state.comments.isNotEmpty) ||
|
state.comments.isNotEmpty) ||
|
||||||
state.onlyShowTargetComment) {
|
state.onlyShowTargetComment) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 240,
|
height: _trailingBoxHeight,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(Constants.happyFaces.pickRandomly()!),
|
child: Text(Constants.happyFaces.pickRandomly()!),
|
||||||
),
|
),
|
||||||
@ -194,8 +197,13 @@ class MainView extends StatelessWidget {
|
|||||||
buildWhen: (CommentsState prev, CommentsState current) =>
|
buildWhen: (CommentsState prev, CommentsState current) =>
|
||||||
prev.status != current.status,
|
prev.status != current.status,
|
||||||
builder: (BuildContext context, CommentsState state) {
|
builder: (BuildContext context, CommentsState state) {
|
||||||
return Visibility(
|
return AnimatedOpacity(
|
||||||
visible: state.status == CommentsStatus.loading,
|
opacity: state.status == CommentsStatus.loading
|
||||||
|
? NumSwitch.on
|
||||||
|
: NumSwitch.off,
|
||||||
|
duration: const Duration(
|
||||||
|
milliseconds: _loadingIndicatorOpacityAnimationDuration,
|
||||||
|
),
|
||||||
child: const LinearProgressIndicator(),
|
child: const LinearProgressIndicator(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -208,7 +216,6 @@ class MainView extends StatelessWidget {
|
|||||||
|
|
||||||
class _ParentItemSection extends StatelessWidget {
|
class _ParentItemSection extends StatelessWidget {
|
||||||
const _ParentItemSection({
|
const _ParentItemSection({
|
||||||
Key? key,
|
|
||||||
required this.scrollController,
|
required this.scrollController,
|
||||||
required this.refreshController,
|
required this.refreshController,
|
||||||
required this.commentEditingController,
|
required this.commentEditingController,
|
||||||
@ -221,7 +228,7 @@ class _ParentItemSection extends StatelessWidget {
|
|||||||
required this.onStoryLinkTapped,
|
required this.onStoryLinkTapped,
|
||||||
required this.onLoginTapped,
|
required this.onLoginTapped,
|
||||||
required this.onRightMoreTapped,
|
required this.onRightMoreTapped,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final ScrollController scrollController;
|
final ScrollController scrollController;
|
||||||
final RefreshController refreshController;
|
final RefreshController refreshController;
|
||||||
@ -231,7 +238,7 @@ class _ParentItemSection extends StatelessWidget {
|
|||||||
final FocusNode focusNode;
|
final FocusNode focusNode;
|
||||||
final double topPadding;
|
final double topPadding;
|
||||||
final bool splitViewEnabled;
|
final bool splitViewEnabled;
|
||||||
final Function(Item item, Rect? rect) onMoreTapped;
|
final void Function(Item item, Rect? rect) onMoreTapped;
|
||||||
final ValueChanged<String> onStoryLinkTapped;
|
final ValueChanged<String> onStoryLinkTapped;
|
||||||
final VoidCallback onLoginTapped;
|
final VoidCallback onLoginTapped;
|
||||||
final ValueChanged<Comment> onRightMoreTapped;
|
final ValueChanged<Comment> onRightMoreTapped;
|
||||||
@ -342,7 +349,7 @@ class _ParentItemSection extends StatelessWidget {
|
|||||||
prefState.fontSize.fontSize,
|
prefState.fontSize.fontSize,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyText1
|
.bodyLarge
|
||||||
?.color,
|
?.color,
|
||||||
),
|
),
|
||||||
children: <TextSpan>[
|
children: <TextSpan>[
|
||||||
|
@ -12,17 +12,17 @@ import 'package:hacki/utils/utils.dart';
|
|||||||
|
|
||||||
class MorePopupMenu extends StatelessWidget {
|
class MorePopupMenu extends StatelessWidget {
|
||||||
const MorePopupMenu({
|
const MorePopupMenu({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.item,
|
required this.item,
|
||||||
required this.isBlocked,
|
required this.isBlocked,
|
||||||
required this.showSnackBar,
|
required this.showSnackBar,
|
||||||
required this.onStoryLinkTapped,
|
required this.onStoryLinkTapped,
|
||||||
required this.onLoginTapped,
|
required this.onLoginTapped,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Item item;
|
final Item item;
|
||||||
final bool isBlocked;
|
final bool isBlocked;
|
||||||
final Function({
|
final void Function({
|
||||||
required String content,
|
required String content,
|
||||||
VoidCallback? action,
|
VoidCallback? action,
|
||||||
String? label,
|
String? label,
|
||||||
|
@ -168,7 +168,7 @@ class PollView extends StatelessWidget {
|
|||||||
? SnackBarAction(
|
? SnackBarAction(
|
||||||
label: label,
|
label: label,
|
||||||
onPressed: action,
|
onPressed: action,
|
||||||
textColor: Theme.of(context).textTheme.bodyText1?.color,
|
textColor: Theme.of(context).textTheme.bodyLarge?.color,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
|
@ -111,7 +111,8 @@ class _ReplyBoxState extends State<ReplyBox> {
|
|||||||
...<Widget>[
|
...<Widget>[
|
||||||
if (replyingTo != null)
|
if (replyingTo != null)
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: expanded ? 1 : 0,
|
opacity:
|
||||||
|
expanded ? NumSwitch.on : NumSwitch.off,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
key: const Key('quote'),
|
key: const Key('quote'),
|
||||||
|
@ -9,19 +9,19 @@ import 'package:responsive_builder/responsive_builder.dart';
|
|||||||
|
|
||||||
class TimeMachineDialog extends StatelessWidget {
|
class TimeMachineDialog extends StatelessWidget {
|
||||||
const TimeMachineDialog({
|
const TimeMachineDialog({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.comment,
|
required this.comment,
|
||||||
required this.size,
|
required this.size,
|
||||||
required this.deviceType,
|
required this.deviceType,
|
||||||
required this.widthFactor,
|
required this.widthFactor,
|
||||||
required this.onStoryLinkTapped,
|
required this.onStoryLinkTapped,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Comment comment;
|
final Comment comment;
|
||||||
final Size size;
|
final Size size;
|
||||||
final DeviceScreenType deviceType;
|
final DeviceScreenType deviceType;
|
||||||
final double widthFactor;
|
final double widthFactor;
|
||||||
final Function(String) onStoryLinkTapped;
|
final void Function(String) onStoryLinkTapped;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -650,89 +650,93 @@ class _ProfileScreenState extends State<ProfileScreen>
|
|||||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||||
final String version = packageInfo.version;
|
final String version = packageInfo.version;
|
||||||
|
|
||||||
showAboutDialog(
|
if (mounted) {
|
||||||
context: context,
|
showAboutDialog(
|
||||||
applicationName: 'Hacki',
|
context: context,
|
||||||
applicationVersion: 'v$version',
|
applicationName: 'Hacki',
|
||||||
applicationIcon: ClipRRect(
|
applicationVersion: 'v$version',
|
||||||
borderRadius: const BorderRadius.all(
|
applicationIcon: ClipRRect(
|
||||||
Radius.circular(
|
borderRadius: const BorderRadius.all(
|
||||||
Dimens.pt12,
|
Radius.circular(
|
||||||
|
Dimens.pt12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
Constants.hackiIconPath,
|
||||||
|
height: Dimens.pt50,
|
||||||
|
width: Dimens.pt50,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Image.asset(
|
children: <Widget>[
|
||||||
Constants.hackiIconPath,
|
ElevatedButton(
|
||||||
height: Dimens.pt50,
|
onPressed: () => LinkUtil.launch(
|
||||||
width: Dimens.pt50,
|
Constants.portfolioLink,
|
||||||
),
|
),
|
||||||
),
|
child: Row(
|
||||||
children: <Widget>[
|
children: const <Widget>[
|
||||||
ElevatedButton(
|
Icon(
|
||||||
onPressed: () => LinkUtil.launch(
|
FontAwesomeIcons.addressCard,
|
||||||
Constants.portfolioLink,
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Dimens.pt12,
|
||||||
|
),
|
||||||
|
Text('Developer'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
ElevatedButton(
|
||||||
children: const <Widget>[
|
onPressed: () => LinkUtil.launch(
|
||||||
Icon(
|
Constants.githubLink,
|
||||||
FontAwesomeIcons.addressCard,
|
),
|
||||||
),
|
child: Row(
|
||||||
SizedBox(
|
children: const <Widget>[
|
||||||
width: Dimens.pt12,
|
Icon(
|
||||||
),
|
FontAwesomeIcons.github,
|
||||||
Text('Developer'),
|
),
|
||||||
],
|
SizedBox(
|
||||||
|
width: Dimens.pt12,
|
||||||
|
),
|
||||||
|
Text('Source code'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
ElevatedButton(
|
||||||
ElevatedButton(
|
onPressed: () => LinkUtil.launch(
|
||||||
onPressed: () => LinkUtil.launch(
|
Platform.isIOS
|
||||||
Constants.githubLink,
|
? Constants.appStoreLink
|
||||||
|
: Constants.googlePlayLink,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: const <Widget>[
|
||||||
|
Icon(
|
||||||
|
Icons.thumb_up,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Dimens.pt12,
|
||||||
|
),
|
||||||
|
Text('Like the app?'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
ElevatedButton(
|
||||||
children: const <Widget>[
|
onPressed: () => LinkUtil.launch(
|
||||||
Icon(
|
Constants.sponsorLink,
|
||||||
FontAwesomeIcons.github,
|
),
|
||||||
),
|
child: Row(
|
||||||
SizedBox(
|
children: const <Widget>[
|
||||||
width: Dimens.pt12,
|
Icon(
|
||||||
),
|
FeatherIcons.coffee,
|
||||||
Text('Source code'),
|
),
|
||||||
],
|
SizedBox(
|
||||||
|
width: Dimens.pt12,
|
||||||
|
),
|
||||||
|
Text('Buy me a coffee'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
ElevatedButton(
|
);
|
||||||
onPressed: () => LinkUtil.launch(
|
}
|
||||||
Platform.isIOS ? Constants.appStoreLink : Constants.googlePlayLink,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: const <Widget>[
|
|
||||||
Icon(
|
|
||||||
Icons.thumb_up,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: Dimens.pt12,
|
|
||||||
),
|
|
||||||
Text('Like the app?'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () => LinkUtil.launch(
|
|
||||||
Constants.sponsorLink,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: const <Widget>[
|
|
||||||
Icon(
|
|
||||||
FeatherIcons.coffee,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: Dimens.pt12,
|
|
||||||
),
|
|
||||||
Text('Buy me a coffee'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCommentTapped(Comment comment, {VoidCallback? then}) {
|
void onCommentTapped(Comment comment, {VoidCallback? then}) {
|
||||||
|
@ -22,7 +22,7 @@ class InboxView extends StatelessWidget {
|
|||||||
final RefreshController refreshController;
|
final RefreshController refreshController;
|
||||||
final List<Comment> comments;
|
final List<Comment> comments;
|
||||||
final List<int> unreadCommentsIds;
|
final List<int> unreadCommentsIds;
|
||||||
final Function(Comment) onCommentTapped;
|
final void Function(Comment) onCommentTapped;
|
||||||
final VoidCallback onMarkAllAsReadTapped;
|
final VoidCallback onMarkAllAsReadTapped;
|
||||||
final VoidCallback onLoadMore;
|
final VoidCallback onLoadMore;
|
||||||
final VoidCallback onRefresh;
|
final VoidCallback onRefresh;
|
||||||
|
@ -179,8 +179,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.expand((List<Widget> e) => e)
|
.expand((List<Widget> e) => e),
|
||||||
.toList(),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: Dimens.pt40,
|
height: Dimens.pt40,
|
||||||
),
|
),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hacki/screens/widgets/widgets.dart';
|
import 'package:hacki/screens/widgets/widgets.dart';
|
||||||
|
|
||||||
typedef DateRangeCallback = Function(DateTime, DateTime);
|
typedef DateRangeCallback = void Function(DateTime, DateTime);
|
||||||
|
|
||||||
enum CustomDateTimeRange {
|
enum CustomDateTimeRange {
|
||||||
pastDay(Duration(days: 1), label: 'past day'),
|
pastDay(Duration(days: 1), label: 'past day'),
|
||||||
@ -17,10 +17,10 @@ enum CustomDateTimeRange {
|
|||||||
|
|
||||||
class CustomRangeFilterChip extends StatelessWidget {
|
class CustomRangeFilterChip extends StatelessWidget {
|
||||||
const CustomRangeFilterChip({
|
const CustomRangeFilterChip({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.range,
|
required this.range,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final CustomDateTimeRange range;
|
final CustomDateTimeRange range;
|
||||||
final DateRangeCallback onTap;
|
final DateRangeCallback onTap;
|
||||||
|
@ -5,14 +5,14 @@ import 'package:intl/intl.dart';
|
|||||||
|
|
||||||
class DateTimeRangeFilterChip extends StatelessWidget {
|
class DateTimeRangeFilterChip extends StatelessWidget {
|
||||||
const DateTimeRangeFilterChip({
|
const DateTimeRangeFilterChip({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.filter,
|
required this.filter,
|
||||||
required this.onDateTimeRangeUpdated,
|
required this.onDateTimeRangeUpdated,
|
||||||
required this.onDateTimeRangeRemoved,
|
required this.onDateTimeRangeRemoved,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final DateTimeRangeFilter? filter;
|
final DateTimeRangeFilter? filter;
|
||||||
final Function(DateTime, DateTime) onDateTimeRangeUpdated;
|
final void Function(DateTime, DateTime) onDateTimeRangeUpdated;
|
||||||
final VoidCallback onDateTimeRangeRemoved;
|
final VoidCallback onDateTimeRangeRemoved;
|
||||||
|
|
||||||
static final DateFormat _dateTimeFormatter = DateFormat.yMMMd();
|
static final DateFormat _dateTimeFormatter = DateFormat.yMMMd();
|
||||||
|
@ -4,9 +4,9 @@ import 'package:hacki/screens/widgets/widgets.dart';
|
|||||||
|
|
||||||
class PostedByFilterChip extends StatelessWidget {
|
class PostedByFilterChip extends StatelessWidget {
|
||||||
const PostedByFilterChip({
|
const PostedByFilterChip({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.filter,
|
required this.filter,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final PostedByFilter? filter;
|
final PostedByFilter? filter;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class BlocBuilder3<
|
|||||||
BlocC extends StateStreamable<BlocCState>,
|
BlocC extends StateStreamable<BlocCState>,
|
||||||
BlocCState> extends StatelessWidget {
|
BlocCState> extends StatelessWidget {
|
||||||
const BlocBuilder3({
|
const BlocBuilder3({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.builder,
|
required this.builder,
|
||||||
this.blocA,
|
this.blocA,
|
||||||
this.blocB,
|
this.blocB,
|
||||||
@ -25,7 +25,7 @@ class BlocBuilder3<
|
|||||||
this.buildWhenA,
|
this.buildWhenA,
|
||||||
this.buildWhenB,
|
this.buildWhenB,
|
||||||
this.buildWhenC,
|
this.buildWhenC,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final BlocWidgetBuilder3<BlocAState, BlocBState, BlocCState> builder;
|
final BlocWidgetBuilder3<BlocAState, BlocBState, BlocCState> builder;
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ class CommentTile extends StatelessWidget {
|
|||||||
final Comment comment;
|
final Comment comment;
|
||||||
final int level;
|
final int level;
|
||||||
final bool actionable;
|
final bool actionable;
|
||||||
final Function(Comment)? onReplyTapped;
|
final void Function(Comment)? onReplyTapped;
|
||||||
final Function(Comment, Rect?)? onMoreTapped;
|
final void Function(Comment, Rect?)? onMoreTapped;
|
||||||
final Function(Comment)? onEditTapped;
|
final void Function(Comment)? onEditTapped;
|
||||||
final Function(Comment)? onRightMoreTapped;
|
final void Function(Comment)? onRightMoreTapped;
|
||||||
final Function(String) onStoryLinkTapped;
|
final void Function(String) onStoryLinkTapped;
|
||||||
final FetchMode fetchMode;
|
final FetchMode fetchMode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -57,7 +57,7 @@ class ItemsListView<T extends Item> extends StatelessWidget {
|
|||||||
final VoidCallback? onRefresh;
|
final VoidCallback? onRefresh;
|
||||||
final VoidCallback? onLoadMore;
|
final VoidCallback? onLoadMore;
|
||||||
final ValueChanged<Story>? onPinned;
|
final ValueChanged<Story>? onPinned;
|
||||||
final Function(T) onTap;
|
final void Function(T) onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -249,11 +249,10 @@ class ItemsListView<T extends Item> extends StatelessWidget {
|
|||||||
|
|
||||||
class _CommentTile extends StatelessWidget {
|
class _CommentTile extends StatelessWidget {
|
||||||
const _CommentTile({
|
const _CommentTile({
|
||||||
Key? key,
|
|
||||||
required this.comment,
|
required this.comment,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
this.fontSize = 16,
|
this.fontSize = 16,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Comment comment;
|
final Comment comment;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
@ -113,7 +113,8 @@ class LinkPreview extends StatefulWidget {
|
|||||||
|
|
||||||
class _LinkPreviewState extends State<LinkPreview> {
|
class _LinkPreviewState extends State<LinkPreview> {
|
||||||
InfoBase? _info;
|
InfoBase? _info;
|
||||||
String? _errorTitle, _errorBody;
|
String? _errorTitle;
|
||||||
|
String? _errorBody;
|
||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -158,7 +159,7 @@ class _LinkPreviewState extends State<LinkPreview> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLinkContainer(
|
Widget _buildLinkContainer(
|
||||||
double _height, {
|
double height, {
|
||||||
String? title = '',
|
String? title = '',
|
||||||
String? desc = '',
|
String? desc = '',
|
||||||
String? imageUri = '',
|
String? imageUri = '',
|
||||||
@ -177,7 +178,7 @@ class _LinkPreviewState extends State<LinkPreview> {
|
|||||||
const BoxShadow(blurRadius: 3, color: Palette.grey),
|
const BoxShadow(blurRadius: 3, color: Palette.grey),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
height: _height,
|
height: height,
|
||||||
child: LinkView(
|
child: LinkView(
|
||||||
key: widget.key ?? Key(widget.link),
|
key: widget.key ?? Key(widget.link),
|
||||||
metadata: widget.story.simpleMetadata,
|
metadata: widget.story.simpleMetadata,
|
||||||
|
@ -37,7 +37,7 @@ class LinkView extends StatelessWidget {
|
|||||||
final String description;
|
final String description;
|
||||||
final String? imageUri;
|
final String? imageUri;
|
||||||
final String? imagePath;
|
final String? imagePath;
|
||||||
final Function(String) onTap;
|
final void Function(String) onTap;
|
||||||
final TextStyle? titleTextStyle;
|
final TextStyle? titleTextStyle;
|
||||||
final TextStyle? bodyTextStyle;
|
final TextStyle? bodyTextStyle;
|
||||||
final bool showMultiMedia;
|
final bool showMultiMedia;
|
||||||
@ -76,13 +76,13 @@ class LinkView extends StatelessWidget {
|
|||||||
final double layoutWidth = constraints.biggest.width;
|
final double layoutWidth = constraints.biggest.width;
|
||||||
final double layoutHeight = constraints.biggest.height;
|
final double layoutHeight = constraints.biggest.height;
|
||||||
|
|
||||||
final TextStyle _titleFontSize = titleTextStyle ??
|
final TextStyle titleFontSize = titleTextStyle ??
|
||||||
TextStyle(
|
TextStyle(
|
||||||
fontSize: computeTitleFontSize(layoutWidth),
|
fontSize: computeTitleFontSize(layoutWidth),
|
||||||
color: Palette.black,
|
color: Palette.black,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
);
|
);
|
||||||
final TextStyle _bodyFontSize = bodyTextStyle ??
|
final TextStyle bodyFontSize = bodyTextStyle ??
|
||||||
TextStyle(
|
TextStyle(
|
||||||
fontSize: computeTitleFontSize(layoutWidth) - 1,
|
fontSize: computeTitleFontSize(layoutWidth) - 1,
|
||||||
color: Palette.grey,
|
color: Palette.grey,
|
||||||
@ -131,11 +131,11 @@ class LinkView extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildTitleContainer(
|
_buildTitleContainer(
|
||||||
_titleFontSize,
|
titleFontSize,
|
||||||
computeTitleLines(layoutHeight),
|
computeTitleLines(layoutHeight),
|
||||||
),
|
),
|
||||||
_buildBodyContainer(
|
_buildBodyContainer(
|
||||||
_bodyFontSize,
|
bodyFontSize,
|
||||||
computeBodyLines(layoutHeight),
|
computeBodyLines(layoutHeight),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -149,7 +149,7 @@ class LinkView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTitleContainer(TextStyle _titleTS, int _maxLines) {
|
Widget _buildTitleContainer(TextStyle titleTS, int maxLines) {
|
||||||
final bool showUrl = this.showUrl && url.isNotEmpty;
|
final bool showUrl = this.showUrl && url.isNotEmpty;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(4, 2, 3, 0),
|
padding: const EdgeInsets.fromLTRB(4, 2, 3, 0),
|
||||||
@ -159,9 +159,9 @@ class LinkView extends StatelessWidget {
|
|||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: _titleTS,
|
style: titleTS,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: _maxLines,
|
maxLines: maxLines,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (showUrl)
|
if (showUrl)
|
||||||
@ -170,10 +170,10 @@ class LinkView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'($readableUrl)',
|
'($readableUrl)',
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: _titleTS.copyWith(
|
style: titleTS.copyWith(
|
||||||
color: Palette.grey,
|
color: Palette.grey,
|
||||||
fontSize:
|
fontSize:
|
||||||
_titleTS.fontSize == null ? 12 : _titleTS.fontSize! - 4,
|
titleTS.fontSize == null ? 12 : titleTS.fontSize! - 4,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
||||||
@ -185,7 +185,7 @@ class LinkView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBodyContainer(TextStyle _bodyTS, int _maxLines) {
|
Widget _buildBodyContainer(TextStyle bodyTS, int maxLines) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -198,9 +198,9 @@ class LinkView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
metadata,
|
metadata,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: _bodyTS.copyWith(
|
style: bodyTS.copyWith(
|
||||||
fontSize:
|
fontSize:
|
||||||
_bodyTS.fontSize == null ? 12 : _bodyTS.fontSize! - 2,
|
bodyTS.fontSize == null ? 12 : bodyTS.fontSize! - 2,
|
||||||
),
|
),
|
||||||
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
@ -212,9 +212,9 @@ class LinkView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
description,
|
description,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: _bodyTS,
|
style: bodyTS,
|
||||||
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
|
||||||
maxLines: (bodyMaxLines ?? _maxLines) -
|
maxLines: (bodyMaxLines ?? maxLines) -
|
||||||
(showMetadata ? 1 : 0) -
|
(showMetadata ? 1 : 0) -
|
||||||
(showUrl && url.isNotEmpty ? 1 : 0),
|
(showUrl && url.isNotEmpty ? 1 : 0),
|
||||||
),
|
),
|
||||||
|
@ -63,7 +63,7 @@ class WebImageInfo extends InfoBase {
|
|||||||
|
|
||||||
/// Video Information
|
/// Video Information
|
||||||
class WebVideoInfo extends WebImageInfo {
|
class WebVideoInfo extends WebImageInfo {
|
||||||
WebVideoInfo({String? image}) : super(image: image);
|
WebVideoInfo({super.image});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Web analyzer
|
/// Web analyzer
|
||||||
|
@ -6,7 +6,7 @@ import 'package:hacki/styles/styles.dart';
|
|||||||
import 'package:hacki/utils/utils.dart';
|
import 'package:hacki/utils/utils.dart';
|
||||||
|
|
||||||
class OnboardingView extends StatefulWidget {
|
class OnboardingView extends StatefulWidget {
|
||||||
const OnboardingView({Key? key}) : super(key: key);
|
const OnboardingView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OnboardingView> createState() => _OnboardingViewState();
|
State<OnboardingView> createState() => _OnboardingViewState();
|
||||||
@ -106,10 +106,9 @@ class _OnboardingViewState extends State<OnboardingView> {
|
|||||||
|
|
||||||
class _PageViewChild extends StatelessWidget {
|
class _PageViewChild extends StatelessWidget {
|
||||||
const _PageViewChild({
|
const _PageViewChild({
|
||||||
Key? key,
|
|
||||||
required this.path,
|
required this.path,
|
||||||
required this.description,
|
required this.description,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final String path;
|
final String path;
|
||||||
final String description;
|
final String description;
|
||||||
|
@ -56,7 +56,7 @@ class StoryTile extends StatelessWidget {
|
|||||||
titleStyle: TextStyle(
|
titleStyle: TextStyle(
|
||||||
color: hasRead
|
color: hasRead
|
||||||
? Palette.grey[500]
|
? Palette.grey[500]
|
||||||
: Theme.of(context).textTheme.subtitle1?.color,
|
: Theme.of(context).textTheme.bodyLarge?.color,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
showMetadata: showMetadata,
|
showMetadata: showMetadata,
|
||||||
@ -90,7 +90,7 @@ class StoryTile extends StatelessWidget {
|
|||||||
? Palette.grey[500]
|
? Palette.grey[500]
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyText1
|
.bodyLarge
|
||||||
?.color,
|
?.color,
|
||||||
fontSize: simpleTileFontSize,
|
fontSize: simpleTileFontSize,
|
||||||
),
|
),
|
||||||
@ -137,9 +137,8 @@ class StoryTile extends StatelessWidget {
|
|||||||
|
|
||||||
class _LinkPreviewPlaceholder extends StatelessWidget {
|
class _LinkPreviewPlaceholder extends StatelessWidget {
|
||||||
const _LinkPreviewPlaceholder({
|
const _LinkPreviewPlaceholder({
|
||||||
Key? key,
|
|
||||||
required this.height,
|
required this.height,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final double height;
|
final double height;
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ export 'custom_chip.dart';
|
|||||||
export 'custom_circular_progress_indicator.dart';
|
export 'custom_circular_progress_indicator.dart';
|
||||||
export 'items_list_view.dart';
|
export 'items_list_view.dart';
|
||||||
export 'link_preview/link_preview.dart';
|
export 'link_preview/link_preview.dart';
|
||||||
export 'link_preview/link_preview.dart';
|
|
||||||
export 'offline_banner.dart';
|
export 'offline_banner.dart';
|
||||||
export 'onboarding_view.dart';
|
export 'onboarding_view.dart';
|
||||||
export 'spring_curve.dart';
|
export 'spring_curve.dart';
|
||||||
|
@ -38,3 +38,8 @@ abstract class TextDimens {
|
|||||||
static const double pt26 = 26;
|
static const double pt26 = 26;
|
||||||
static const double pt36 = 36;
|
static const double pt36 = 36;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NumSwitch {
|
||||||
|
static const double on = 1;
|
||||||
|
static const double off = 0;
|
||||||
|
}
|
||||||
|
727
pubspec.lock
727
pubspec.lock
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
|||||||
name: hacki
|
name: hacki
|
||||||
description: A Hacker News reader.
|
description: A Hacker News reader.
|
||||||
version: 1.0.2+80
|
version: 1.0.3+81
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
flutter: "3.3.10"
|
flutter: "3.7.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
adaptive_theme: ^3.0.0
|
adaptive_theme: ^3.0.0
|
||||||
@ -73,12 +73,14 @@ dependencies:
|
|||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
bloc_test: ^9.1.0
|
bloc_test: ^9.1.0
|
||||||
|
flutter_driver:
|
||||||
|
sdk: flutter
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
integration_test:
|
integration_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
mocktail: ^0.3.0
|
mocktail: ^0.3.0
|
||||||
very_good_analysis: ^2.4.0
|
very_good_analysis: ^3.1.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
Submodule submodules/flutter updated: 135454af32...b06b8b2710
@ -20,8 +20,11 @@ void main() {
|
|||||||
final MockStoriesRepository mockStoriesRepository = MockStoriesRepository();
|
final MockStoriesRepository mockStoriesRepository = MockStoriesRepository();
|
||||||
final MockSembastRepository mockSembastRepository = MockSembastRepository();
|
final MockSembastRepository mockSembastRepository = MockSembastRepository();
|
||||||
|
|
||||||
const int created = 0, delay = 1, karma = 2;
|
const int created = 0;
|
||||||
const String about = 'about', id = 'id';
|
const int delay = 1;
|
||||||
|
const int karma = 2;
|
||||||
|
const String about = 'about';
|
||||||
|
const String id = 'id';
|
||||||
|
|
||||||
const User tUser = User(
|
const User tUser = User(
|
||||||
about: about,
|
about: about,
|
||||||
@ -57,7 +60,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
group('AuthAppStarted', () {
|
group('AuthAppStarted', () {
|
||||||
const String username = 'username', password = 'password';
|
const String username = 'username';
|
||||||
|
const String password = 'password';
|
||||||
setUp(() {
|
setUp(() {
|
||||||
when(() => mockAuthRepository.username)
|
when(() => mockAuthRepository.username)
|
||||||
.thenAnswer((_) => Future<String?>.value(username));
|
.thenAnswer((_) => Future<String?>.value(username));
|
||||||
|
Reference in New Issue
Block a user