mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-10 12:07:58 -06:00
fix: Add labels to each cubit using repositories and state properties, remove label cubits
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/providers/correspondent_bloc_provider.dart';
|
||||
|
||||
class CorrespondentWidget extends StatelessWidget {
|
||||
final int? correspondentId;
|
||||
final Correspondent? correspondent;
|
||||
final void Function(int? id)? onSelected;
|
||||
final Color? textColor;
|
||||
final bool isClickable;
|
||||
@@ -13,7 +10,7 @@ class CorrespondentWidget extends StatelessWidget {
|
||||
|
||||
const CorrespondentWidget({
|
||||
Key? key,
|
||||
required this.correspondentId,
|
||||
required this.correspondent,
|
||||
this.textColor,
|
||||
this.isClickable = true,
|
||||
this.textStyle,
|
||||
@@ -22,25 +19,18 @@ class CorrespondentWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CorrespondentBlocProvider(
|
||||
child: AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child:
|
||||
BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () => onSelected?.call(correspondentId!),
|
||||
child: Text(
|
||||
(state.getLabel(correspondentId)?.name) ?? "-",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: (textStyle ?? Theme.of(context).textTheme.bodyMedium)
|
||||
?.copyWith(
|
||||
color: textColor ?? Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
return AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child: GestureDetector(
|
||||
onTap: () => onSelected?.call(correspondent?.id),
|
||||
child: Text(
|
||||
correspondent?.name ?? "-",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style:
|
||||
(textStyle ?? Theme.of(context).textTheme.bodyMedium)?.copyWith(
|
||||
color: textColor ?? Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,68 +1,45 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit_mixin.dart';
|
||||
|
||||
part 'label_state.dart';
|
||||
part 'label_cubit.freezed.dart';
|
||||
|
||||
class LabelCubit<T extends Label> extends Cubit<LabelState<T>> {
|
||||
final LabelRepository<T> _repository;
|
||||
class LabelCubit extends Cubit<LabelState> with LabelCubitMixin<LabelState> {
|
||||
@override
|
||||
final LabelRepository labelRepository;
|
||||
|
||||
late StreamSubscription _subscription;
|
||||
|
||||
LabelCubit(LabelRepository<T> repository)
|
||||
: _repository = repository,
|
||||
super(LabelState(
|
||||
isLoaded: repository.isInitialized,
|
||||
labels: repository.current?.values ?? {},
|
||||
)) {
|
||||
_subscription = _repository.values.listen(
|
||||
(event) {
|
||||
if (event == null) {
|
||||
emit(LabelState());
|
||||
}
|
||||
emit(
|
||||
LabelState(isLoaded: event!.hasLoaded, labels: event.values ?? {}));
|
||||
LabelCubit(this.labelRepository) : super(const LabelState()) {
|
||||
labelRepository.subscribe(
|
||||
this,
|
||||
onChanged: (labels) {
|
||||
emit(state.copyWith(
|
||||
correspondents: labels.correspondents,
|
||||
documentTypes: labels.documentTypes,
|
||||
storagePaths: labels.storagePaths,
|
||||
tags: labels.tags,
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
///
|
||||
/// Adds [item] to the current state. A new state is automatically pushed
|
||||
/// due to the subscription to the repository, which updates the state on
|
||||
/// operation.
|
||||
///
|
||||
Future<T> add(T item) async {
|
||||
assert(item.id == null);
|
||||
final addedItem = await _repository.create(item);
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
Future<void> reload() {
|
||||
return _repository.findAll();
|
||||
}
|
||||
|
||||
Future<T> replace(T item) async {
|
||||
assert(item.id != null);
|
||||
final updatedItem = await _repository.update(item);
|
||||
return updatedItem;
|
||||
}
|
||||
|
||||
Future<void> remove(T item) async {
|
||||
assert(item.id != null);
|
||||
if (state.labels.containsKey(item.id)) {
|
||||
await _repository.delete(item);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
emit(LabelState(isLoaded: false, labels: {}));
|
||||
@override
|
||||
Future<void> close() {
|
||||
labelRepository.unsubscribe(this);
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
_subscription.cancel();
|
||||
return super.close();
|
||||
}
|
||||
Map<int, Correspondent> get correspondents => state.correspondents;
|
||||
|
||||
@override
|
||||
Map<int, DocumentType> get documentTypes => state.documentTypes;
|
||||
|
||||
@override
|
||||
Map<int, StoragePath> get storagePaths => state.storagePaths;
|
||||
|
||||
@override
|
||||
Map<int, Tag> get tags => state.tags;
|
||||
}
|
||||
|
||||
237
lib/features/labels/cubit/label_cubit.freezed.dart
Normal file
237
lib/features/labels/cubit/label_cubit.freezed.dart
Normal file
@@ -0,0 +1,237 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'label_cubit.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LabelState {
|
||||
Map<int, Correspondent> get correspondents =>
|
||||
throw _privateConstructorUsedError;
|
||||
Map<int, DocumentType> get documentTypes =>
|
||||
throw _privateConstructorUsedError;
|
||||
Map<int, Tag> get tags => throw _privateConstructorUsedError;
|
||||
Map<int, StoragePath> get storagePaths => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$LabelStateCopyWith<LabelState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LabelStateCopyWith<$Res> {
|
||||
factory $LabelStateCopyWith(
|
||||
LabelState value, $Res Function(LabelState) then) =
|
||||
_$LabelStateCopyWithImpl<$Res, LabelState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{Map<int, Correspondent> correspondents,
|
||||
Map<int, DocumentType> documentTypes,
|
||||
Map<int, Tag> tags,
|
||||
Map<int, StoragePath> storagePaths});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LabelStateCopyWithImpl<$Res, $Val extends LabelState>
|
||||
implements $LabelStateCopyWith<$Res> {
|
||||
_$LabelStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? correspondents = null,
|
||||
Object? documentTypes = null,
|
||||
Object? tags = null,
|
||||
Object? storagePaths = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
correspondents: null == correspondents
|
||||
? _value.correspondents
|
||||
: correspondents // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, Correspondent>,
|
||||
documentTypes: null == documentTypes
|
||||
? _value.documentTypes
|
||||
: documentTypes // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, DocumentType>,
|
||||
tags: null == tags
|
||||
? _value.tags
|
||||
: tags // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, Tag>,
|
||||
storagePaths: null == storagePaths
|
||||
? _value.storagePaths
|
||||
: storagePaths // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, StoragePath>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$_LabelStateCopyWith<$Res>
|
||||
implements $LabelStateCopyWith<$Res> {
|
||||
factory _$$_LabelStateCopyWith(
|
||||
_$_LabelState value, $Res Function(_$_LabelState) then) =
|
||||
__$$_LabelStateCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{Map<int, Correspondent> correspondents,
|
||||
Map<int, DocumentType> documentTypes,
|
||||
Map<int, Tag> tags,
|
||||
Map<int, StoragePath> storagePaths});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$_LabelStateCopyWithImpl<$Res>
|
||||
extends _$LabelStateCopyWithImpl<$Res, _$_LabelState>
|
||||
implements _$$_LabelStateCopyWith<$Res> {
|
||||
__$$_LabelStateCopyWithImpl(
|
||||
_$_LabelState _value, $Res Function(_$_LabelState) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? correspondents = null,
|
||||
Object? documentTypes = null,
|
||||
Object? tags = null,
|
||||
Object? storagePaths = null,
|
||||
}) {
|
||||
return _then(_$_LabelState(
|
||||
correspondents: null == correspondents
|
||||
? _value._correspondents
|
||||
: correspondents // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, Correspondent>,
|
||||
documentTypes: null == documentTypes
|
||||
? _value._documentTypes
|
||||
: documentTypes // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, DocumentType>,
|
||||
tags: null == tags
|
||||
? _value._tags
|
||||
: tags // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, Tag>,
|
||||
storagePaths: null == storagePaths
|
||||
? _value._storagePaths
|
||||
: storagePaths // ignore: cast_nullable_to_non_nullable
|
||||
as Map<int, StoragePath>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_LabelState implements _LabelState {
|
||||
const _$_LabelState(
|
||||
{final Map<int, Correspondent> correspondents = const {},
|
||||
final Map<int, DocumentType> documentTypes = const {},
|
||||
final Map<int, Tag> tags = const {},
|
||||
final Map<int, StoragePath> storagePaths = const {}})
|
||||
: _correspondents = correspondents,
|
||||
_documentTypes = documentTypes,
|
||||
_tags = tags,
|
||||
_storagePaths = storagePaths;
|
||||
|
||||
final Map<int, Correspondent> _correspondents;
|
||||
@override
|
||||
@JsonKey()
|
||||
Map<int, Correspondent> get correspondents {
|
||||
if (_correspondents is EqualUnmodifiableMapView) return _correspondents;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_correspondents);
|
||||
}
|
||||
|
||||
final Map<int, DocumentType> _documentTypes;
|
||||
@override
|
||||
@JsonKey()
|
||||
Map<int, DocumentType> get documentTypes {
|
||||
if (_documentTypes is EqualUnmodifiableMapView) return _documentTypes;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_documentTypes);
|
||||
}
|
||||
|
||||
final Map<int, Tag> _tags;
|
||||
@override
|
||||
@JsonKey()
|
||||
Map<int, Tag> get tags {
|
||||
if (_tags is EqualUnmodifiableMapView) return _tags;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_tags);
|
||||
}
|
||||
|
||||
final Map<int, StoragePath> _storagePaths;
|
||||
@override
|
||||
@JsonKey()
|
||||
Map<int, StoragePath> get storagePaths {
|
||||
if (_storagePaths is EqualUnmodifiableMapView) return _storagePaths;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_storagePaths);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LabelState(correspondents: $correspondents, documentTypes: $documentTypes, tags: $tags, storagePaths: $storagePaths)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$_LabelState &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._correspondents, _correspondents) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._documentTypes, _documentTypes) &&
|
||||
const DeepCollectionEquality().equals(other._tags, _tags) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._storagePaths, _storagePaths));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_correspondents),
|
||||
const DeepCollectionEquality().hash(_documentTypes),
|
||||
const DeepCollectionEquality().hash(_tags),
|
||||
const DeepCollectionEquality().hash(_storagePaths));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$_LabelStateCopyWith<_$_LabelState> get copyWith =>
|
||||
__$$_LabelStateCopyWithImpl<_$_LabelState>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _LabelState implements LabelState {
|
||||
const factory _LabelState(
|
||||
{final Map<int, Correspondent> correspondents,
|
||||
final Map<int, DocumentType> documentTypes,
|
||||
final Map<int, Tag> tags,
|
||||
final Map<int, StoragePath> storagePaths}) = _$_LabelState;
|
||||
|
||||
@override
|
||||
Map<int, Correspondent> get correspondents;
|
||||
@override
|
||||
Map<int, DocumentType> get documentTypes;
|
||||
@override
|
||||
Map<int, Tag> get tags;
|
||||
@override
|
||||
Map<int, StoragePath> get storagePaths;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_LabelStateCopyWith<_$_LabelState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
104
lib/features/labels/cubit/label_cubit_mixin.dart
Normal file
104
lib/features/labels/cubit/label_cubit_mixin.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
|
||||
mixin LabelCubitMixin<T> on BlocBase<T> {
|
||||
LabelRepository get labelRepository;
|
||||
|
||||
Map<int, Correspondent> get correspondents;
|
||||
Map<int, DocumentType> get documentTypes;
|
||||
Map<int, Tag> get tags;
|
||||
Map<int, StoragePath> get storagePaths;
|
||||
|
||||
Future<Correspondent> addCorrespondent(Correspondent item) async {
|
||||
assert(item.id == null);
|
||||
final addedItem = await labelRepository.createCorrespondent(item);
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
Future<void> reloadCorrespondents() {
|
||||
return labelRepository.findAllCorrespondents();
|
||||
}
|
||||
|
||||
Future<Correspondent> replaceCorrespondent(Correspondent item) async {
|
||||
assert(item.id != null);
|
||||
final updatedItem = await labelRepository.updateCorrespondent(item);
|
||||
return updatedItem;
|
||||
}
|
||||
|
||||
Future<void> removeCorrespondent(Correspondent item) async {
|
||||
assert(item.id != null);
|
||||
if (correspondents.containsKey(item.id)) {
|
||||
await labelRepository.deleteCorrespondent(item);
|
||||
}
|
||||
}
|
||||
|
||||
Future<DocumentType> addDocumentType(DocumentType item) async {
|
||||
assert(item.id == null);
|
||||
final addedItem = await labelRepository.createDocumentType(item);
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
Future<void> reloadDocumentTypes() {
|
||||
return labelRepository.findAllDocumentTypes();
|
||||
}
|
||||
|
||||
Future<DocumentType> replaceDocumentType(DocumentType item) async {
|
||||
assert(item.id != null);
|
||||
final updatedItem = await labelRepository.updateDocumentType(item);
|
||||
return updatedItem;
|
||||
}
|
||||
|
||||
Future<void> removeDocumentType(DocumentType item) async {
|
||||
assert(item.id != null);
|
||||
if (documentTypes.containsKey(item.id)) {
|
||||
await labelRepository.deleteDocumentType(item);
|
||||
}
|
||||
}
|
||||
|
||||
Future<StoragePath> addStoragePath(StoragePath item) async {
|
||||
assert(item.id == null);
|
||||
final addedItem = await labelRepository.createStoragePath(item);
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
Future<void> reloadStoragePaths() {
|
||||
return labelRepository.findAllStoragePaths();
|
||||
}
|
||||
|
||||
Future<StoragePath> replaceStoragePath(StoragePath item) async {
|
||||
assert(item.id != null);
|
||||
final updatedItem = await labelRepository.updateStoragePath(item);
|
||||
return updatedItem;
|
||||
}
|
||||
|
||||
Future<void> removeStoragePath(StoragePath item) async {
|
||||
assert(item.id != null);
|
||||
if (storagePaths.containsKey(item.id)) {
|
||||
await labelRepository.deleteStoragePath(item);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Tag> addTag(Tag item) async {
|
||||
assert(item.id == null);
|
||||
final addedItem = await labelRepository.createTag(item);
|
||||
return addedItem;
|
||||
}
|
||||
|
||||
Future<void> reloadTags() {
|
||||
return labelRepository.findAllTags();
|
||||
}
|
||||
|
||||
Future<Tag> replaceTag(Tag item) async {
|
||||
assert(item.id != null);
|
||||
final updatedItem = await labelRepository.updateTag(item);
|
||||
return updatedItem;
|
||||
}
|
||||
|
||||
Future<void> removeTag(Tag item) async {
|
||||
assert(item.id != null);
|
||||
if (tags.containsKey(item.id)) {
|
||||
await labelRepository.deleteTag(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,11 @@
|
||||
part of 'label_cubit.dart';
|
||||
|
||||
class LabelState<T extends Label> {
|
||||
LabelState.initial() : this(isLoaded: false, labels: {});
|
||||
final bool isLoaded;
|
||||
final Map<int, T> labels;
|
||||
|
||||
LabelState({
|
||||
this.isLoaded = false,
|
||||
this.labels = const {},
|
||||
});
|
||||
|
||||
T? getLabel(int? key) {
|
||||
if (isLoaded) {
|
||||
return labels[key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@freezed
|
||||
class LabelState with _$LabelState {
|
||||
const factory LabelState({
|
||||
@Default({}) Map<int, Correspondent> correspondents,
|
||||
@Default({}) Map<int, DocumentType> documentTypes,
|
||||
@Default({}) Map<int, Tag> tags,
|
||||
@Default({}) Map<int, StoragePath> storagePaths,
|
||||
}) = _LabelState;
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/correspondent_repository_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class CorrespondentBlocProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const CorrespondentBlocProvider({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<Correspondent>(
|
||||
context.read<LabelRepository<Correspondent>>(),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/document_type_repository_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class DocumentTypeBlocProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const DocumentTypeBlocProvider({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<DocumentType>(
|
||||
context.read<LabelRepository<DocumentType>>(),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/correspondent_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/document_type_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/storage_path_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/tag_repository_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class LabelsBlocProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const LabelsBlocProvider({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<LabelCubit<StoragePath>>(
|
||||
create: (context) => LabelCubit<StoragePath>(
|
||||
context.read<LabelRepository<StoragePath>>(),
|
||||
),
|
||||
),
|
||||
BlocProvider<LabelCubit<Correspondent>>(
|
||||
create: (context) => LabelCubit<Correspondent>(
|
||||
context.read<LabelRepository<Correspondent>>(),
|
||||
),
|
||||
),
|
||||
BlocProvider<LabelCubit<DocumentType>>(
|
||||
create: (context) => LabelCubit<DocumentType>(
|
||||
context.read<LabelRepository<DocumentType>>(),
|
||||
),
|
||||
),
|
||||
BlocProvider<LabelCubit<Tag>>(
|
||||
create: (context) => LabelCubit<Tag>(
|
||||
context.read<LabelRepository<Tag>>(),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/storage_path_repository_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class StoragePathBlocProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const StoragePathBlocProvider({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<StoragePath>(
|
||||
context.read<LabelRepository<StoragePath>>(),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/tag_repository_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class TagBlocProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const TagBlocProvider({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<Tag>(
|
||||
context.read<LabelRepository<Tag>>(),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/providers/document_type_bloc_provider.dart';
|
||||
|
||||
class DocumentTypeWidget extends StatelessWidget {
|
||||
final int? documentTypeId;
|
||||
final DocumentType? documentType;
|
||||
final bool isClickable;
|
||||
final TextStyle? textStyle;
|
||||
final void Function(int? id)? onSelected;
|
||||
const DocumentTypeWidget({
|
||||
Key? key,
|
||||
required this.documentTypeId,
|
||||
required this.documentType,
|
||||
this.isClickable = true,
|
||||
this.textStyle,
|
||||
this.onSelected,
|
||||
@@ -19,23 +16,16 @@ class DocumentTypeWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DocumentTypeBlocProvider(
|
||||
child: AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child: GestureDetector(
|
||||
onTap: () => onSelected?.call(documentTypeId),
|
||||
child:
|
||||
BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
||||
builder: (context, state) {
|
||||
return Text(
|
||||
state.labels[documentTypeId]?.toString() ?? "-",
|
||||
style: (textStyle ?? Theme.of(context).textTheme.bodyMedium)
|
||||
?.copyWith(color: Theme.of(context).colorScheme.tertiary),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
);
|
||||
},
|
||||
),
|
||||
return AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child: GestureDetector(
|
||||
onTap: () => onSelected?.call(documentType?.id),
|
||||
child: Text(
|
||||
documentType?.toString() ?? "-",
|
||||
style: (textStyle ?? Theme.of(context).textTheme.bodyMedium)
|
||||
?.copyWith(color: Theme.of(context).colorScheme.tertiary),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/providers/storage_path_bloc_provider.dart';
|
||||
|
||||
class StoragePathWidget extends StatelessWidget {
|
||||
final int? pathId;
|
||||
final StoragePath? storagePath;
|
||||
final Color? textColor;
|
||||
final bool isClickable;
|
||||
final void Function(int? id)? onSelected;
|
||||
|
||||
const StoragePathWidget({
|
||||
Key? key,
|
||||
this.pathId,
|
||||
this.storagePath,
|
||||
this.textColor,
|
||||
this.isClickable = true,
|
||||
this.onSelected,
|
||||
@@ -20,23 +17,17 @@ class StoragePathWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoragePathBlocProvider(
|
||||
child: AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child: BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () => onSelected?.call(pathId),
|
||||
child: Text(
|
||||
state.getLabel(pathId)?.name ?? "-",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: textColor ?? Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
return AbsorbPointer(
|
||||
absorbing: !isClickable,
|
||||
child: GestureDetector(
|
||||
onTap: () => onSelected?.call(storagePath?.id),
|
||||
child: Text(
|
||||
storagePath?.name ?? "-",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: textColor ?? Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/state/impl/tag_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_tag_page.dart';
|
||||
@@ -21,6 +20,8 @@ class TagFormField extends StatefulWidget {
|
||||
final bool excludeAllowed;
|
||||
final Map<int, Tag> selectableOptions;
|
||||
final Widget? suggestions;
|
||||
final String? labelText;
|
||||
final String? hintText;
|
||||
|
||||
const TagFormField({
|
||||
super.key,
|
||||
@@ -32,6 +33,8 @@ class TagFormField extends StatefulWidget {
|
||||
this.excludeAllowed = true,
|
||||
required this.selectableOptions,
|
||||
this.suggestions,
|
||||
this.labelText,
|
||||
this.hintText,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -94,8 +97,8 @@ class _TagFormFieldState extends State<TagFormField> {
|
||||
Icons.label_outline,
|
||||
),
|
||||
suffixIcon: _buildSuffixIcon(context, field),
|
||||
labelText: S.of(context)!.tags,
|
||||
hintText: S.of(context)!.filterTags,
|
||||
labelText: widget.labelText ?? S.of(context)!.tags,
|
||||
hintText: widget.hintText ?? S.of(context)!.filterTags,
|
||||
),
|
||||
controller: _textEditingController,
|
||||
),
|
||||
@@ -240,8 +243,8 @@ class _TagFormFieldState extends State<TagFormField> {
|
||||
void _onAddTag(BuildContext context, FormFieldState<TagsQuery> field) async {
|
||||
final Tag? tag = await Navigator.of(context).push<Tag>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: AddTagPage(initialValue: _textEditingController.text),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/providers/tag_bloc_provider.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tag_widget.dart';
|
||||
|
||||
class TagsWidget extends StatelessWidget {
|
||||
final Iterable<int> tagIds;
|
||||
final List<Tag> tags;
|
||||
final bool isMultiLine;
|
||||
final void Function(int tagId)? onTagSelected;
|
||||
final bool isClickable;
|
||||
@@ -15,7 +12,7 @@ class TagsWidget extends StatelessWidget {
|
||||
|
||||
const TagsWidget({
|
||||
Key? key,
|
||||
required this.tagIds,
|
||||
required this.tags,
|
||||
this.isMultiLine = true,
|
||||
this.isClickable = true,
|
||||
this.onTagSelected,
|
||||
@@ -25,36 +22,33 @@ class TagsWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TagBlocProvider(
|
||||
child: BlocBuilder<LabelCubit<Tag>, LabelState<Tag>>(
|
||||
builder: (context, state) {
|
||||
final children = tagIds
|
||||
.where((id) => state.labels.containsKey(id))
|
||||
.map(
|
||||
(id) => TagWidget(
|
||||
tag: state.getLabel(id)!,
|
||||
isClickable: isClickable,
|
||||
onSelected: () => onTagSelected?.call(id),
|
||||
showShortName: showShortNames,
|
||||
dense: dense,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
if (isMultiLine) {
|
||||
return Wrap(
|
||||
runAlignment: WrapAlignment.start,
|
||||
children: children,
|
||||
runSpacing: 4,
|
||||
spacing: 4,
|
||||
);
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(children: children),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
return Builder(
|
||||
builder: (context) {
|
||||
final children = tags
|
||||
.map(
|
||||
(tag) => TagWidget(
|
||||
tag: tag,
|
||||
isClickable: isClickable,
|
||||
onSelected: () => onTagSelected?.call(tag.id!),
|
||||
showShortName: showShortNames,
|
||||
dense: dense,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
if (isMultiLine) {
|
||||
return Wrap(
|
||||
runAlignment: WrapAlignment.start,
|
||||
children: children,
|
||||
runSpacing: 4,
|
||||
spacing: 4,
|
||||
);
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(children: children),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_he
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/widgets/material/search/colored_tab_bar.dart';
|
||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
|
||||
import 'package:paperless_mobile/features/document_search/view/sliver_search_bar.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_correspondent_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_document_type_page.dart';
|
||||
@@ -17,6 +16,7 @@ import 'package:paperless_mobile/features/edit_label/view/impl/edit_document_typ
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/edit_storage_path_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/edit_tag_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit_mixin.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_tab_view.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -141,12 +141,12 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
notificationPredicate: (notification) =>
|
||||
connectedState.isConnected,
|
||||
onRefresh: () => [
|
||||
context.read<LabelCubit<Correspondent>>(),
|
||||
context.read<LabelCubit<DocumentType>>(),
|
||||
context.read<LabelCubit<Tag>>(),
|
||||
context.read<LabelCubit<StoragePath>>(),
|
||||
context.read<LabelCubit>().reloadCorrespondents,
|
||||
context.read<LabelCubit>().reloadDocumentTypes,
|
||||
context.read<LabelCubit>().reloadTags,
|
||||
context.read<LabelCubit>().reloadStoragePaths,
|
||||
][_currentIndex]
|
||||
.reload(),
|
||||
.call(),
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
@@ -157,6 +157,10 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
SliverOverlapInjector(handle: searchBarHandle),
|
||||
SliverOverlapInjector(handle: tabBarHandle),
|
||||
LabelTabView<Correspondent>(
|
||||
labels: context
|
||||
.watch<LabelCubit>()
|
||||
.state
|
||||
.correspondents,
|
||||
filterBuilder: (label) => DocumentFilter(
|
||||
correspondent:
|
||||
IdQueryParameter.fromId(label.id),
|
||||
@@ -180,6 +184,10 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
SliverOverlapInjector(handle: searchBarHandle),
|
||||
SliverOverlapInjector(handle: tabBarHandle),
|
||||
LabelTabView<DocumentType>(
|
||||
labels: context
|
||||
.watch<LabelCubit>()
|
||||
.state
|
||||
.documentTypes,
|
||||
filterBuilder: (label) => DocumentFilter(
|
||||
documentType:
|
||||
IdQueryParameter.fromId(label.id),
|
||||
@@ -203,6 +211,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
SliverOverlapInjector(handle: searchBarHandle),
|
||||
SliverOverlapInjector(handle: tabBarHandle),
|
||||
LabelTabView<Tag>(
|
||||
labels:
|
||||
context.watch<LabelCubit>().state.tags,
|
||||
filterBuilder: (label) => DocumentFilter(
|
||||
tags: IdsTagsQuery.fromIds([label.id!]),
|
||||
pageSize: label.documentCount ?? 0,
|
||||
@@ -234,6 +244,10 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
SliverOverlapInjector(handle: searchBarHandle),
|
||||
SliverOverlapInjector(handle: tabBarHandle),
|
||||
LabelTabView<StoragePath>(
|
||||
labels: context
|
||||
.watch<LabelCubit>()
|
||||
.state
|
||||
.storagePaths,
|
||||
onEdit: _openEditStoragePathPage,
|
||||
filterBuilder: (label) => DocumentFilter(
|
||||
storagePath:
|
||||
@@ -267,8 +281,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: EditCorrespondentPage(correspondent: correspondent),
|
||||
),
|
||||
),
|
||||
@@ -279,8 +293,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: EditDocumentTypePage(documentType: docType),
|
||||
),
|
||||
),
|
||||
@@ -291,8 +305,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: EditTagPage(tag: tag),
|
||||
),
|
||||
),
|
||||
@@ -303,8 +317,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: EditStoragePathPage(
|
||||
storagePath: path,
|
||||
),
|
||||
@@ -317,8 +331,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: const AddCorrespondentPage(),
|
||||
),
|
||||
),
|
||||
@@ -329,8 +343,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: const AddDocumentTypePage(),
|
||||
),
|
||||
),
|
||||
@@ -341,8 +355,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: const AddTagPage(),
|
||||
),
|
||||
),
|
||||
@@ -353,8 +367,8 @@ class _LabelsPageState extends State<LabelsPage>
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||
builder: (_) => RepositoryProvider.value(
|
||||
value: context.read<LabelRepository>(),
|
||||
child: const AddStoragePathPage(),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -51,6 +51,7 @@ class LabelItem<T extends Label> extends StatelessWidget {
|
||||
filter,
|
||||
context.read(),
|
||||
context.read(),
|
||||
context.read(),
|
||||
),
|
||||
child: const LinkedDocumentsPage(),
|
||||
),
|
||||
|
||||
@@ -3,12 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
import 'package:paperless_mobile/core/translation/matching_algorithm_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/core/widgets/offline_widget.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_item.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
|
||||
class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
final Map<int, T> labels;
|
||||
final DocumentFilter Function(Label) filterBuilder;
|
||||
final void Function(T) onEdit;
|
||||
final void Function() onAddNew;
|
||||
@@ -32,69 +32,61 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
required this.emptyStateDescription,
|
||||
required this.onAddNew,
|
||||
required this.emptyStateActionButtonLabel,
|
||||
required this.labels,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<T>(
|
||||
context.read(),
|
||||
),
|
||||
child: BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
||||
builder: (context, connectivityState) {
|
||||
return BlocBuilder<LabelCubit<T>, LabelState<T>>(
|
||||
builder: (context, state) {
|
||||
if (!state.isLoaded && !connectivityState.isConnected) {
|
||||
return const OfflineWidget();
|
||||
}
|
||||
final labels = state.labels.values.toList()..sort();
|
||||
if (labels.isEmpty) {
|
||||
return SliverFillRemaining(
|
||||
child: Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
emptyStateDescription,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onAddNew,
|
||||
child: Text(emptyStateActionButtonLabel),
|
||||
),
|
||||
].padded(),
|
||||
),
|
||||
return BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
||||
builder: (context, connectivityState) {
|
||||
if (!connectivityState.isConnected) {
|
||||
return const OfflineWidget();
|
||||
}
|
||||
final sortedLabels = labels.values.toList()..sort();
|
||||
if (labels.isEmpty) {
|
||||
return SliverFillRemaining(
|
||||
child: Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
emptyStateDescription,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
final l = labels.elementAt(index);
|
||||
return LabelItem<T>(
|
||||
name: l.name,
|
||||
content: contentBuilder?.call(l) ??
|
||||
Text(
|
||||
translateMatchingAlgorithmName(
|
||||
context, l.matchingAlgorithm) +
|
||||
((l.match?.isNotEmpty ?? false)
|
||||
? ": ${l.match}"
|
||||
: ""),
|
||||
maxLines: 2,
|
||||
),
|
||||
onOpenEditPage: onEdit,
|
||||
filterBuilder: filterBuilder,
|
||||
leading: leadingBuilder?.call(l),
|
||||
label: l,
|
||||
);
|
||||
},
|
||||
childCount: labels.length,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onAddNew,
|
||||
child: Text(emptyStateActionButtonLabel),
|
||||
),
|
||||
].padded(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
final l = sortedLabels.elementAt(index);
|
||||
return LabelItem<T>(
|
||||
name: l.name,
|
||||
content: contentBuilder?.call(l) ??
|
||||
Text(
|
||||
translateMatchingAlgorithmName(
|
||||
context, l.matchingAlgorithm) +
|
||||
((l.match?.isNotEmpty ?? false)
|
||||
? ": ${l.match}"
|
||||
: ""),
|
||||
maxLines: 2,
|
||||
),
|
||||
onOpenEditPage: onEdit,
|
||||
filterBuilder: filterBuilder,
|
||||
leading: leadingBuilder?.call(l),
|
||||
label: l,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
childCount: labels.length,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class LabelText<T extends Label> extends StatelessWidget {
|
||||
final int? id;
|
||||
final T? label;
|
||||
final String placeholder;
|
||||
final TextStyle? style;
|
||||
|
||||
const LabelText({
|
||||
super.key,
|
||||
this.style,
|
||||
this.id,
|
||||
this.placeholder = "",
|
||||
required this.label,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => LabelCubit<T>(
|
||||
context.read<LabelRepository<T>>(),
|
||||
),
|
||||
child: BlocBuilder<LabelCubit<T>, LabelState<T>>(
|
||||
builder: (context, state) {
|
||||
return Text(
|
||||
state.labels[id]?.toString() ?? placeholder,
|
||||
style: style,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
},
|
||||
),
|
||||
return Text(
|
||||
label?.toString() ?? placeholder,
|
||||
style: style,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user