Skip to content

Commit

Permalink
Merge branch 'main' into feature/widgetbook-preview-to-gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Matej-Hlatky committed May 28, 2024
2 parents d7a4d12 + a19268b commit ea3c399
Show file tree
Hide file tree
Showing 33 changed files with 939 additions and 493 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2024-05-07 - v1.0.0(25)

- Android: Fix auto verify Deep links - no need to manually enable domain association

## 2024-05-07 - v1.0.0(24)

- Fix issue that no document was open when QR code was scanned
Expand Down
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ Flutter app for Android and iOS.

### Onboarding

User onboarding - starts with one [`OnboardingScreen`](lib/ui/screens/onboarding_screen.dart):
User onboarding - starts with one [`Onboarding`](lib/ui/onboarding.dart):

1. [`OnboardingAcceptTermsOfServiceScreen`](lib/ui/screens/onboarding_accept_terms_of_service_screen.dart)
2. [`OnboardingSelectSigningCertificateScreen`](lib/ui/screens/onboarding_select_signing_certificate_screen.dart)
3. [`OnboardingFinishedScreen`](lib/ui/screens/onboarding_finished_screen.dart)
1. Accept Privacy Policy using [`OnboardingAcceptDocumentScreen`](lib/ui/screens/onboarding_accept_document_screen.dart)
2. Accept Terms of Service using same [`OnboardingAcceptDocumentScreen`](lib/ui/screens/onboarding_accept_document_screen.dart)
3. optionally [`OnboardingSelectSigningCertificateScreen`](lib/ui/screens/onboarding_select_signing_certificate_screen.dart)
4. Presenting finish - [`OnboardingFinishedScreen`](lib/ui/screens/onboarding_finished_screen.dart)

### Sign single document

Expand All @@ -48,6 +49,13 @@ Signing of single (PDF, TXT, image, eForms XML, ...) document using
6. [`PresentSignedDocumentScreen`](lib/ui/screens/present_signed_document_screen.dart) - here, the
(success / error) result is presented and signed document is saved into "Downloads".

### Remote document signing

Similar to [Sign single document](#sign-single-document), but starts with:

- [`StartRemoteDocumentSigningScreen`](lib/ui/screens/start_remote_document_signing_screen.dart)
- [`QRCodeScannerScreen`](lib/ui/screens/qr_code_scanner_screen.dart)

## Scripts

FVM init and Pub get:
Expand Down
9 changes: 9 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="https" />
<data android:host="autogram.slovensko.digital" />
<data android:pathPrefix="/api/" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="avm" />
<data android:host="autogram.slovensko.digital" />
<data android:pathPrefix="/api/" />
Expand Down
46 changes: 18 additions & 28 deletions lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,61 +1,51 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'app_navigator_observer.dart';
import 'app_service.dart';
import 'bloc/app_bloc.dart';
import 'di.dart';
import 'l10n/app_localizations.dart';
import 'strings_context.dart';
import 'ui/app_theme.dart';
import 'ui/screens/main_screen.dart';

/// Main Material app.
///
/// Consumes [AppService] to read its [AppService.incomingUri].
/// Gets [AppService] to read its [AppService.incomingUri].
///
/// Home is [MainScreen].
class App extends StatelessWidget {
const App({super.key});

@override
Widget build(BuildContext context) {
// TODO Move "Consumer<AppService>" and additional code into MainScreen
final home = Consumer<AppService>(
builder: (context, appService, _) {
return ValueListenableBuilder(
valueListenable: appService.incomingUri,
builder: (context, incomingUri, _) {
// TODO Convert to stateful and show modal dialog with question whether to start over with different input file
final appService = getIt.get<AppService>();

return MainScreen(
incomingUri: incomingUri,
);
},
final home = ValueListenableBuilder(
valueListenable: appService.incomingUri,
builder: (context, incomingUri, _) {
// TODO Convert to stateful and show modal dialog with question whether to start over with different input file

return MainScreen(
incomingUri: incomingUri,
);
},
);

return MaterialApp(
final app = MaterialApp(
title: context.strings.appTitle,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
debugShowCheckedModeBanner: false,
navigatorObservers: [AppNavigatorObserver()],
theme: appTheme(context, brightness: Brightness.light),
home: home,
);

// Normally, setting home Widget would be sufficient
// However need to assign arguments to RouteSettings so it can be read
// back when navigated from OnboardingScreen
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/') {
return MaterialPageRoute(
// ignore: prefer_const_constructors, prefer_const_literals_to_create_immutables
settings: RouteSettings(name: '/', arguments: {}),
builder: (_) => home,
);
}

return null;
},
return BlocProvider<AppBloc>(
create: (_) => AppBloc(),
child: app,
);
}
}
16 changes: 16 additions & 0 deletions lib/bloc/app_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter_bloc/flutter_bloc.dart' show Bloc;

import '../app.dart';
import 'app_event.dart';

export 'app_event.dart';

/// Bloc for the [App], where event type is used also as state, so it is
/// used as simple event bus.
class AppBloc extends Bloc<AppEvent, AppEvent?> {
AppBloc() : super(null) {
on<AppEvent>((event, emit) {
emit(event);
});
}
}
19 changes: 19 additions & 0 deletions lib/bloc/app_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter/foundation.dart';

import 'app_bloc.dart';

/// Event for the [AppBloc].
@immutable
sealed class AppEvent {
const AppEvent();

@override
String toString() {
return "$runtimeType()";
}
}

/// "Request open file" event.
class RequestOpenFileEvent extends AppEvent {
const RequestOpenFileEvent() : super();
}
31 changes: 0 additions & 31 deletions lib/certificate_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,4 @@ extension CertificateExtensions on Certificate {

return x509CertificateData.tbsCertificate!;
}

/// Gets the usage label text.
String? get usageLabel {
// Issuer SN: SVK eID ACA2 / SVK eID PCA / SVK eID SCA
// Slot: QES / ES
// keyUsage: KeyUsage.NON_REPUDIATION / KeyUsage.KEY_ENCIPHERMENT / KeyUsage.DATA_ENCIPHERMENT
// extKeyUsage: null / ExtendedKeyUsage.CLIENT_AUTH / null

final cert = tbsCertificate;
final keyUsage = cert.extensions?.keyUsage;

if (isQualified) {
return "Kvalifikovaný certifikát pre elektronický podpis";
}

if (keyUsage == null) {
return null;
}

if (keyUsage.contains(KeyUsage.DIGITAL_SIGNATURE)) {
return "Certifikát pre elektronický podpis";
}

if (keyUsage.contains(KeyUsage.DATA_ENCIPHERMENT)) {
return "Šifrovací certifikát";
}

return keyUsage
.map((e) => e.name.toLowerCase().replaceAll('_', ' '))
.join(", ");
}
}
21 changes: 16 additions & 5 deletions lib/data/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import 'signature_type.dart';

/// Interface for general app settings.
abstract interface class ISettings {
/// Accepted Terms of Service (ToS) document version value.
ValueNotifier<int?> get acceptedTermsOfServiceVersion;
/// Accepted Privacy Policy document version value.
ValueNotifier<String?> get acceptedPrivacyPolicyVersion;

/// Accepted Terms of Service document version value.
ValueNotifier<String?> get acceptedTermsOfServiceVersion;

/// The signing container value.
ValueNotifier<PdfSigningOption> get signingPdfContainer;
Expand All @@ -27,11 +30,19 @@ abstract interface class ISettings {
///
/// Uses **Shared Preferences** - need to call [Settings.initialize] before use.
// TODO Make only "Settings" type and private _SettingsImpl that will be returned by factory fun
// TODO Also register it using Injectable
class Settings with NotifiedPreferences implements ISettings {
@override
late final ValueNotifier<int?> acceptedTermsOfServiceVersion =
createSetting<int?>(
key: 'tos.version.accepted',
late final ValueNotifier<String?> acceptedPrivacyPolicyVersion =
createSetting<String?>(
key: 'doc.pp.version.accepted',
initialValue: null,
);

@override
late final ValueNotifier<String?> acceptedTermsOfServiceVersion =
createSetting<String?>(
key: 'doc.tos.version.accepted',
initialValue: null,
);

Expand Down
69 changes: 36 additions & 33 deletions lib/di.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ea3c399

Please sign in to comment.