Merge pull request #622 from ente-io/lint_action

Add Github action to run lint check
This commit is contained in:
Neeraj Gupta 2022-11-06 14:17:45 +05:30 committed by GitHub
commit f8beb64495
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 210 additions and 160 deletions

33
.github/workflows/code_quality.yml vendored Normal file
View file

@ -0,0 +1,33 @@
name: Check Linter Rules
on:
pull_request:
branches:
- master
jobs:
test:
if: github.event.pull_request.draft == 'false'
name: Check the source code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v2
with:
path: ${{ runner.tool_cache }}/flutter
key: flutter-3.0.0-stable
# Setup the flutter environment.
- uses: subosito/flutter-action@v2.3.0
with:
channel: 'stable'
flutter-version: '3.0.0'
# Fetch sub modules
- run: git submodule update --init --recursive
# Get flutter dependencies.
- name: Install packages
run: flutter pub get
- name: Run Linter
run: flutter analyze --no-fatal-infos
# - name: Run Test :sed:
# run: flutter test

View file

@ -55,9 +55,11 @@ analyzer:
prefer_const_constructors: warning
prefer_const_declarations: warning
prefer_const_constructors_in_immutables: warning
prefer_final_locals: warning
unnecessary_const: error
cancel_subscriptions: error
invalid_dependency: info
use_build_context_synchronously: ignore # experimental lint, requires many changes
prefer_interpolation_to_compose_strings: ignore # later too many warnings
prefer_double_quotes: ignore # too many warnings

View file

@ -66,8 +66,10 @@ class EnteRequestInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (kDebugMode) {
assert(options.baseUrl == Network.apiEndpoint,
"interceptor should only be used for API endpoint");
assert(
options.baseUrl == Network.apiEndpoint,
"interceptor should only be used for API endpoint",
);
}
// ignore: prefer_const_constructors
options.headers.putIfAbsent("x-request-id", () => Uuid().v4().toString());

View file

@ -645,7 +645,7 @@ class FilesDB {
inParam = inParam.substring(0, inParam.length - 1);
final db = await instance.database;
final order = (asc ?? false ? 'ASC' : 'DESC');
String whereClause =
final String whereClause =
'$columnCollectionID IN ($inParam) AND $columnCreationTime >= ? AND '
'$columnCreationTime <= ? AND $columnOwnerID = ?';
final List<Object> whereArgs = [startTime, endTime, userID];
@ -1261,7 +1261,8 @@ class FilesDB {
}
Future<Map<int, List<File>>> getAllFilesGroupByCollectionID(
List<int> ids) async {
List<int> ids,
) async {
final result = <int, List<File>>{};
if (ids.isEmpty) {
return result;

View file

@ -161,9 +161,9 @@ class File extends EnteFile {
duration = asset.duration;
}
}
if (fileType == FileType.image) {
if (fileType == FileType.image && mediaUploadData.sourceFile != null) {
final exifTime =
await getCreationTimeFromEXIF(mediaUploadData.sourceFile);
await getCreationTimeFromEXIF(mediaUploadData.sourceFile!);
if (exifTime != null) {
creationTime = exifTime.microsecondsSinceEpoch;
}

View file

@ -264,8 +264,10 @@ Future<List<AssetEntity>> _getAllAssetLists(AssetPathEntity pathEntity) async {
size: assetFetchPageSize,
);
Bus.instance.fire(
LocalImportProgressEvent(pathEntity.name,
currentPage * assetFetchPageSize + currentPageResult.length),
LocalImportProgressEvent(
pathEntity.name,
currentPage * assetFetchPageSize + currentPageResult.length,
),
);
result.addAll(currentPageResult);
currentPage = currentPage + 1;

View file

@ -360,16 +360,20 @@ class RemoteSyncService {
if (pendingUploads.isEmpty) {
continue;
} else {
_logger.info("RemovingFiles $collectionIDs: pendingUploads "
"${pendingUploads.length}");
_logger.info(
"RemovingFiles $collectionIDs: pendingUploads "
"${pendingUploads.length}",
);
}
final Set<String> localIDsInOtherFileEntries =
await _db.getLocalIDsPresentInEntries(
pendingUploads,
collectionID,
);
_logger.info("RemovingFiles $collectionIDs: filesInOtherCollection "
"${localIDsInOtherFileEntries.length}");
_logger.info(
"RemovingFiles $collectionIDs: filesInOtherCollection "
"${localIDsInOtherFileEntries.length}",
);
final List<File> entriesToUpdate = [];
final List<int> entriesToDelete = [];
for (File pendingUpload in pendingUploads) {

View file

@ -63,142 +63,148 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
: 120;
return Scaffold(
appBar: widget.showProgressBar
? AppBar(
elevation: 0,
title: Hero(
tag: "recovery_key",
child: StepProgressIndicator(
totalSteps: 4,
currentStep: 3,
selectedColor:
Theme.of(context).colorScheme.greenAlternative,
roundedEdges: const Radius.circular(10),
unselectedColor: Theme.of(context)
.colorScheme
.stepProgressUnselectedColor,
),
appBar: widget.showProgressBar
? AppBar(
elevation: 0,
title: Hero(
tag: "recovery_key",
child: StepProgressIndicator(
totalSteps: 4,
currentStep: 3,
selectedColor: Theme.of(context).colorScheme.greenAlternative,
roundedEdges: const Radius.circular(10),
unselectedColor:
Theme.of(context).colorScheme.stepProgressUnselectedColor,
),
)
: widget.showAppBar
? AppBar(
elevation: 0,
title: Text(widget.title ?? "Recovery key"),
)
: null,
body: Padding(
padding: EdgeInsets.fromLTRB(20, topPadding, 20, 20),
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth,
minHeight: constraints.maxHeight),
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
widget.showAppBar
? const SizedBox.shrink()
: Text(
widget.title ?? "Recovery key",
style: Theme.of(context).textTheme.headline4,
),
Padding(
padding:
EdgeInsets.all(widget.showAppBar ? 0 : 12)),
Text(
widget.text ??
"If you forget your password, the only way you can recover your data is with this key.",
style: Theme.of(context).textTheme.subtitle1,
),
const Padding(padding: EdgeInsets.only(top: 24)),
DottedBorder(
color: const Color.fromRGBO(17, 127, 56, 1),
//color of dotted/dash line
strokeWidth: 1,
//thickness of dash/dots
dashPattern: const [6, 6],
radius: const Radius.circular(8),
//dash patterns, 10 is dash width, 6 is space width
child: SizedBox(
//inner container
// height: 120, //height of inner container
width: double
.infinity, //width to 100% match to parent container.
// ignore: prefer_const_literals_to_create_immutables
child: Column(
children: [
GestureDetector(
onTap: () async {
await Clipboard.setData(
ClipboardData(text: recoveryKey),
);
showToast(context,
"Recovery key copied to clipboard");
setState(() {
_hasTriedToSave = true;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: const Color.fromRGBO(
49, 155, 86, .2),
),
)
: widget.showAppBar
? AppBar(
elevation: 0,
title: Text(widget.title ?? "Recovery key"),
)
: null,
body: Padding(
padding: EdgeInsets.fromLTRB(20, topPadding, 20, 20),
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth,
minHeight: constraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
widget.showAppBar
? const SizedBox.shrink()
: Text(
widget.title ?? "Recovery key",
style: Theme.of(context).textTheme.headline4,
),
Padding(
padding: EdgeInsets.all(widget.showAppBar ? 0 : 12),
),
Text(
widget.text ??
"If you forget your password, the only way you can recover your data is with this key.",
style: Theme.of(context).textTheme.subtitle1,
),
const Padding(padding: EdgeInsets.only(top: 24)),
DottedBorder(
color: const Color.fromRGBO(17, 127, 56, 1),
//color of dotted/dash line
strokeWidth: 1,
//thickness of dash/dots
dashPattern: const [6, 6],
radius: const Radius.circular(8),
//dash patterns, 10 is dash width, 6 is space width
child: SizedBox(
//inner container
// height: 120, //height of inner container
width: double
.infinity, //width to 100% match to parent container.
// ignore: prefer_const_literals_to_create_immutables
child: Column(
children: [
GestureDetector(
onTap: () async {
await Clipboard.setData(
ClipboardData(text: recoveryKey),
);
showToast(
context,
"Recovery key copied to clipboard",
);
setState(() {
_hasTriedToSave = true;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: const Color.fromRGBO(
49,
155,
86,
.2,
),
borderRadius: const BorderRadius.all(
Radius.circular(2),
),
color: Theme.of(context)
.colorScheme
.recoveryKeyBoxColor,
),
padding: const EdgeInsets.all(20),
width: double.infinity,
child: Text(
recoveryKey,
style:
Theme.of(context).textTheme.bodyText1,
borderRadius: const BorderRadius.all(
Radius.circular(2),
),
color: Theme.of(context)
.colorScheme
.recoveryKeyBoxColor,
),
padding: const EdgeInsets.all(20),
width: double.infinity,
child: Text(
recoveryKey,
style:
Theme.of(context).textTheme.bodyText1,
),
),
],
),
),
],
),
),
SizedBox(
height: 80,
),
SizedBox(
height: 80,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Text(
widget.subText ??
"We dont store this key, please save this in a safe place.",
style: Theme.of(context).textTheme.bodyText1,
),
),
),
Expanded(
child: Container(
alignment: Alignment.bottomCenter,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Text(
widget.subText ??
"We dont store this key, please save this in a safe place.",
style: Theme.of(context).textTheme.bodyText1,
),
padding: const EdgeInsets.fromLTRB(10, 10, 10, 42),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _saveOptions(context, recoveryKey),
),
),
Expanded(
child: Container(
alignment: Alignment.bottomCenter,
width: double.infinity,
padding: const EdgeInsets.fromLTRB(10, 10, 10, 42),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _saveOptions(context, recoveryKey),
),
),
)
],
), // columnEnds
),
)
],
), // columnEnds
),
);
},
),
));
),
);
},
),
),
);
}
List<Widget> _saveOptions(BuildContext context, String recoveryKey) {

View file

@ -41,8 +41,10 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
_tabChangedEventSubscription =
Bus.instance.on<TabChangedEvent>().listen((event) {
if (event.source != TabChangedEventSource.tabBar) {
debugPrint('${(TabChangedEvent).toString()} index changed from '
'$currentTabIndex to ${event.selectedIndex} via ${event.source}');
debugPrint(
'${(TabChangedEvent).toString()} index changed from '
'$currentTabIndex to ${event.selectedIndex} via ${event.source}',
);
if (mounted) {
setState(() {
currentTabIndex = event.selectedIndex;

View file

@ -27,7 +27,7 @@ class HomeGalleryWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
double bottomSafeArea = MediaQuery.of(context).padding.bottom;
final double bottomSafeArea = MediaQuery.of(context).padding.bottom;
final gallery = Gallery(
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) async {
final ownerID = Configuration.instance.getUserID();

View file

@ -89,7 +89,8 @@ class _HomeWidgetState extends State<HomeWidget> {
Bus.instance.on<TabChangedEvent>().listen((event) {
if (event.source != TabChangedEventSource.pageView) {
debugPrint(
"TabChange going from $_selectedTabIndex to ${event.selectedIndex} souce: ${event.source}");
"TabChange going from $_selectedTabIndex to ${event.selectedIndex} souce: ${event.source}",
);
_selectedTabIndex = event.selectedIndex;
// _pageController.jumpToPage(_selectedTabIndex);
_pageController.animateToPage(

View file

@ -1,6 +1,6 @@
// @dart=2.9
import 'dart:math' show max, min;
import 'dart:math' show max;
import 'package:flutter/material.dart';
import 'package:photos/ui/huge_listview/draggable_scrollbar.dart';

View file

@ -3,7 +3,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:photos/ente_theme_data.dart';
import 'package:photos/models/billing_plan.dart';
import 'package:photos/models/subscription.dart';
@ -38,7 +37,6 @@ class StripeSubscriptionPage extends StatefulWidget {
}
class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
final _logger = Logger("StripeSubscriptionPage");
final _billingService = BillingService.instance;
final _userService = UserService.instance;
Subscription _currentSubscription;

View file

@ -15,7 +15,6 @@ class AppVersionWidget extends StatefulWidget {
class _AppVersionWidgetState extends State<AppVersionWidget> {
static const kTapThresholdForInspector = 5;
static const kConsecutiveTapTimeWindowInMilliseconds = 2000;
static const kDummyDelayDurationInMilliseconds = 1500;
int _lastTap;
int _consecutiveTaps = 0;

View file

@ -471,7 +471,10 @@ class FadingAppBarState extends State<FadingAppBar> {
}
Future<void> _saveLivePhotoOnDroid(
io.File image, io.File video, File enteFile) async {
io.File image,
io.File video,
File enteFile,
) async {
debugPrint("Downloading LivePhoto on Droid");
AssetEntity savedAsset = await PhotoManager.editor
.saveImageWithPath(image.path, title: enteFile.title);
@ -502,7 +505,7 @@ class FadingAppBarState extends State<FadingAppBar> {
await dialog.show();
try {
final io.File fileToSave = await getFile(file);
var m = MediaExtension();
final m = MediaExtension();
final bool result = await m.setAs("file://${fileToSave.path}", "image/*");
if (result == false) {
showShortToast(context, "Something went wrong");

View file

@ -91,7 +91,7 @@ class FadingBottomBarState extends State<FadingBottomBar> {
if (widget.file is TrashFile) {
_addTrashOptions(children);
}
bool isUploadedByUser = widget.file.uploadedFileID != null &&
final bool isUploadedByUser = widget.file.uploadedFileID != null &&
widget.file.ownerID == Configuration.instance.getUserID();
bool isFileHidden = false;
if (isUploadedByUser) {

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'dart:io' as io;
import 'package:exif/exif.dart';
@ -29,18 +27,16 @@ Future<Map<String, IfdTag>> getExif(File file) async {
}
}
Future<DateTime> getCreationTimeFromEXIF(io.File file) async {
Future<DateTime?> getCreationTimeFromEXIF(io.File file) async {
try {
final exif = await readExifFromFile(file);
if (exif != null) {
final exifTime = exif.containsKey(kDateTimeOriginal)
? exif[kDateTimeOriginal].printable
: exif.containsKey(kImageDateTime)
? exif[kImageDateTime].printable
: null;
if (exifTime != null && exifTime != kEmptyExifDateTime) {
return DateFormat(kExifDateTimePattern).parse(exifTime);
}
final exifTime = exif.containsKey(kDateTimeOriginal)
? exif[kDateTimeOriginal]!.printable
: exif.containsKey(kImageDateTime)
? exif[kImageDateTime]!.printable
: null;
if (exifTime != null && exifTime != kEmptyExifDateTime) {
return DateFormat(kExifDateTimePattern).parse(exifTime);
}
} catch (e) {
_logger.severe("failed to getCreationTimeFromEXIF", e);

View file

@ -188,7 +188,8 @@ class FileUploader {
_queue.remove(id).completer.completeError(reason);
}
_logger.info(
'number of enteries removed from queue ${uploadsToBeRemoved.length}');
'number of enteries removed from queue ${uploadsToBeRemoved.length}',
);
_totalCountInUploadSession -= uploadsToBeRemoved.length;
}