diff --git a/.cspell/dart_flutter.txt b/.cspell/dart_flutter.txt new file mode 100644 index 00000000..0639e559 --- /dev/null +++ b/.cspell/dart_flutter.txt @@ -0,0 +1,9 @@ +autofocus +gapless +lerp +pubspec +sublist +todos +unawaited +unfocus +writeln diff --git a/.cspell/misc.txt b/.cspell/misc.txt new file mode 100644 index 00000000..94f59994 --- /dev/null +++ b/.cspell/misc.txt @@ -0,0 +1,11 @@ +browsable +cleartext +deeplinking +flathub +foss +fullscreen +playstore +postmarket +provokateurin +subroutes +uncategorized diff --git a/.cspell/neon.txt b/.cspell/neon.txt new file mode 100644 index 00000000..175b008f --- /dev/null +++ b/.cspell/neon.txt @@ -0,0 +1,20 @@ +crypton +exportables +fcmup +filesize +gotify +heckel +mocktail +nextpush +noprovider +ntfy +oled +oledas +rxdart +seti +siacs +sqflite +underspecified +updateshouldnotify +wakelock +zxing diff --git a/.cspell/nextcloud.txt b/.cspell/nextcloud.txt new file mode 100644 index 00000000..0880b4e9 --- /dev/null +++ b/.cspell/nextcloud.txt @@ -0,0 +1,71 @@ +apirequest +applist +apppassword +approximative +appstore +bigfilechunking +bools +bulkupload +commenters +csapi +datetime +deletedshares +displayname +etag +fediverse +getapppassword +groupid +hovercard +iscustomavatar +itemsperpage +keepalive +keypair +lastmod +licence +logfile +logoheader +mimetypes +mountpoint +navigations +nextcloud +nextcloud's +openlocaleditor +organisation +prio +productname +publicpreview +reshares +resharing +rgdnvw +r'sharebymail +r'updatenotification +r'uppush +shareapi +sharebymail +sharee +shareesapi +shareinfo +statuscode +stime +stylesheet +subadmin +subadmins +subfiles +subline +tasktypes +textprocessing +totalitems +transferownership +trashbin +undelete +unifiedpush +unsharing +unstar +updatenotification +uppush +usercount +usergroup +userid +userroom +versionstring +whatsnew diff --git a/.cspell/tools.txt b/.cspell/tools.txt new file mode 100644 index 00000000..35a57397 --- /dev/null +++ b/.cspell/tools.txt @@ -0,0 +1,60 @@ +aarch +allprojects +appindicator +autoptr +buildscript +buildsystem +buildx +cest +classpath +cloc +commitlint +dapplication +dists +endforeach +endfunction +endlegend +endswith +enduml +euxo +exiftool +extglob +freedesktop +fullpath +gboolean +gchar +genhtml +gradlew +hicolor +icudtl +inkscape +intellij +jetbrains +jvmargs +klass +lcov +libapp +libappindicator +libayatana +libflutter +libindicator +libsqlite +mipmap +ndebug +nproc +plantuml +precache +puml +rpath +startuml +stdlib +strconcat +strdupv +strfreev +subprojects +sysroot +tsvg +werror +workdir +xxxh +xxxhdpi diff --git a/.cspell/webdav.txt b/.cspell/webdav.txt new file mode 100644 index 00000000..8085aee1 --- /dev/null +++ b/.cspell/webdav.txt @@ -0,0 +1,50 @@ +copymove +dasl +davgetcontentlength +davgetcontenttype +davgetetag +davgetlastmodified +davresourcetype +fileid +getcontentlength +getcontenttype +getetag +getlastmodified +largefile +mkcol +multistatus +nccreationtime +ncdatafingerprint +nchaspreview +ncisencrypted +ncmetadataetag +ncmounttype +ncnote +ncrichworkspace +ncuploadtime +nodestcoll +noncoll +noparent +occommentscount +occommentshref +occommentsunread +ocdownloadurl +ocfavorite +ocfileid +ocid +ocmsharepermissions +ocownerdisplayname +ocownerid +ocpermissions +ocsize +ocssharepermissions +owncloud +propertyupdate +propfind +proppatch +propstat +propstats +resourcetype +sharees +systemtag +webdav diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml new file mode 100644 index 00000000..65e0751b --- /dev/null +++ b/.github/workflows/spellcheck.yaml @@ -0,0 +1,10 @@ +name: 'Check spelling' +on: + pull_request: + +jobs: + spellcheck: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: streetsidesoftware/cspell-action@v3 diff --git a/README.md b/README.md index 9a4945ac..8bc73a34 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The Neon project has three main goals: The Neon project uses [Dart](https://dart.dev/) and [Flutter](https://flutter.dev/) to help mobile client developers building apps. Flutter allows us to build convergent cross-platform clients that feel native. We are a 100% FOSS framework and do not rely on any proprietary libraries making it easy for developers to publish their apps in places like the [F-Droid](https://f-droid.org/) store. -We provide a generated [Nextcloud Dart client](packages/nextcloud) that is generated from the new OpenAPI specifications shipped with Nextcloud and is already being used by other Dart and Flutter projects. Gone are the days of looking at the PHP code and implementing an API client by hand wich can be time-consuming and very error-prone. +We provide a generated [Nextcloud Dart client](packages/nextcloud) that is generated from the new OpenAPI specifications shipped with Nextcloud and is already being used by other Dart and Flutter projects. Gone are the days of looking at the PHP code and implementing an API client by hand which can be time-consuming and very error-prone. We provide abstractions, common utilities and prebuilt UI components (called Widgets in Flutter) that can be re-used. This allows Neon to make developing a new Nextcloud client as easy as adding a few custom UI elements and the necessary state management, while everything else is already taken care of for you. diff --git a/cspell.json b/cspell.json new file mode 100644 index 00000000..eb3a04ff --- /dev/null +++ b/cspell.json @@ -0,0 +1,60 @@ +{ + "version": "0.2", + "language": "en", + "words": [ + "OpenAPI" + ], + "ignorePaths": [ + "**.iml", + "**.log", + "**.svg", + "**/assets/**", + "**/build/**", + "**/coverage/**", + "**/ephemeral/**", + "**/l10n/!(en.arb)", + "external", + "packages/app/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java", + "packages/app/android/gradlew*", + "packages/file_icons/lib/src/data.dart", + "packages/neon_lints/lib", + "packages/nextcloud/test/files" + ], + "dictionaries": [ + "bash", + "dart_flutter", + "en_US", + "misc", + "neon", + "nextcloud", + "softwareTerms", + "tools", + "webdav" + ], + "dictionaryDefinitions": [ + { + "name": "dart_flutter", + "path": ".cspell/dart_flutter.txt" + }, + { + "name": "misc", + "path": ".cspell/misc.txt" + }, + { + "name": "neon", + "path": ".cspell/neon.txt" + }, + { + "name": "nextcloud", + "path": ".cspell/nextcloud.txt" + }, + { + "name": "tools", + "path": ".cspell/tools.txt" + }, + { + "name": "webdav", + "path": ".cspell/webdav.txt" + } + ] +} diff --git a/external/nextcloud-notifications b/external/nextcloud-notifications index 9e4bfdcf..8056d80c 160000 --- a/external/nextcloud-notifications +++ b/external/nextcloud-notifications @@ -1 +1 @@ -Subproject commit 9e4bfdcf04d3a17402f4b22166e1afd4fc7ff833 +Subproject commit 8056d80ce22aeef0a65c3f2523869e7ea0f37f54 diff --git a/packages/file_icons/bin/file_icons.dart b/packages/file_icons/bin/file_icons.dart index 8a980a0e..cea7b274 100644 --- a/packages/file_icons/bin/file_icons.dart +++ b/packages/file_icons/bin/file_icons.dart @@ -98,7 +98,7 @@ void generateData() { "import 'package:flutter/widgets.dart';", '', '// Code points', - // This filters unused codepoints. + // This filters unused code points. for (final type in codePoints.keys .where((final type) => iconSet.keys.map((final pattern) => iconSet[pattern]![0] == type).contains(true))) ...[ 'const ${_toVariableName(type)} = ${codePoints[type]};', diff --git a/packages/neon/neon/lib/l10n/en.arb b/packages/neon/neon/lib/l10n/en.arb index d8c3f2b3..a5a715f9 100644 --- a/packages/neon/neon/lib/l10n/en.arb +++ b/packages/neon/neon/lib/l10n/en.arb @@ -12,7 +12,7 @@ "loginOpenAgain": "Open again", "loginSwitchToBrowserWindow": "Please switch to the browser window that just opened and proceed there", "loginWorksWith": "works with", - "loginUsingQrcode": "Login using a QR code", + "loginUsingQRcode": "Login using a QR code", "loginUsingServerAddress": "Login using the server address", "loginCheckingServerVersion": "Checking server version", "loginSupportedServerVersion": "Supported server version: {version}", @@ -69,7 +69,7 @@ }, "errorEmptyField": "This field can not be empty", "errorInvalidURL": "Invalid URL provided", - "errorInvalidQrcode": "Invalid QR-Code provided", + "errorInvalidQRcode": "Invalid QR-Code provided", "errorRouteNotFound": "Route not found: {route}", "@errorRouteNotFound" : { "placeholders": { diff --git a/packages/neon/neon/lib/l10n/localizations.dart b/packages/neon/neon/lib/l10n/localizations.dart index c9720a38..f95d6212 100644 --- a/packages/neon/neon/lib/l10n/localizations.dart +++ b/packages/neon/neon/lib/l10n/localizations.dart @@ -131,11 +131,11 @@ abstract class AppLocalizations { /// **'works with'** String get loginWorksWith; - /// No description provided for @loginUsingQrcode. + /// No description provided for @loginUsingQRcode. /// /// In en, this message translates to: /// **'Login using a QR code'** - String get loginUsingQrcode; + String get loginUsingQRcode; /// No description provided for @loginUsingServerAddress. /// @@ -263,11 +263,11 @@ abstract class AppLocalizations { /// **'Invalid URL provided'** String get errorInvalidURL; - /// No description provided for @errorInvalidQrcode. + /// No description provided for @errorInvalidQRcode. /// /// In en, this message translates to: /// **'Invalid QR-Code provided'** - String get errorInvalidQrcode; + String get errorInvalidQRcode; /// No description provided for @errorRouteNotFound. /// diff --git a/packages/neon/neon/lib/l10n/localizations_en.dart b/packages/neon/neon/lib/l10n/localizations_en.dart index 34c2cef8..071828f9 100644 --- a/packages/neon/neon/lib/l10n/localizations_en.dart +++ b/packages/neon/neon/lib/l10n/localizations_en.dart @@ -42,7 +42,7 @@ class AppLocalizationsEn extends AppLocalizations { String get loginWorksWith => 'works with'; @override - String get loginUsingQrcode => 'Login using a QR code'; + String get loginUsingQRcode => 'Login using a QR code'; @override String get loginUsingServerAddress => 'Login using the server address'; @@ -121,7 +121,7 @@ class AppLocalizationsEn extends AppLocalizations { String get errorInvalidURL => 'Invalid URL provided'; @override - String get errorInvalidQrcode => 'Invalid QR-Code provided'; + String get errorInvalidQRcode => 'Invalid QR-Code provided'; @override String errorRouteNotFound(String route) { diff --git a/packages/neon/neon/lib/models.dart b/packages/neon/neon/lib/models.dart index 600a662b..90ca9d97 100644 --- a/packages/neon/neon/lib/models.dart +++ b/packages/neon/neon/lib/models.dart @@ -1,4 +1,4 @@ -export 'package:neon/src/models/account.dart' hide Credentials, LoginQrcode; +export 'package:neon/src/models/account.dart' hide Credentials, LoginQRcode; export 'package:neon/src/models/app_ids.dart'; export 'package:neon/src/models/app_implementation.dart'; export 'package:neon/src/models/notifications_interface.dart'; diff --git a/packages/neon/neon/lib/src/models/account.dart b/packages/neon/neon/lib/src/models/account.dart index 4710796f..da5990d5 100644 --- a/packages/neon/neon/lib/src/models/account.dart +++ b/packages/neon/neon/lib/src/models/account.dart @@ -117,16 +117,16 @@ extension AccountFind on Iterable { Account find(final String accountID) => firstWhere((final account) => account.id == accountID); } -/// Qrcode Login credentials. +/// QRcode Login credentials. /// /// The Credentials as provided by the server when manually creating an app /// password. @internal @immutable -class LoginQrcode implements Credentials { - /// Creates a new LoginQrcode object. +class LoginQRcode implements Credentials { + /// Creates a new LoginQRcode object. @visibleForTesting - const LoginQrcode({ + const LoginQRcode({ required this.serverURL, required this.username, required this.password, @@ -139,31 +139,31 @@ class LoginQrcode implements Credentials { @override final String password; - /// Pattern matching the full Qrcode content. - static final _loginQrcodeUrlRegex = RegExp(r'^nc://login/user:(.*)&password:(.*)&server:(.*)$'); + /// Pattern matching the full QRcode content. + static final _loginQRcodeUrlRegex = RegExp(r'^nc://login/user:(.*)&password:(.*)&server:(.*)$'); - /// Pattern matching the path part of the Qrcode. + /// Pattern matching the path part of the QRcode. /// /// This is used when launching the app through an intent. - static final _loginQrcodePathRegex = RegExp(r'^/user:(.*)&password:(.*)&server:(.*)$'); + static final _loginQRcodePathRegex = RegExp(r'^/user:(.*)&password:(.*)&server:(.*)$'); - /// Creates a new `LoginQrcode` object by parsing a url string. + /// Creates a new `LoginQRcode` object by parsing a url string. /// - /// If the [url] string is not valid as a LoginQrcode a [FormatException] is + /// If the [url] string is not valid as a LoginQRcode a [FormatException] is /// thrown. /// /// Example: /// ```dart - /// final loginQrcode = - /// LoginQrcode.parse('nc://login/user:JohnDoe&password:super_secret&server:example.com'); - /// print(loginQrcode.serverURL); // JohnDoe - /// print(loginQrcode.username); // super_secret - /// print(loginQrcode.password); // example.com + /// final loginQRcode = + /// LoginQRcode.parse('nc://login/user:JohnDoe&password:super_secret&server:example.com'); + /// print(loginQRcode.serverURL); // JohnDoe + /// print(loginQRcode.username); // super_secret + /// print(loginQRcode.password); // example.com /// - /// LoginQrcode.parse('::Not valid LoginQrcode::'); // Throws FormatException. + /// LoginQRcode.parse('::Not valid LoginQRcode::'); // Throws FormatException. /// ``` - static LoginQrcode parse(final String url) { - for (final regex in [_loginQrcodeUrlRegex, _loginQrcodePathRegex]) { + static LoginQRcode parse(final String url) { + for (final regex in [_loginQRcodeUrlRegex, _loginQRcodePathRegex]) { final matches = regex.allMatches(url); if (matches.isEmpty) { continue; @@ -174,7 +174,7 @@ class LoginQrcode implements Credentials { continue; } - return LoginQrcode( + return LoginQRcode( serverURL: Uri.parse(match.group(3)!), username: match.group(1)!, password: match.group(2)!, @@ -184,22 +184,22 @@ class LoginQrcode implements Credentials { throw const FormatException(); } - /// Creates a new `LoginQrcode` object by parsing a url string. + /// Creates a new `LoginQRcode` object by parsing a url string. /// - /// Returns `null` if the [url] string is not valid as a LoginQrcode. + /// Returns `null` if the [url] string is not valid as a LoginQRcode. /// /// Example: /// ```dart - /// final loginQrcode = - /// LoginQrcode.parse('nc://login/user:JohnDoe&password:super_secret&server:example.com'); - /// print(loginQrcode.serverURL); // JohnDoe - /// print(loginQrcode.username); // super_secret - /// print(loginQrcode.password); // example.com + /// final loginQRcode = + /// LoginQRcode.parse('nc://login/user:JohnDoe&password:super_secret&server:example.com'); + /// print(loginQRcode.serverURL); // JohnDoe + /// print(loginQRcode.username); // super_secret + /// print(loginQRcode.password); // example.com /// - /// final notLoginQrcode = LoginQrcode.tryParse('::Not valid LoginQrcode::'); - /// print(notLoginQrcode); // null + /// final notLoginQRcode = LoginQRcode.tryParse('::Not valid LoginQRcode::'); + /// print(notLoginQRcode); // null /// ``` - static LoginQrcode? tryParse(final String url) { + static LoginQRcode? tryParse(final String url) { try { return parse(url); } on FormatException { @@ -209,7 +209,7 @@ class LoginQrcode implements Credentials { @override bool operator ==(final Object other) => - other is LoginQrcode && other.serverURL == serverURL && other.username == username && other.password == password; + other is LoginQRcode && other.serverURL == serverURL && other.username == username && other.password == password; @override int get hashCode => Object.hashAll([ diff --git a/packages/neon/neon/lib/src/models/disposable.dart b/packages/neon/neon/lib/src/models/disposable.dart index 72ada454..9b9bc693 100644 --- a/packages/neon/neon/lib/src/models/disposable.dart +++ b/packages/neon/neon/lib/src/models/disposable.dart @@ -11,10 +11,10 @@ abstract interface class Disposable { void dispose(); } -extension DisposeableIterableBloc on Iterable { +extension DisposableIterableBloc on Iterable { /// Calls [Disposable.dispose] on all entries. /// - /// The disposed values will not be removed from the iteraable. + /// The disposed values will not be removed from the iterable. void disposeAll() { for (final bloc in this) { bloc.dispose(); @@ -22,7 +22,7 @@ extension DisposeableIterableBloc on Iterable { } } -extension DisposeableMapBloc on Map { +extension DisposableMapBloc on Map { /// Calls [Disposable.dispose] on all entries. /// /// The disposed values will not be removed from the map. diff --git a/packages/neon/neon/lib/src/pages/login.dart b/packages/neon/neon/lib/src/pages/login.dart index f6ea1caa..ae587379 100644 --- a/packages/neon/neon/lib/src/pages/login.dart +++ b/packages/neon/neon/lib/src/pages/login.dart @@ -108,12 +108,12 @@ class _LoginPageState extends State { height: 50, ), IconButton( - tooltip: AppLocalizations.of(context).loginUsingQrcode, + tooltip: AppLocalizations.of(context).loginUsingQRcode, icon: const Icon( Icons.qr_code_scanner_rounded, size: 60, ), - onPressed: () => const LoginQrcodeRoute().go(context), + onPressed: () => const LoginQRcodeRoute().go(context), ), ], ], diff --git a/packages/neon/neon/lib/src/pages/login_qrcode.dart b/packages/neon/neon/lib/src/pages/login_qr_code.dart similarity index 81% rename from packages/neon/neon/lib/src/pages/login_qrcode.dart rename to packages/neon/neon/lib/src/pages/login_qr_code.dart index 8a581e0d..2446dbbc 100644 --- a/packages/neon/neon/lib/src/pages/login_qrcode.dart +++ b/packages/neon/neon/lib/src/pages/login_qr_code.dart @@ -7,16 +7,16 @@ import 'package:neon/src/utils/exceptions.dart'; import 'package:neon/src/widgets/exception.dart'; @internal -class LoginQrcodePage extends StatefulWidget { - const LoginQrcodePage({ +class LoginQRcodePage extends StatefulWidget { + const LoginQRcodePage({ super.key, }); @override - State createState() => _LoginQrcodePageState(); + State createState() => _LoginQRcodePageState(); } -class _LoginQrcodePageState extends State { +class _LoginQRcodePageState extends State { String? _lastErrorURL; @override @@ -35,11 +35,11 @@ class _LoginQrcodePageState extends State { try { url = code.text; if (url == null) { - throw InvalidQrcodeException(); + throw InvalidQRcodeException(); } - final match = LoginQrcode.tryParse(url); + final match = LoginQRcode.tryParse(url); if (match == null) { - throw InvalidQrcodeException(); + throw InvalidQRcodeException(); } LoginCheckServerStatusRoute.withCredentials( diff --git a/packages/neon/neon/lib/src/pages/route_not_found.dart b/packages/neon/neon/lib/src/pages/route_not_found.dart index 1966e8d7..5c7b771f 100644 --- a/packages/neon/neon/lib/src/pages/route_not_found.dart +++ b/packages/neon/neon/lib/src/pages/route_not_found.dart @@ -26,10 +26,10 @@ class _RouteNotFoundPageState extends State { void initState() { super.initState(); - unawaited(_checkLaunchable()); + unawaited(_checkCanLaunch()); } - Future _checkLaunchable() async { + Future _checkCanLaunch() async { final accountsBloc = NeonProvider.of(context); if (!accountsBloc.hasAccounts) { return; diff --git a/packages/neon/neon/lib/src/pages/settings.dart b/packages/neon/neon/lib/src/pages/settings.dart index 518e21c0..878e8247 100644 --- a/packages/neon/neon/lib/src/pages/settings.dart +++ b/packages/neon/neon/lib/src/pages/settings.dart @@ -208,7 +208,7 @@ class _SettingsPageState extends State { AccountSettingsTile( account: account, onTap: () { - AccountSettingsRoute(accountid: account.id).go(context); + AccountSettingsRoute(accountID: account.id).go(context); }, ), ], diff --git a/packages/neon/neon/lib/src/router.dart b/packages/neon/neon/lib/src/router.dart index 1b4b11fa..b1972c9b 100644 --- a/packages/neon/neon/lib/src/router.dart +++ b/packages/neon/neon/lib/src/router.dart @@ -15,7 +15,7 @@ import 'package:neon/src/pages/login.dart'; import 'package:neon/src/pages/login_check_account.dart'; import 'package:neon/src/pages/login_check_server_status.dart'; import 'package:neon/src/pages/login_flow.dart'; -import 'package:neon/src/pages/login_qrcode.dart'; +import 'package:neon/src/pages/login_qr_code.dart'; import 'package:neon/src/pages/nextcloud_app_settings.dart'; import 'package:neon/src/pages/route_not_found.dart'; import 'package:neon/src/pages/settings.dart'; @@ -36,12 +36,12 @@ class AppRouter extends GoRouter { initialLocation: const HomeRoute().location, errorPageBuilder: _buildErrorPage, redirect: (final context, final state) { - final loginQrcode = LoginQrcode.tryParse(state.uri.toString()); - if (loginQrcode != null) { + final loginQRcode = LoginQRcode.tryParse(state.uri.toString()); + if (loginQRcode != null) { return LoginCheckServerStatusRoute.withCredentials( - serverUrl: loginQrcode.serverURL, - loginName: loginQrcode.username, - password: loginQrcode.password, + serverUrl: loginQRcode.serverURL, + loginName: loginQRcode.username, + password: loginQRcode.password, ).location; } @@ -72,15 +72,15 @@ class AppRouter extends GoRouter { @immutable class AccountSettingsRoute extends GoRouteData { const AccountSettingsRoute({ - required this.accountid, + required this.accountID, }); - final String accountid; + final String accountID; @override Widget build(final BuildContext context, final GoRouterState state) { final bloc = NeonProvider.of(context); - final account = bloc.accounts.value.find(accountid); + final account = bloc.accounts.value.find(accountID); return AccountSettingsPage( bloc: bloc, @@ -108,8 +108,8 @@ class AccountSettingsRoute extends GoRouteData { TypedGoRoute<_AddAccountFlowRoute>( path: 'flow', ), - TypedGoRoute<_AddAccountQrcodeRoute>( - path: 'qrcode', + TypedGoRoute<_AddAccountQRcodeRoute>( + path: 'qr-code', ), TypedGoRoute<_AddAccountCheckServerStatusRoute>( path: 'check/server', @@ -120,7 +120,7 @@ class AccountSettingsRoute extends GoRouteData { ], ), TypedGoRoute( - path: 'account/:accountid', + path: 'account/:accountID', name: 'AccountSettings', ), ], @@ -147,8 +147,8 @@ class HomeRoute extends GoRouteData { TypedGoRoute( path: 'flow', ), - TypedGoRoute( - path: 'qrcode', + TypedGoRoute( + path: 'qr-code', ), TypedGoRoute( path: 'check/server', @@ -201,18 +201,18 @@ class LoginFlowRoute extends GoRouteData { } @immutable -class LoginQrcodeRoute extends GoRouteData { - const LoginQrcodeRoute(); +class LoginQRcodeRoute extends GoRouteData { + const LoginQRcodeRoute(); @override - Widget build(final BuildContext context, final GoRouterState state) => const LoginQrcodePage(); + Widget build(final BuildContext context, final GoRouterState state) => const LoginQRcodePage(); @override FutureOr redirect(final BuildContext context, final GoRouterState state) { final hasAccounts = NeonProvider.of(context).hasAccounts; if (state.fullPath == location && hasAccounts) { - return const _AddAccountQrcodeRoute().location; + return const _AddAccountQRcodeRoute().location; } return null; @@ -325,8 +325,8 @@ class _AddAccountFlowRoute extends LoginFlowRoute { } @immutable -class _AddAccountQrcodeRoute extends LoginQrcodeRoute { - const _AddAccountQrcodeRoute(); +class _AddAccountQRcodeRoute extends LoginQRcodeRoute { + const _AddAccountQRcodeRoute(); } @immutable diff --git a/packages/neon/neon/lib/src/router.g.dart b/packages/neon/neon/lib/src/router.g.dart index 04304861..71b8c324 100644 --- a/packages/neon/neon/lib/src/router.g.dart +++ b/packages/neon/neon/lib/src/router.g.dart @@ -36,8 +36,8 @@ RouteBase get $homeRoute => GoRouteData.$route( factory: $_AddAccountFlowRouteExtension._fromState, ), GoRouteData.$route( - path: 'qrcode', - factory: $_AddAccountQrcodeRouteExtension._fromState, + path: 'qr-code', + factory: $_AddAccountQRcodeRouteExtension._fromState, ), GoRouteData.$route( path: 'check/server', @@ -50,7 +50,7 @@ RouteBase get $homeRoute => GoRouteData.$route( ], ), GoRouteData.$route( - path: 'account/:accountid', + path: 'account/:accountID', name: 'AccountSettings', factory: $AccountSettingsRouteExtension._fromState, ), @@ -163,11 +163,11 @@ extension $_AddAccountFlowRouteExtension on _AddAccountFlowRoute { void replace(BuildContext context) => context.replace(location); } -extension $_AddAccountQrcodeRouteExtension on _AddAccountQrcodeRoute { - static _AddAccountQrcodeRoute _fromState(GoRouterState state) => const _AddAccountQrcodeRoute(); +extension $_AddAccountQRcodeRouteExtension on _AddAccountQRcodeRoute { + static _AddAccountQRcodeRoute _fromState(GoRouterState state) => const _AddAccountQRcodeRoute(); String get location => GoRouteData.$location( - '/settings/account/add/qrcode', + '/settings/account/add/qr-code', ); void go(BuildContext context) => context.go(location); @@ -227,11 +227,11 @@ extension $_AddAccountCheckAccountRouteExtension on _AddAccountCheckAccountRoute extension $AccountSettingsRouteExtension on AccountSettingsRoute { static AccountSettingsRoute _fromState(GoRouterState state) => AccountSettingsRoute( - accountid: state.pathParameters['accountid']!, + accountID: state.pathParameters['accountID']!, ); String get location => GoRouteData.$location( - '/settings/account/${Uri.encodeComponent(accountid)}', + '/settings/account/${Uri.encodeComponent(accountID)}', ); void go(BuildContext context) => context.go(location); @@ -266,8 +266,8 @@ RouteBase get $loginRoute => GoRouteData.$route( factory: $LoginFlowRouteExtension._fromState, ), GoRouteData.$route( - path: 'qrcode', - factory: $LoginQrcodeRouteExtension._fromState, + path: 'qr-code', + factory: $LoginQRcodeRouteExtension._fromState, ), GoRouteData.$route( path: 'check/server', @@ -317,11 +317,11 @@ extension $LoginFlowRouteExtension on LoginFlowRoute { void replace(BuildContext context) => context.replace(location); } -extension $LoginQrcodeRouteExtension on LoginQrcodeRoute { - static LoginQrcodeRoute _fromState(GoRouterState state) => const LoginQrcodeRoute(); +extension $LoginQRcodeRouteExtension on LoginQRcodeRoute { + static LoginQRcodeRoute _fromState(GoRouterState state) => const LoginQRcodeRoute(); String get location => GoRouteData.$location( - '/login/qrcode', + '/login/qr-code', ); void go(BuildContext context) => context.go(location); diff --git a/packages/neon/neon/lib/src/theme/colors.dart b/packages/neon/neon/lib/src/theme/colors.dart index c926ea00..da931746 100644 --- a/packages/neon/neon/lib/src/theme/colors.dart +++ b/packages/neon/neon/lib/src/theme/colors.dart @@ -31,12 +31,12 @@ abstract final class NcColors { /// Color of a starred item. static const Color starredColor = Colors.yellow; - /// Color used to emphasise declining actions. + /// Color used to emphasize declining actions. /// /// Usually used in conjunction with [NcColors.accept]. static const Color decline = Colors.red; - /// Color used to emphasise accepting actions. + /// Color used to emphasize accepting actions. /// /// Usually used in conjunction with [NcColors.decline]. static const Color accept = Colors.green; diff --git a/packages/neon/neon/lib/src/utils/exceptions.dart b/packages/neon/neon/lib/src/utils/exceptions.dart index cf39f41c..394627e4 100644 --- a/packages/neon/neon/lib/src/utils/exceptions.dart +++ b/packages/neon/neon/lib/src/utils/exceptions.dart @@ -8,4 +8,4 @@ class MissingPermissionException implements Exception { class UnableToOpenFileException implements Exception {} -class InvalidQrcodeException implements Exception {} +class InvalidQRcodeException implements Exception {} diff --git a/packages/neon/neon/lib/src/utils/global_options.dart b/packages/neon/neon/lib/src/utils/global_options.dart index 69285960..ef06626f 100644 --- a/packages/neon/neon/lib/src/utils/global_options.dart +++ b/packages/neon/neon/lib/src/utils/global_options.dart @@ -174,14 +174,14 @@ class GlobalOptions extends OptionsCollection { late final systemTrayEnabled = ToggleOption( storage: storage, - key: GlobalOptionKeys.systemtrayEnabled, + key: GlobalOptionKeys.systemTrayEnabled, label: (final context) => AppLocalizations.of(context).globalOptionsSystemTrayEnabled, defaultValue: false, ); late final systemTrayHideToTrayWhenMinimized = ToggleOption.depend( storage: storage, - key: GlobalOptionKeys.systemtrayHideToTrayWhenMinimized, + key: GlobalOptionKeys.systemTrayHideToTrayWhenMinimized, label: (final context) => AppLocalizations.of(context).globalOptionsSystemTrayHideToTrayWhenMinimized, defaultValue: true, enabled: systemTrayEnabled, @@ -228,8 +228,8 @@ enum GlobalOptionKeys implements Storable { pushNotificationsDistributor._('push-notifications-distributor'), startupMinimized._('startup-minimized'), startupMinimizeInsteadOfExit._('startup-minimize-instead-of-exit'), - systemtrayEnabled._('systemtray-enabled'), - systemtrayHideToTrayWhenMinimized._('systemtray-hide-to-tray-when-minimized'), + systemTrayEnabled._('system-tray-enabled'), + systemTrayHideToTrayWhenMinimized._('system-tray-hide-to-tray-when-minimized'), rememberLastUsedAccount._('remember-last-used-account'), initialAccount._('initial-account'), navigationMode._('navigation-mode'); diff --git a/packages/neon/neon/lib/src/utils/relative_time.dart b/packages/neon/neon/lib/src/utils/relative_time.dart index 293667de..bb229769 100644 --- a/packages/neon/neon/lib/src/utils/relative_time.dart +++ b/packages/neon/neon/lib/src/utils/relative_time.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; -/// Extension for formating the differnce between two [DateTime]s. +/// Extension for formatting the difference between two [DateTime]s. @internal extension RelativeTimeFormat on DateTime { /// Format the relative time between this and [to]. diff --git a/packages/neon/neon/lib/src/widgets/drawer_destination.dart b/packages/neon/neon/lib/src/widgets/drawer_destination.dart index ddc1e98b..f7b72457 100644 --- a/packages/neon/neon/lib/src/widgets/drawer_destination.dart +++ b/packages/neon/neon/lib/src/widgets/drawer_destination.dart @@ -50,7 +50,7 @@ extension NavigationRailDestinationExtension on NavigationRailDestination { return icon; } - final notificationIdicator = Builder( + final notificationIndicator = Builder( builder: (final context) { final style = TextStyle( color: Theme.of(context).colorScheme.primary, @@ -68,7 +68,7 @@ extension NavigationRailDestinationExtension on NavigationRailDestination { alignment: Alignment.bottomRight, children: [ icon, - notificationIdicator, + notificationIndicator, ], ); }, @@ -95,7 +95,7 @@ extension NavigationDrawerDestinationExtension on NavigationDrawerDestination { return label; } - final notificationIdicator = Padding( + final notificationIndicator = Padding( padding: const EdgeInsets.only(left: 12, right: 24), child: Builder( builder: (final context) { @@ -118,7 +118,7 @@ extension NavigationDrawerDestinationExtension on NavigationDrawerDestination { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ label, - notificationIdicator, + notificationIndicator, ], ), ); diff --git a/packages/neon/neon/lib/src/widgets/exception.dart b/packages/neon/neon/lib/src/widgets/exception.dart index 1656594a..ff1cd0aa 100644 --- a/packages/neon/neon/lib/src/widgets/exception.dart +++ b/packages/neon/neon/lib/src/widgets/exception.dart @@ -130,9 +130,9 @@ class NeonException extends StatelessWidget { ); } - if (exception is InvalidQrcodeException) { + if (exception is InvalidQRcodeException) { return ExceptionDetails( - text: AppLocalizations.of(context).errorInvalidQrcode, + text: AppLocalizations.of(context).errorInvalidQRcode, ); } diff --git a/packages/neon/neon/test/account_test.dart b/packages/neon/neon/test/account_test.dart index 9c415e22..339db79e 100644 --- a/packages/neon/neon/test/account_test.dart +++ b/packages/neon/neon/test/account_test.dart @@ -2,20 +2,20 @@ import 'package:neon/src/models/account.dart'; import 'package:test/test.dart'; void main() { - group('LoginQrcode', () { + group('LoginQRcode', () { const qrCodePath = '/user:JohnDoe&password:super_secret&server:example.com'; const qrCode = 'nc://login$qrCodePath'; - const invalidUrl = '::Not valid LoginQrcode::'; - final credentials = LoginQrcode( + const invalidUrl = '::Not valid LoginQRcode::'; + final credentials = LoginQRcode( serverURL: Uri.parse('example.com'), username: 'JohnDoe', password: 'super_secret', ); test('parse', () { - expect(LoginQrcode.tryParse(qrCode), equals(credentials)); - expect(LoginQrcode.tryParse(qrCodePath), equals(credentials)); - expect(LoginQrcode.tryParse(invalidUrl), null); + expect(LoginQRcode.tryParse(qrCode), equals(credentials)); + expect(LoginQRcode.tryParse(qrCodePath), equals(credentials)); + expect(LoginQRcode.tryParse(invalidUrl), null); }); test('equality', () { diff --git a/packages/neon/neon/test/result_test.dart b/packages/neon/neon/test/result_test.dart index 55aee147..89f0c4e0 100644 --- a/packages/neon/neon/test/result_test.dart +++ b/packages/neon/neon/test/result_test.dart @@ -25,7 +25,7 @@ void main() { expect(a, equals(b), reason: 'ignore cached state in equality'); expect(a.hashCode, equals(a.hashCode), reason: 'identical'); - expect(a.hashCode, isNot(equals(b.hashCode)), reason: 'hashcode should respect the cached state'); + expect(a.hashCode, isNot(equals(b.hashCode)), reason: 'hashCode should respect the cached state'); }); test('Transform to loading', () { diff --git a/packages/neon/neon_news/lib/blocs/news.dart b/packages/neon/neon_news/lib/blocs/news.dart index c82c6c02..224fec85 100644 --- a/packages/neon/neon_news/lib/blocs/news.dart +++ b/packages/neon/neon_news/lib/blocs/news.dart @@ -105,7 +105,6 @@ class NewsBloc extends InteractiveBloc implements NewsBlocEvents, NewsBlocStates feeds, () async => account.client.news.listFeeds(), (final response) { - // This is a bit ugly, but IDGAF right now if (response.newestItemId != null) { _newestItemId = response.newestItemId!; } diff --git a/packages/nextcloud/lib/src/api/notifications.openapi.json b/packages/nextcloud/lib/src/api/notifications.openapi.json index 6e87975a..e348b6df 100644 --- a/packages/nextcloud/lib/src/api/notifications.openapi.json +++ b/packages/nextcloud/lib/src/api/notifications.openapi.json @@ -729,7 +729,7 @@ ], "responses": { "200": { - "description": "Existing nsotification IDs returned", + "description": "Existing notification IDs returned", "content": { "application/json": { "schema": { diff --git a/packages/nextcloud/lib/src/webdav/file.dart b/packages/nextcloud/lib/src/webdav/file.dart index a796270c..cc163baf 100644 --- a/packages/nextcloud/lib/src/webdav/file.dart +++ b/packages/nextcloud/lib/src/webdav/file.dart @@ -80,7 +80,7 @@ class WebDavFile { /// Returns the decoded name of the file / folder without the whole path late final String name = () { - // normalised path (remove trailing slash) + // normalized path (remove trailing slash) final end = path.endsWith('/') ? path.length - 1 : path.length; final segments = Uri.parse(path, 0, end).pathSegments; diff --git a/tool/update-cspell-dictionaries.sh b/tool/update-cspell-dictionaries.sh new file mode 100755 index 00000000..18dd4e78 --- /dev/null +++ b/tool/update-cspell-dictionaries.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -euxo pipefail +cd "$(dirname "$0")/.." + +for file in .cspell/*; do + rm "$file" + cspell lint --quiet --unique --words-only . | tr '[:upper:]' '[:lower:]' | sort -f | uniq > "$file" || true +done