mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-06 15:15:50 -06:00
Resetting filter doesn't reset sorting, some bugfixes and UI updates
This commit is contained in:
@@ -49,7 +49,6 @@ void main() async {
|
|||||||
|
|
||||||
await getIt<ConnectivityCubit>().initialize();
|
await getIt<ConnectivityCubit>().initialize();
|
||||||
await getIt<ApplicationSettingsCubit>().initialize();
|
await getIt<ApplicationSettingsCubit>().initialize();
|
||||||
await getIt<AuthenticationCubit>().initialize();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mocked classes
|
// Mocked classes
|
||||||
@@ -97,7 +96,6 @@ void main() async {
|
|||||||
|
|
||||||
await getIt<ConnectivityCubit>().initialize();
|
await getIt<ConnectivityCubit>().initialize();
|
||||||
await getIt<ApplicationSettingsCubit>().initialize();
|
await getIt<ApplicationSettingsCubit>().initialize();
|
||||||
await getIt<AuthenticationCubit>().initialize();
|
|
||||||
});
|
});
|
||||||
// Mocked classes
|
// Mocked classes
|
||||||
|
|
||||||
@@ -149,7 +147,6 @@ void main() async {
|
|||||||
));
|
));
|
||||||
await getIt<ConnectivityCubit>().initialize();
|
await getIt<ConnectivityCubit>().initialize();
|
||||||
await getIt<ApplicationSettingsCubit>().initialize();
|
await getIt<ApplicationSettingsCubit>().initialize();
|
||||||
await getIt<AuthenticationCubit>().initialize();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.binding.waitUntilFirstFrameRasterized;
|
await t.binding.waitUntilFirstFrameRasterized;
|
||||||
@@ -199,7 +196,6 @@ void main() async {
|
|||||||
|
|
||||||
await getIt<ConnectivityCubit>().initialize();
|
await getIt<ConnectivityCubit>().initialize();
|
||||||
await getIt<ApplicationSettingsCubit>().initialize();
|
await getIt<ApplicationSettingsCubit>().initialize();
|
||||||
await getIt<AuthenticationCubit>().initialize();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.binding.waitUntilFirstFrameRasterized;
|
await t.binding.waitUntilFirstFrameRasterized;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
import 'package:paperless_mobile/di_initializer.dart';
|
import 'package:paperless_mobile/di_initializer.dart';
|
||||||
|
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n.dart';
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
import 'package:paperless_mobile/main.dart';
|
import 'package:paperless_mobile/main.dart';
|
||||||
|
|
||||||
@@ -35,5 +36,5 @@ Future<void> initAndLaunchTestApp(
|
|||||||
Future<void> Function() initializationCallback,
|
Future<void> Function() initializationCallback,
|
||||||
) async {
|
) async {
|
||||||
await initializationCallback();
|
await initializationCallback();
|
||||||
runApp(const PaperlessMobileEntrypoint());
|
//runApp(const PaperlessMobileEntrypoint(authenticationCubit: ),));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/models/saved_view_model.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
@@ -8,11 +7,10 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
|
|||||||
|
|
||||||
SavedViewRepositoryImpl(this._api);
|
SavedViewRepositoryImpl(this._api);
|
||||||
|
|
||||||
final BehaviorSubject<Map<int, SavedView>> _subject =
|
final BehaviorSubject<Map<int, SavedView>?> _subject = BehaviorSubject();
|
||||||
BehaviorSubject.seeded({});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<Map<int, SavedView>> get savedViews =>
|
Stream<Map<int, SavedView>?> get savedViews =>
|
||||||
_subject.stream.asBroadcastStream();
|
_subject.stream.asBroadcastStream();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -23,7 +21,7 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
|
|||||||
@override
|
@override
|
||||||
Future<SavedView> create(SavedView view) async {
|
Future<SavedView> create(SavedView view) async {
|
||||||
final created = await _api.save(view);
|
final created = await _api.save(view);
|
||||||
final updatedState = {..._subject.value}
|
final updatedState = {..._subject.valueOrNull ?? {}}
|
||||||
..putIfAbsent(created.id!, () => created);
|
..putIfAbsent(created.id!, () => created);
|
||||||
_subject.add(updatedState);
|
_subject.add(updatedState);
|
||||||
return created;
|
return created;
|
||||||
@@ -32,7 +30,7 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
|
|||||||
@override
|
@override
|
||||||
Future<int> delete(SavedView view) async {
|
Future<int> delete(SavedView view) async {
|
||||||
await _api.delete(view);
|
await _api.delete(view);
|
||||||
final updatedState = {..._subject.value}..remove(view.id);
|
final updatedState = {..._subject.valueOrNull ?? {}}..remove(view.id);
|
||||||
_subject.add(updatedState);
|
_subject.add(updatedState);
|
||||||
return view.id!;
|
return view.id!;
|
||||||
}
|
}
|
||||||
@@ -40,7 +38,7 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
|
|||||||
@override
|
@override
|
||||||
Future<SavedView?> find(int id) async {
|
Future<SavedView?> find(int id) async {
|
||||||
final found = await _api.find(id);
|
final found = await _api.find(id);
|
||||||
final updatedState = {..._subject.value}
|
final updatedState = {..._subject.valueOrNull ?? {}}
|
||||||
..update(id, (_) => found, ifAbsent: () => found);
|
..update(id, (_) => found, ifAbsent: () => found);
|
||||||
_subject.add(updatedState);
|
_subject.add(updatedState);
|
||||||
return found;
|
return found;
|
||||||
@@ -50,7 +48,7 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
|
|||||||
Future<Iterable<SavedView>> findAll([Iterable<int>? ids]) async {
|
Future<Iterable<SavedView>> findAll([Iterable<int>? ids]) async {
|
||||||
final found = await _api.findAll(ids);
|
final found = await _api.findAll(ids);
|
||||||
final updatedState = {
|
final updatedState = {
|
||||||
..._subject.value,
|
..._subject.valueOrNull ?? {},
|
||||||
...{for (final view in found) view.id!: view},
|
...{for (final view in found) view.id!: view},
|
||||||
};
|
};
|
||||||
_subject.add(updatedState);
|
_subject.add(updatedState);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
|
||||||
abstract class SavedViewRepository {
|
abstract class SavedViewRepository {
|
||||||
Stream<Map<int, SavedView>> get savedViews;
|
Stream<Map<int, SavedView>?> get savedViews;
|
||||||
|
|
||||||
Future<SavedView> create(SavedView view);
|
Future<SavedView> create(SavedView view);
|
||||||
Future<SavedView?> find(int id);
|
Future<SavedView?> find(int id);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:paperless_mobile/di_initializer.config.dart';
|
import 'package:paperless_mobile/di_initializer.config.dart';
|
||||||
import 'package:paperless_mobile/di_modules.dart';
|
import 'package:paperless_mobile/di_modules.dart';
|
||||||
import 'package:paperless_mobile/di_paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
@@ -21,7 +20,7 @@ void configureDependencies(String environment) =>
|
|||||||
///
|
///
|
||||||
/// Registers new security context, which will be used by the HttpClient, see [RegisterModule].
|
/// Registers new security context, which will be used by the HttpClient, see [RegisterModule].
|
||||||
///
|
///
|
||||||
void registerSecurityContext(ClientCertificate? cert) {
|
Future<void> registerSecurityContext(ClientCertificate? cert) async {
|
||||||
var context = SecurityContext();
|
var context = SecurityContext();
|
||||||
if (cert != null) {
|
if (cert != null) {
|
||||||
context = context
|
context = context
|
||||||
@@ -29,6 +28,6 @@ void registerSecurityContext(ClientCertificate? cert) {
|
|||||||
..useCertificateChainBytes(cert.bytes, password: cert.passphrase)
|
..useCertificateChainBytes(cert.bytes, password: cert.passphrase)
|
||||||
..setTrustedCertificatesBytes(cert.bytes, password: cert.passphrase);
|
..setTrustedCertificatesBytes(cert.bytes, password: cert.passphrase);
|
||||||
}
|
}
|
||||||
getIt.unregister<SecurityContext>();
|
await getIt.unregister<SecurityContext>();
|
||||||
getIt.registerSingleton<SecurityContext>(context);
|
getIt.registerSingleton<SecurityContext>(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,11 +107,11 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
color: Colors
|
color: Colors
|
||||||
.black, //TODO: check if there is a way to dynamically determine color...
|
.black, //TODO: check if there is a way to dynamically determine color...
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.pop(
|
onPressed: () => Navigator.of(context).pop(
|
||||||
context,
|
BlocProvider.of<DocumentDetailsCubit>(context)
|
||||||
BlocProvider.of<DocumentDetailsCubit>(context)
|
.state
|
||||||
.state
|
.document,
|
||||||
.document),
|
),
|
||||||
),
|
),
|
||||||
floating: true,
|
floating: true,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
@@ -237,13 +237,13 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
return ListView(
|
return ListView(
|
||||||
children: [
|
children: [
|
||||||
_DetailsItem.text(DateFormat().format(document.modified),
|
_DetailsItem.text(DateFormat().format(document.modified),
|
||||||
label: S.of(context).documentModifiedPropertyLabel,
|
label: S.of(context).documentModifiedPropertyLabel,
|
||||||
context: context),
|
context: context)
|
||||||
_separator(),
|
.paddedOnly(bottom: 16),
|
||||||
_DetailsItem.text(DateFormat().format(document.added),
|
_DetailsItem.text(DateFormat().format(document.added),
|
||||||
label: S.of(context).documentAddedPropertyLabel,
|
label: S.of(context).documentAddedPropertyLabel,
|
||||||
context: context),
|
context: context)
|
||||||
_separator(),
|
.paddedSymmetrically(vertical: 16),
|
||||||
_DetailsItem(
|
_DetailsItem(
|
||||||
label: S.of(context).documentArchiveSerialNumberPropertyLongLabel,
|
label: S.of(context).documentArchiveSerialNumberPropertyLongLabel,
|
||||||
content: document.archiveSerialNumber != null
|
content: document.archiveSerialNumber != null
|
||||||
@@ -255,30 +255,26 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
onPressed:
|
onPressed:
|
||||||
widget.allowEdit ? () => _assignAsn(document) : null,
|
widget.allowEdit ? () => _assignAsn(document) : null,
|
||||||
),
|
),
|
||||||
),
|
).paddedSymmetrically(vertical: 16),
|
||||||
_separator(),
|
|
||||||
_DetailsItem.text(
|
_DetailsItem.text(
|
||||||
meta.mediaFilename,
|
meta.mediaFilename,
|
||||||
context: context,
|
context: context,
|
||||||
label: S.of(context).documentMetaDataMediaFilenamePropertyLabel,
|
label: S.of(context).documentMetaDataMediaFilenamePropertyLabel,
|
||||||
),
|
).paddedSymmetrically(vertical: 16),
|
||||||
_separator(),
|
|
||||||
_DetailsItem.text(
|
_DetailsItem.text(
|
||||||
meta.originalChecksum,
|
meta.originalChecksum,
|
||||||
context: context,
|
context: context,
|
||||||
label: S.of(context).documentMetaDataChecksumLabel,
|
label: S.of(context).documentMetaDataChecksumLabel,
|
||||||
),
|
).paddedSymmetrically(vertical: 16),
|
||||||
_separator(),
|
|
||||||
_DetailsItem.text(formatBytes(meta.originalSize, 2),
|
_DetailsItem.text(formatBytes(meta.originalSize, 2),
|
||||||
label: S.of(context).documentMetaDataOriginalFileSizeLabel,
|
label: S.of(context).documentMetaDataOriginalFileSizeLabel,
|
||||||
context: context),
|
context: context)
|
||||||
_separator(),
|
.paddedSymmetrically(vertical: 16),
|
||||||
_DetailsItem.text(
|
_DetailsItem.text(
|
||||||
meta.originalMimeType,
|
meta.originalMimeType,
|
||||||
label: S.of(context).documentMetaDataOriginalMimeTypeLabel,
|
label: S.of(context).documentMetaDataOriginalMimeTypeLabel,
|
||||||
context: context,
|
context: context,
|
||||||
),
|
).paddedSymmetrically(vertical: 16),
|
||||||
_separator(),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -295,16 +291,13 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
|
|
||||||
Widget _buildDocumentContentView(DocumentModel document, String? match) {
|
Widget _buildDocumentContentView(DocumentModel document, String? match) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: _DetailsItem(
|
child: HighlightedText(
|
||||||
content: HighlightedText(
|
text: document.content ?? "",
|
||||||
text: document.content ?? "",
|
highlights: match == null ? [] : match.split(" "),
|
||||||
highlights: match == null ? [] : match.split(" "),
|
style: Theme.of(context).textTheme.bodyText2,
|
||||||
style: Theme.of(context).textTheme.bodyText2,
|
caseSensitive: false,
|
||||||
caseSensitive: false,
|
|
||||||
),
|
|
||||||
label: S.of(context).documentDetailsPageTabContentLabel,
|
|
||||||
),
|
),
|
||||||
);
|
).paddedOnly(top: 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDocumentOverview(DocumentModel document, String? match) {
|
Widget _buildDocumentOverview(DocumentModel document, String? match) {
|
||||||
@@ -314,60 +307,61 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
content: HighlightedText(
|
content: HighlightedText(
|
||||||
text: document.title,
|
text: document.title,
|
||||||
highlights: match?.split(" ") ?? <String>[],
|
highlights: match?.split(" ") ?? <String>[],
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
label: S.of(context).documentTitlePropertyLabel,
|
label: S.of(context).documentTitlePropertyLabel,
|
||||||
),
|
).paddedOnly(bottom: 16),
|
||||||
_separator(),
|
|
||||||
_DetailsItem.text(
|
_DetailsItem.text(
|
||||||
DateFormat.yMMMd().format(document.created),
|
DateFormat.yMMMd().format(document.created),
|
||||||
context: context,
|
context: context,
|
||||||
label: S.of(context).documentCreatedPropertyLabel,
|
label: S.of(context).documentCreatedPropertyLabel,
|
||||||
),
|
).paddedSymmetrically(vertical: 16),
|
||||||
_separator(),
|
Visibility(
|
||||||
_DetailsItem(
|
visible: document.documentType != null,
|
||||||
content: DocumentTypeWidget(
|
child: _DetailsItem(
|
||||||
isClickable: widget.isLabelClickable,
|
content: DocumentTypeWidget(
|
||||||
documentTypeId: document.documentType,
|
textStyle: Theme.of(context).textTheme.bodyLarge,
|
||||||
afterSelected: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
label: S.of(context).documentDocumentTypePropertyLabel,
|
|
||||||
),
|
|
||||||
_separator(),
|
|
||||||
_DetailsItem(
|
|
||||||
label: S.of(context).documentCorrespondentPropertyLabel,
|
|
||||||
content: CorrespondentWidget(
|
|
||||||
isClickable: widget.isLabelClickable,
|
|
||||||
correspondentId: document.correspondent,
|
|
||||||
afterSelected: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_separator(),
|
|
||||||
_DetailsItem(
|
|
||||||
label: S.of(context).documentStoragePathPropertyLabel,
|
|
||||||
content: StoragePathWidget(
|
|
||||||
isClickable: widget.isLabelClickable,
|
|
||||||
pathId: document.storagePath,
|
|
||||||
afterSelected: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_separator(),
|
|
||||||
_DetailsItem(
|
|
||||||
label: S.of(context).documentTagsPropertyLabel,
|
|
||||||
content: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: TagsWidget(
|
|
||||||
isClickable: widget.isLabelClickable,
|
isClickable: widget.isLabelClickable,
|
||||||
tagIds: document.tags,
|
documentTypeId: document.documentType,
|
||||||
isSelectedPredicate: (_) => false,
|
|
||||||
onTagSelected: (int tagId) {},
|
|
||||||
),
|
),
|
||||||
),
|
label: S.of(context).documentDocumentTypePropertyLabel,
|
||||||
|
).paddedSymmetrically(vertical: 16),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: document.correspondent != null,
|
||||||
|
child: _DetailsItem(
|
||||||
|
label: S.of(context).documentCorrespondentPropertyLabel,
|
||||||
|
content: CorrespondentWidget(
|
||||||
|
textStyle: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
isClickable: widget.isLabelClickable,
|
||||||
|
correspondentId: document.correspondent,
|
||||||
|
),
|
||||||
|
).paddedSymmetrically(vertical: 16),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: document.storagePath != null,
|
||||||
|
child: _DetailsItem(
|
||||||
|
label: S.of(context).documentStoragePathPropertyLabel,
|
||||||
|
content: StoragePathWidget(
|
||||||
|
isClickable: widget.isLabelClickable,
|
||||||
|
pathId: document.storagePath,
|
||||||
|
),
|
||||||
|
).paddedSymmetrically(vertical: 16),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: document.tags.isNotEmpty,
|
||||||
|
child: _DetailsItem(
|
||||||
|
label: S.of(context).documentTagsPropertyLabel,
|
||||||
|
content: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: TagsWidget(
|
||||||
|
isClickable: widget.isLabelClickable,
|
||||||
|
tagIds: document.tags,
|
||||||
|
isSelectedPredicate: (_) => false,
|
||||||
|
onTagSelected: (int tagId) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).paddedSymmetrically(vertical: 16),
|
||||||
),
|
),
|
||||||
// _separator(),
|
// _separator(),
|
||||||
// FutureBuilder<List<SimilarDocumentModel>>(
|
// FutureBuilder<List<SimilarDocumentModel>>(
|
||||||
@@ -396,10 +390,6 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _separator() {
|
|
||||||
return const SizedBox(height: 32.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Downloads file to temporary directory, from which it can then be shared.
|
/// Downloads file to temporary directory, from which it can then be shared.
|
||||||
///
|
///
|
||||||
@@ -477,10 +467,7 @@ class _DetailsItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.caption,
|
||||||
.textTheme
|
|
||||||
.headline5
|
|
||||||
?.copyWith(fontWeight: FontWeight.bold),
|
|
||||||
),
|
),
|
||||||
content,
|
content,
|
||||||
],
|
],
|
||||||
@@ -492,7 +479,7 @@ class _DetailsItem extends StatelessWidget {
|
|||||||
String text, {
|
String text, {
|
||||||
required this.label,
|
required this.label,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
}) : content = Text(text, style: Theme.of(context).textTheme.bodyText2);
|
}) : content = Text(text, style: Theme.of(context).textTheme.bodyLarge);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColoredTabBar extends Container implements PreferredSizeWidget {
|
class ColoredTabBar extends Container implements PreferredSizeWidget {
|
||||||
|
|||||||
@@ -88,6 +88,13 @@ class DocumentsCubit extends Cubit<DocumentsState> {
|
|||||||
emit(DocumentsState(filter: filter, value: [result], isLoaded: true));
|
emit(DocumentsState(filter: filter, value: [result], isLoaded: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> resetFilter() async {
|
||||||
|
final filter = DocumentFilter.initial.copyWith(
|
||||||
|
sortField: state.filter.sortField,
|
||||||
|
sortOrder: state.filter.sortOrder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convenience method which allows to directly use [DocumentFilter.copyWith] on the current filter.
|
/// Convenience method which allows to directly use [DocumentFilter.copyWith] on the current filter.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -151,22 +151,28 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
switch (settings.preferredViewType) {
|
switch (settings.preferredViewType) {
|
||||||
case ViewType.list:
|
case ViewType.list:
|
||||||
child = DocumentListView(
|
child = DocumentListView(
|
||||||
onTap: _openDetails,
|
|
||||||
state: state,
|
state: state,
|
||||||
|
onTap: _openDetails,
|
||||||
onSelected: _onSelected,
|
onSelected: _onSelected,
|
||||||
pagingController: _pagingController,
|
pagingController: _pagingController,
|
||||||
hasInternetConnection: isConnected,
|
hasInternetConnection: isConnected,
|
||||||
onTagSelected: _addTagToFilter,
|
onTagSelected: _addTagToFilter,
|
||||||
|
onCorrespondentSelected: _addCorrespondentToFilter,
|
||||||
|
onDocumentTypeSelected: _addDocumentTypeToFilter,
|
||||||
|
onStoragePathSelected: _addStoragePathToFilter,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ViewType.grid:
|
case ViewType.grid:
|
||||||
child = DocumentGridView(
|
child = DocumentGridView(
|
||||||
onTap: _openDetails,
|
|
||||||
state: state,
|
state: state,
|
||||||
|
onTap: _openDetails,
|
||||||
onSelected: _onSelected,
|
onSelected: _onSelected,
|
||||||
pagingController: _pagingController,
|
pagingController: _pagingController,
|
||||||
hasInternetConnection: isConnected,
|
hasInternetConnection: isConnected,
|
||||||
onTagSelected: _addTagToFilter,
|
onTagSelected: _addTagToFilter,
|
||||||
|
onCorrespondentSelected: _addCorrespondentToFilter,
|
||||||
|
onDocumentTypeSelected: _addDocumentTypeToFilter,
|
||||||
|
onStoragePathSelected: _addStoragePathToFilter,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -176,7 +182,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
child: DocumentsEmptyState(
|
child: DocumentsEmptyState(
|
||||||
state: state,
|
state: state,
|
||||||
onReset: () {
|
onReset: () {
|
||||||
_documentsCubit.updateFilter();
|
_documentsCubit.resetFilter();
|
||||||
_savedViewCubit.resetSelection();
|
_savedViewCubit.resetSelection();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -195,7 +201,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
try {
|
try {
|
||||||
if (state.selectedSavedViewId == null) {
|
if (state.selectedSavedViewId == null) {
|
||||||
_documentsCubit.updateFilter();
|
_documentsCubit.resetFilter();
|
||||||
} else {
|
} else {
|
||||||
final newFilter = state
|
final newFilter = state
|
||||||
.value[state.selectedSavedViewId]
|
.value[state.selectedSavedViewId]
|
||||||
@@ -280,6 +286,63 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _addCorrespondentToFilter(int? correspondentId) {
|
||||||
|
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
||||||
|
try {
|
||||||
|
if (cubit.state.filter.correspondent.id == correspondentId) {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) =>
|
||||||
|
filter.copyWith(correspondent: const CorrespondentQuery.unset()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) => filter.copyWith(
|
||||||
|
correspondent: CorrespondentQuery.fromId(correspondentId)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
|
showErrorMessage(context, error, stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addDocumentTypeToFilter(int? documentTypeId) {
|
||||||
|
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
||||||
|
try {
|
||||||
|
if (cubit.state.filter.documentType.id == documentTypeId) {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) =>
|
||||||
|
filter.copyWith(documentType: const DocumentTypeQuery.unset()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) => filter.copyWith(
|
||||||
|
documentType: DocumentTypeQuery.fromId(documentTypeId)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
|
showErrorMessage(context, error, stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addStoragePathToFilter(int? pathId) {
|
||||||
|
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
||||||
|
try {
|
||||||
|
if (cubit.state.filter.correspondent.id == pathId) {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) =>
|
||||||
|
filter.copyWith(storagePath: const StoragePathQuery.unset()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cubit.updateCurrentFilter(
|
||||||
|
(filter) =>
|
||||||
|
filter.copyWith(storagePath: StoragePathQuery.fromId(pathId)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
|
showErrorMessage(context, error, stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _loadNewPage(int pageKey) async {
|
Future<void> _loadNewPage(int pageKey) async {
|
||||||
final pageCount = _documentsCubit.state
|
final pageCount = _documentsCubit.state
|
||||||
.inferPageCount(pageSize: _documentsCubit.state.filter.pageSize);
|
.inferPageCount(pageSize: _documentsCubit.state.filter.pageSize);
|
||||||
@@ -299,9 +362,10 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
|
|
||||||
Future<void> _onRefresh() async {
|
Future<void> _onRefresh() async {
|
||||||
try {
|
try {
|
||||||
await _documentsCubit.updateCurrentFilter(
|
_documentsCubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(page: 1),
|
(filter) => filter.copyWith(page: 1),
|
||||||
);
|
);
|
||||||
|
_savedViewCubit.reload();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ class DocumentGridView extends StatelessWidget {
|
|||||||
final DocumentsState state;
|
final DocumentsState state;
|
||||||
final bool hasInternetConnection;
|
final bool hasInternetConnection;
|
||||||
final void Function(int tagId) onTagSelected;
|
final void Function(int tagId) onTagSelected;
|
||||||
|
final void Function(int correspondentId) onCorrespondentSelected;
|
||||||
|
final void Function(int correspondentId) onDocumentTypeSelected;
|
||||||
|
final void Function(int? id)? onStoragePathSelected;
|
||||||
|
|
||||||
const DocumentGridView({
|
const DocumentGridView({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -21,6 +24,9 @@ class DocumentGridView extends StatelessWidget {
|
|||||||
required this.onSelected,
|
required this.onSelected,
|
||||||
required this.hasInternetConnection,
|
required this.hasInternetConnection,
|
||||||
required this.onTagSelected,
|
required this.onTagSelected,
|
||||||
|
required this.onCorrespondentSelected,
|
||||||
|
required this.onDocumentTypeSelected,
|
||||||
|
this.onStoragePathSelected,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/provider/label_repositories_provider.dart';
|
import 'package:paperless_mobile/core/repository/provider/label_repositories_provider.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/documents_list_loading_widget.dart';
|
import 'package:paperless_mobile/core/widgets/documents_list_loading_widget.dart';
|
||||||
@@ -16,7 +15,10 @@ class DocumentListView extends StatelessWidget {
|
|||||||
final DocumentsState state;
|
final DocumentsState state;
|
||||||
final bool hasInternetConnection;
|
final bool hasInternetConnection;
|
||||||
final bool isLabelClickable;
|
final bool isLabelClickable;
|
||||||
final void Function(int tagId) onTagSelected;
|
final void Function(int id)? onTagSelected;
|
||||||
|
final void Function(int? id)? onCorrespondentSelected;
|
||||||
|
final void Function(int? id)? onDocumentTypeSelected;
|
||||||
|
final void Function(int? id)? onStoragePathSelected;
|
||||||
|
|
||||||
const DocumentListView({
|
const DocumentListView({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -26,7 +28,10 @@ class DocumentListView extends StatelessWidget {
|
|||||||
required this.onSelected,
|
required this.onSelected,
|
||||||
required this.hasInternetConnection,
|
required this.hasInternetConnection,
|
||||||
this.isLabelClickable = true,
|
this.isLabelClickable = true,
|
||||||
required this.onTagSelected,
|
this.onTagSelected,
|
||||||
|
this.onCorrespondentSelected,
|
||||||
|
this.onDocumentTypeSelected,
|
||||||
|
this.onStoragePathSelected,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -52,6 +57,9 @@ class DocumentListView extends StatelessWidget {
|
|||||||
: false;
|
: false;
|
||||||
},
|
},
|
||||||
onTagSelected: onTagSelected,
|
onTagSelected: onTagSelected,
|
||||||
|
onCorrespondentSelected: onCorrespondentSelected,
|
||||||
|
onDocumentTypeSelected: onDocumentTypeSelected,
|
||||||
|
onStoragePathSelected: onStoragePathSelected,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ class DocumentListItem extends StatelessWidget {
|
|||||||
final bool isLabelClickable;
|
final bool isLabelClickable;
|
||||||
final bool Function(int tagId) isTagSelectedPredicate;
|
final bool Function(int tagId) isTagSelectedPredicate;
|
||||||
|
|
||||||
final void Function(int tagId) onTagSelected;
|
final void Function(int tagId)? onTagSelected;
|
||||||
|
final void Function(int? correspondentId)? onCorrespondentSelected;
|
||||||
|
final void Function(int? documentTypeId)? onDocumentTypeSelected;
|
||||||
|
final void Function(int? id)? onStoragePathSelected;
|
||||||
|
|
||||||
const DocumentListItem({
|
const DocumentListItem({
|
||||||
Key? key,
|
Key? key,
|
||||||
@@ -25,7 +28,10 @@ class DocumentListItem extends StatelessWidget {
|
|||||||
required this.isAtLeastOneSelected,
|
required this.isAtLeastOneSelected,
|
||||||
this.isLabelClickable = true,
|
this.isLabelClickable = true,
|
||||||
required this.isTagSelectedPredicate,
|
required this.isTagSelectedPredicate,
|
||||||
required this.onTagSelected,
|
this.onTagSelected,
|
||||||
|
this.onCorrespondentSelected,
|
||||||
|
this.onDocumentTypeSelected,
|
||||||
|
this.onStoragePathSelected,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -48,6 +54,7 @@ class DocumentListItem extends StatelessWidget {
|
|||||||
child: CorrespondentWidget(
|
child: CorrespondentWidget(
|
||||||
isClickable: isLabelClickable,
|
isClickable: isLabelClickable,
|
||||||
correspondentId: document.correspondent,
|
correspondentId: document.correspondent,
|
||||||
|
onSelected: onCorrespondentSelected,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -68,7 +75,7 @@ class DocumentListItem extends StatelessWidget {
|
|||||||
tagIds: document.tags,
|
tagIds: document.tags,
|
||||||
isMultiLine: false,
|
isMultiLine: false,
|
||||||
isSelectedPredicate: isTagSelectedPredicate,
|
isSelectedPredicate: isTagSelectedPredicate,
|
||||||
onTagSelected: onTagSelected,
|
onTagSelected: (id) => onTagSelected?.call(id),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -123,7 +123,12 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
|
|
||||||
void _resetFilter() async {
|
void _resetFilter() async {
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
Navigator.pop(context, DocumentFilter.initial);
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
DocumentFilter.initial.copyWith(
|
||||||
|
sortField: widget.initialFilter.sortField,
|
||||||
|
sortOrder: widget.initialFilter.sortOrder,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDocumentTypeFormField() {
|
Widget _buildDocumentTypeFormField() {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class _LabelFormState<T extends Label> extends State<LabelForm<T>> {
|
|||||||
),
|
),
|
||||||
FormBuilderCheckbox(
|
FormBuilderCheckbox(
|
||||||
name: Label.isInsensitiveKey,
|
name: Label.isInsensitiveKey,
|
||||||
initialValue: widget.initialValue?.isInsensitive,
|
initialValue: widget.initialValue?.isInsensitive ?? true,
|
||||||
title: Text(S.of(context).labelIsInsensivitePropertyLabel),
|
title: Text(S.of(context).labelIsInsensivitePropertyLabel),
|
||||||
),
|
),
|
||||||
...widget.additionalFields,
|
...widget.additionalFields,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
|||||||
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/offline_banner.dart';
|
|
||||||
import 'package:paperless_mobile/di_initializer.dart';
|
import 'package:paperless_mobile/di_initializer.dart';
|
||||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
||||||
|
|||||||
@@ -9,16 +9,18 @@ import 'package:paperless_mobile/util.dart';
|
|||||||
|
|
||||||
class CorrespondentWidget extends StatelessWidget {
|
class CorrespondentWidget extends StatelessWidget {
|
||||||
final int? correspondentId;
|
final int? correspondentId;
|
||||||
final void Function()? afterSelected;
|
final void Function(int? id)? onSelected;
|
||||||
final Color? textColor;
|
final Color? textColor;
|
||||||
final bool isClickable;
|
final bool isClickable;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
|
||||||
const CorrespondentWidget({
|
const CorrespondentWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.correspondentId,
|
required this.correspondentId,
|
||||||
this.afterSelected,
|
|
||||||
this.textColor,
|
this.textColor,
|
||||||
this.isClickable = true,
|
this.isClickable = true,
|
||||||
|
this.textStyle,
|
||||||
|
this.onSelected,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -30,14 +32,15 @@ class CorrespondentWidget extends StatelessWidget {
|
|||||||
BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => _addCorrespondentToFilter(context),
|
onTap: () => onSelected?.call(correspondentId!),
|
||||||
child: Text(
|
child: Text(
|
||||||
(state.getLabel(correspondentId)?.name) ?? "-",
|
(state.getLabel(correspondentId)?.name) ?? "-",
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: (textStyle ?? Theme.of(context).textTheme.bodyText2)
|
||||||
color: textColor ?? Theme.of(context).colorScheme.primary,
|
?.copyWith(
|
||||||
),
|
color: textColor ?? Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -45,24 +48,4 @@ class CorrespondentWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addCorrespondentToFilter(BuildContext context) {
|
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
|
||||||
try {
|
|
||||||
if (cubit.state.filter.correspondent.id == correspondentId) {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) =>
|
|
||||||
filter.copyWith(correspondent: const CorrespondentQuery.unset()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) => filter.copyWith(
|
|
||||||
correspondent: CorrespondentQuery.fromId(correspondentId)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
afterSelected?.call();
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
|
||||||
showErrorMessage(context, error, stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||||
import 'package:paperless_mobile/util.dart';
|
|
||||||
|
|
||||||
class DocumentTypeWidget extends StatelessWidget {
|
class DocumentTypeWidget extends StatelessWidget {
|
||||||
final int? documentTypeId;
|
final int? documentTypeId;
|
||||||
final void Function()? afterSelected;
|
|
||||||
final bool isClickable;
|
final bool isClickable;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
final void Function(int? id)? onSelected;
|
||||||
const DocumentTypeWidget({
|
const DocumentTypeWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.documentTypeId,
|
required this.documentTypeId,
|
||||||
this.afterSelected,
|
|
||||||
this.isClickable = true,
|
this.isClickable = true,
|
||||||
|
this.textStyle,
|
||||||
|
this.onSelected,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -27,16 +27,14 @@ class DocumentTypeWidget extends StatelessWidget {
|
|||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: !isClickable,
|
absorbing: !isClickable,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _addDocumentTypeToFilter(context),
|
onTap: () => onSelected?.call(documentTypeId),
|
||||||
child:
|
child:
|
||||||
BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Text(
|
return Text(
|
||||||
state.labels[documentTypeId]?.toString() ?? "-",
|
state.labels[documentTypeId]?.toString() ?? "-",
|
||||||
style: Theme.of(context)
|
style: (textStyle ?? Theme.of(context).textTheme.bodyText2)
|
||||||
.textTheme
|
?.copyWith(color: Theme.of(context).colorScheme.tertiary),
|
||||||
.bodyText2!
|
|
||||||
.copyWith(color: Theme.of(context).colorScheme.tertiary),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -44,24 +42,4 @@ class DocumentTypeWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addDocumentTypeToFilter(BuildContext context) {
|
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
|
||||||
try {
|
|
||||||
if (cubit.state.filter.documentType.id == documentTypeId) {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) =>
|
|
||||||
filter.copyWith(documentType: const DocumentTypeQuery.unset()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) => filter.copyWith(
|
|
||||||
documentType: DocumentTypeQuery.fromId(documentTypeId)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
afterSelected?.call();
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
|
||||||
showErrorMessage(context, error, stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,21 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||||
import 'package:paperless_mobile/util.dart';
|
|
||||||
|
|
||||||
class StoragePathWidget extends StatelessWidget {
|
class StoragePathWidget extends StatelessWidget {
|
||||||
final int? pathId;
|
final int? pathId;
|
||||||
final void Function()? afterSelected;
|
|
||||||
final Color? textColor;
|
final Color? textColor;
|
||||||
final bool isClickable;
|
final bool isClickable;
|
||||||
|
final void Function(int? id)? onSelected;
|
||||||
|
|
||||||
const StoragePathWidget({
|
const StoragePathWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.pathId,
|
this.pathId,
|
||||||
this.afterSelected,
|
|
||||||
this.textColor,
|
this.textColor,
|
||||||
this.isClickable = true,
|
this.isClickable = true,
|
||||||
|
this.onSelected,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -32,7 +30,7 @@ class StoragePathWidget extends StatelessWidget {
|
|||||||
child: BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
child: BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => _addStoragePathToFilter(context),
|
onTap: () => onSelected?.call(pathId),
|
||||||
child: Text(
|
child: Text(
|
||||||
state.getLabel(pathId)?.name ?? "-",
|
state.getLabel(pathId)?.name ?? "-",
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
@@ -47,24 +45,4 @@ class StoragePathWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addStoragePathToFilter(BuildContext context) {
|
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
|
||||||
try {
|
|
||||||
if (cubit.state.filter.correspondent.id == pathId) {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) =>
|
|
||||||
filter.copyWith(storagePath: const StoragePathQuery.unset()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
cubit.updateCurrentFilter(
|
|
||||||
(filter) =>
|
|
||||||
filter.copyWith(storagePath: StoragePathQuery.fromId(pathId)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
afterSelected?.call();
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
|
||||||
showErrorMessage(context, error, stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/store/local_vault.dart';
|
import 'package:paperless_mobile/core/store/local_vault.dart';
|
||||||
import 'package:paperless_mobile/di_initializer.dart';
|
import 'package:paperless_mobile/di_initializer.dart';
|
||||||
@@ -11,12 +10,9 @@ import 'package:paperless_mobile/features/login/model/user_credentials.model.dar
|
|||||||
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/application_settings_state.dart';
|
import 'package:paperless_mobile/features/settings/model/application_settings_state.dart';
|
||||||
|
|
||||||
@prod
|
|
||||||
@test
|
|
||||||
@singleton
|
|
||||||
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||||
final LocalAuthenticationService _localAuthService;
|
final LocalAuthenticationService _localAuthService;
|
||||||
final PaperlessAuthenticationApi _authApi;
|
PaperlessAuthenticationApi _authApi;
|
||||||
final LocalVault _localVault;
|
final LocalVault _localVault;
|
||||||
|
|
||||||
AuthenticationCubit(
|
AuthenticationCubit(
|
||||||
@@ -25,10 +21,6 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
this._authApi,
|
this._authApi,
|
||||||
) : super(AuthenticationState.initial);
|
) : super(AuthenticationState.initial);
|
||||||
|
|
||||||
Future<void> initialize() {
|
|
||||||
return restoreSessionState();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> login({
|
Future<void> login({
|
||||||
required UserCredentials credentials,
|
required UserCredentials credentials,
|
||||||
required String serverUrl,
|
required String serverUrl,
|
||||||
@@ -37,6 +29,8 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
assert(credentials.username != null && credentials.password != null);
|
assert(credentials.username != null && credentials.password != null);
|
||||||
try {
|
try {
|
||||||
registerSecurityContext(clientCertificate);
|
registerSecurityContext(clientCertificate);
|
||||||
|
//TODO: Workaround for new architecture, listen for security context changes in timeout_client, possibly persisted in hive.
|
||||||
|
_authApi = getIt<PaperlessAuthenticationApi>();
|
||||||
// Store information required to make requests
|
// Store information required to make requests
|
||||||
final currentAuth = AuthenticationInformation(
|
final currentAuth = AuthenticationInformation(
|
||||||
serverUrl: serverUrl,
|
serverUrl: serverUrl,
|
||||||
@@ -82,13 +76,16 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
}
|
}
|
||||||
if (storedAuth == null || !storedAuth.isValid) {
|
if (storedAuth == null || !storedAuth.isValid) {
|
||||||
return emit(
|
return emit(
|
||||||
AuthenticationState(isAuthenticated: false, wasLoginStored: false));
|
AuthenticationState(isAuthenticated: false, wasLoginStored: false),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
if (appSettings.isLocalAuthenticationEnabled) {
|
if (appSettings.isLocalAuthenticationEnabled) {
|
||||||
final localAuthSuccess = await _localAuthService
|
final localAuthSuccess = await _localAuthService
|
||||||
.authenticateLocalUser("Authenticate to log back in");
|
.authenticateLocalUser("Authenticate to log back in");
|
||||||
if (localAuthSuccess) {
|
if (localAuthSuccess) {
|
||||||
registerSecurityContext(storedAuth.clientCertificate);
|
await registerSecurityContext(storedAuth.clientCertificate);
|
||||||
|
//TODO: Workaround for new architecture, listen for security context changes in timeout_client, possibly persisted in hive.
|
||||||
|
_authApi = getIt<PaperlessAuthenticationApi>();
|
||||||
return emit(
|
return emit(
|
||||||
AuthenticationState(
|
AuthenticationState(
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
@@ -105,11 +102,13 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return emit(AuthenticationState(
|
await registerSecurityContext(storedAuth.clientCertificate);
|
||||||
|
final authState = AuthenticationState(
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
authentication: storedAuth,
|
authentication: storedAuth,
|
||||||
wasLoginStored: true,
|
wasLoginStored: true,
|
||||||
));
|
);
|
||||||
|
return emit(authState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||||
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_state.dart';
|
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_state.dart';
|
||||||
@@ -12,22 +11,26 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
|
|
||||||
SavedViewCubit(this._repository) : super(SavedViewState(value: {})) {
|
SavedViewCubit(this._repository) : super(SavedViewState(value: {})) {
|
||||||
_subscription = _repository.savedViews.listen(
|
_subscription = _repository.savedViews.listen(
|
||||||
(savedViews) => emit(state.copyWith(value: savedViews)),
|
(savedViews) {
|
||||||
|
if (savedViews == null) {
|
||||||
|
emit(state.copyWith(isLoaded: false));
|
||||||
|
} else {
|
||||||
|
emit(state.copyWith(value: savedViews, isLoaded: true));
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectView(SavedView? view) {
|
void selectView(SavedView? view) {
|
||||||
emit(SavedViewState(value: state.value, selectedSavedViewId: view?.id));
|
emit(state.copyWith(
|
||||||
|
selectedSavedViewId: view?.id,
|
||||||
|
overwriteSelectedSavedViewId: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SavedView> add(SavedView view) async {
|
Future<SavedView> add(SavedView view) async {
|
||||||
final savedView = await _repository.create(view);
|
final savedView = await _repository.create(view);
|
||||||
emit(
|
emit(state.copyWith(value: {...state.value, savedView.id!: savedView}));
|
||||||
SavedViewState(
|
|
||||||
value: {...state.value, savedView.id!: savedView},
|
|
||||||
selectedSavedViewId: state.selectedSavedViewId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return savedView;
|
return savedView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,11 +45,16 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
Future<void> initialize() async {
|
Future<void> initialize() async {
|
||||||
final views = await _repository.findAll();
|
final views = await _repository.findAll();
|
||||||
final values = {for (var element in views) element.id!: element};
|
final values = {for (var element in views) element.id!: element};
|
||||||
emit(SavedViewState(value: values));
|
emit(SavedViewState(value: values, isLoaded: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> reload() => initialize();
|
||||||
|
|
||||||
void resetSelection() {
|
void resetSelection() {
|
||||||
emit(SavedViewState(value: state.value));
|
emit(SavedViewState(
|
||||||
|
value: state.value,
|
||||||
|
isLoaded: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import 'package:equatable/equatable.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
|
||||||
class SavedViewState with EquatableMixin {
|
class SavedViewState with EquatableMixin {
|
||||||
|
final bool isLoaded;
|
||||||
final Map<int, SavedView> value;
|
final Map<int, SavedView> value;
|
||||||
final int? selectedSavedViewId;
|
final int? selectedSavedViewId;
|
||||||
|
|
||||||
SavedViewState({
|
SavedViewState({
|
||||||
required this.value,
|
required this.value,
|
||||||
|
this.isLoaded = false,
|
||||||
this.selectedSavedViewId,
|
this.selectedSavedViewId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,9 +22,11 @@ class SavedViewState with EquatableMixin {
|
|||||||
Map<int, SavedView>? value,
|
Map<int, SavedView>? value,
|
||||||
int? selectedSavedViewId,
|
int? selectedSavedViewId,
|
||||||
bool overwriteSelectedSavedViewId = false,
|
bool overwriteSelectedSavedViewId = false,
|
||||||
|
bool? isLoaded,
|
||||||
}) {
|
}) {
|
||||||
return SavedViewState(
|
return SavedViewState(
|
||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
|
isLoaded: isLoaded ?? this.isLoaded,
|
||||||
selectedSavedViewId: overwriteSelectedSavedViewId
|
selectedSavedViewId: overwriteSelectedSavedViewId
|
||||||
? selectedSavedViewId
|
? selectedSavedViewId
|
||||||
: this.selectedSavedViewId,
|
: this.selectedSavedViewId,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
@@ -8,6 +10,7 @@ import 'package:paperless_mobile/features/saved_view/cubit/saved_view_state.dart
|
|||||||
import 'package:paperless_mobile/features/saved_view/view/add_saved_view_page.dart';
|
import 'package:paperless_mobile/features/saved_view/view/add_saved_view_page.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n.dart';
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
import 'package:paperless_mobile/util.dart';
|
import 'package:paperless_mobile/util.dart';
|
||||||
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
class SavedViewSelectionWidget extends StatelessWidget {
|
class SavedViewSelectionWidget extends StatelessWidget {
|
||||||
final DocumentFilter currentFilter;
|
final DocumentFilter currentFilter;
|
||||||
@@ -29,6 +32,9 @@ class SavedViewSelectionWidget extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
BlocBuilder<SavedViewCubit, SavedViewState>(
|
BlocBuilder<SavedViewCubit, SavedViewState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
if (!state.isLoaded) {
|
||||||
|
return _buildLoadingWidget(context);
|
||||||
|
}
|
||||||
if (state.value.isEmpty) {
|
if (state.value.isEmpty) {
|
||||||
return Text(S.of(context).savedViewsEmptyStateText);
|
return Text(S.of(context).savedViewsEmptyStateText);
|
||||||
}
|
}
|
||||||
@@ -58,32 +64,61 @@ class SavedViewSelectionWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Row(
|
BlocBuilder<SavedViewCubit, SavedViewState>(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
builder: (context, state) {
|
||||||
children: [
|
return Row(
|
||||||
Text(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
S.of(context).savedViewsLabel,
|
children: [
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
Text(
|
||||||
),
|
S.of(context).savedViewsLabel,
|
||||||
BlocBuilder<DocumentsCubit, DocumentsState>(
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
buildWhen: (previous, current) =>
|
),
|
||||||
previous.filter != current.filter,
|
BlocBuilder<DocumentsCubit, DocumentsState>(
|
||||||
builder: (context, docState) {
|
buildWhen: (previous, current) =>
|
||||||
return TextButton.icon(
|
previous.filter != current.filter,
|
||||||
icon: const Icon(Icons.add),
|
builder: (context, docState) {
|
||||||
onPressed: enabled
|
return TextButton.icon(
|
||||||
? () => _onCreatePressed(context, docState.filter)
|
icon: const Icon(Icons.add),
|
||||||
: null,
|
onPressed: (enabled && state.isLoaded)
|
||||||
label: Text(S.of(context).savedViewCreateNewLabel),
|
? () => _onCreatePressed(context, docState.filter)
|
||||||
);
|
: null,
|
||||||
},
|
label: Text(S.of(context).savedViewCreateNewLabel),
|
||||||
),
|
);
|
||||||
],
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildLoadingWidget(BuildContext context) {
|
||||||
|
final r = Random(123456789);
|
||||||
|
return SizedBox(
|
||||||
|
height: height,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Shimmer.fromColors(
|
||||||
|
baseColor: Theme.of(context).brightness == Brightness.light
|
||||||
|
? Colors.grey[300]!
|
||||||
|
: Colors.grey[900]!,
|
||||||
|
highlightColor: Theme.of(context).brightness == Brightness.light
|
||||||
|
? Colors.grey[100]!
|
||||||
|
: Colors.grey[600]!,
|
||||||
|
child: ListView.separated(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: 10,
|
||||||
|
itemBuilder: (context, index) => FilterChip(
|
||||||
|
label: SizedBox(width: r.nextInt((index * 20) + 50).toDouble()),
|
||||||
|
onSelected: null),
|
||||||
|
separatorBuilder: (context, index) => SizedBox(width: 8.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _onCreatePressed(BuildContext context, DocumentFilter filter) async {
|
void _onCreatePressed(BuildContext context, DocumentFilter filter) async {
|
||||||
final newView = await Navigator.of(context).push<SavedView?>(
|
final newView = await Navigator.of(context).push<SavedView?>(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -34,6 +35,7 @@ import 'package:paperless_mobile/features/document_upload/cubit/document_upload_
|
|||||||
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
|
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
||||||
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/application_settings_state.dart';
|
import 'package:paperless_mobile/features/settings/model/application_settings_state.dart';
|
||||||
@@ -57,7 +59,13 @@ void main() async {
|
|||||||
// Load application settings and stored authentication data
|
// Load application settings and stored authentication data
|
||||||
await getIt<ConnectivityCubit>().initialize();
|
await getIt<ConnectivityCubit>().initialize();
|
||||||
await getIt<ApplicationSettingsCubit>().initialize();
|
await getIt<ApplicationSettingsCubit>().initialize();
|
||||||
await getIt<AuthenticationCubit>().initialize();
|
|
||||||
|
final authCubit = AuthenticationCubit(
|
||||||
|
getIt<LocalVault>(),
|
||||||
|
getIt<LocalAuthenticationService>(),
|
||||||
|
getIt<PaperlessAuthenticationApi>(),
|
||||||
|
);
|
||||||
|
await authCubit.restoreSessionState();
|
||||||
|
|
||||||
// Create repositories
|
// Create repositories
|
||||||
final LabelRepository<Tag> tagRepository =
|
final LabelRepository<Tag> tagRepository =
|
||||||
@@ -80,13 +88,17 @@ void main() async {
|
|||||||
RepositoryProvider.value(value: storagePathRepository),
|
RepositoryProvider.value(value: storagePathRepository),
|
||||||
RepositoryProvider.value(value: savedViewRepository),
|
RepositoryProvider.value(value: savedViewRepository),
|
||||||
],
|
],
|
||||||
child: const PaperlessMobileEntrypoint(),
|
child: PaperlessMobileEntrypoint(authenticationCubit: authCubit),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PaperlessMobileEntrypoint extends StatefulWidget {
|
class PaperlessMobileEntrypoint extends StatefulWidget {
|
||||||
const PaperlessMobileEntrypoint({Key? key}) : super(key: key);
|
final AuthenticationCubit authenticationCubit;
|
||||||
|
const PaperlessMobileEntrypoint({
|
||||||
|
Key? key,
|
||||||
|
required this.authenticationCubit,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PaperlessMobileEntrypoint> createState() =>
|
State<PaperlessMobileEntrypoint> createState() =>
|
||||||
@@ -165,8 +177,8 @@ class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
|
|||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
FormBuilderLocalizations.delegate,
|
FormBuilderLocalizations.delegate,
|
||||||
],
|
],
|
||||||
home: BlocProvider<AuthenticationCubit>.value(
|
home: BlocProvider.value(
|
||||||
value: getIt<AuthenticationCubit>(),
|
value: widget.authenticationCubit,
|
||||||
child: const AuthenticationWrapper(),
|
child: const AuthenticationWrapper(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -291,10 +303,10 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
|||||||
if (authentication.isAuthenticated) {
|
if (authentication.isAuthenticated) {
|
||||||
return const HomePage();
|
return const HomePage();
|
||||||
} else {
|
} else {
|
||||||
// if (authentication.wasLoginStored &&
|
if (authentication.wasLoginStored &&
|
||||||
// !(authentication.wasLocalAuthenticationSuccessful ?? false)) {
|
!(authentication.wasLocalAuthenticationSuccessful ?? false)) {
|
||||||
// return const BiometricAuthenticationPage();
|
return const BiometricAuthenticationPage();
|
||||||
// }
|
}
|
||||||
return const LoginPage();
|
return const LoginPage();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
|||||||
@override
|
@override
|
||||||
Future<StoragePath?> getStoragePath(int id) {
|
Future<StoragePath?> getStoragePath(int id) {
|
||||||
return getSingleResult(
|
return getSingleResult(
|
||||||
"/api/storage_paths/?page=1&page_size=100000",
|
"/api/storage_paths/$id/",
|
||||||
StoragePath.fromJson,
|
StoragePath.fromJson,
|
||||||
ErrorCode.storagePathLoadFailed,
|
ErrorCode.storagePathLoadFailed,
|
||||||
client: client,
|
client: client,
|
||||||
|
|||||||
Reference in New Issue
Block a user