Added translations, fixed chips theming

This commit is contained in:
Anton Stubenbord
2023-01-20 12:46:46 +01:00
parent f9dfddf704
commit fa3059218d
24 changed files with 399 additions and 270 deletions

View File

@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/generated/l10n.dart';
String translateMatchingAlgorithm(
BuildContext context, MatchingAlgorithm algorithm) {
String translateMatchingAlgorithmDescription(
BuildContext context,
MatchingAlgorithm algorithm,
) {
switch (algorithm) {
case MatchingAlgorithm.anyWord:
return S.of(context).matchingAlgorithmAnyDescription;
@@ -19,3 +21,23 @@ String translateMatchingAlgorithm(
return S.of(context).matchingAlgorithmAutoDescription;
}
}
String translateMatchingAlgorithmName(
BuildContext context,
MatchingAlgorithm algorithm,
) {
switch (algorithm) {
case MatchingAlgorithm.anyWord:
return S.of(context).matchingAlgorithmAnyName;
case MatchingAlgorithm.allWords:
return S.of(context).matchingAlgorithmAllName;
case MatchingAlgorithm.exactMatch:
return S.of(context).matchingAlgorithmExactName;
case MatchingAlgorithm.regex:
return S.of(context).matchingAlgorithmRegexName;
case MatchingAlgorithm.fuzzy:
return S.of(context).matchingAlgorithmFuzzyName;
case MatchingAlgorithm.auto:
return S.of(context).matchingAlgorithmAutoName;
}
}

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
import 'package:paperless_mobile/generated/l10n.dart';
class RelativeDateRangePickerHelper extends StatefulWidget {
@@ -28,15 +29,17 @@ class _RelativeDateRangePickerHelperState
separatorBuilder: (context, index) => const SizedBox(width: 8.0),
itemBuilder: (context, index) {
final option = _options[index];
return FilterChip(
label: Text(option.title),
onSelected: (isSelected) {
final value =
isSelected ? option.value : const RelativeDateRangeQuery();
widget.field.didChange(value);
widget.onChanged?.call(value);
},
selected: widget.field.value == option.value,
return ColoredChipWrapper(
child: FilterChip(
label: Text(option.title),
onSelected: (isSelected) {
final value =
isSelected ? option.value : const RelativeDateRangeQuery();
widget.field.didChange(value);
widget.onChanged?.call(value);
},
selected: widget.field.value == option.value,
),
);
},
scrollDirection: Axis.horizontal,

View File

@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
class ColoredChipWrapper extends StatelessWidget {
final Color? backgroundColor;
final Widget child;
const ColoredChipWrapper({
super.key,
this.backgroundColor,
required this.child,
});
@override
Widget build(BuildContext context) {
Color color = backgroundColor ?? Colors.lightGreen[50]!;
return Theme(
data: Theme.of(context).copyWith(
canvasColor: color,
),
child: child,
);
}
}

View File

@@ -438,7 +438,6 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
child: TagsWidget(
isClickable: widget.isLabelClickable,
tagIds: document.tags,
isSelectedPredicate: (_) => false,
onTagSelected: (int tagId) {},
),
),

View File

@@ -95,7 +95,7 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
}
void unselectView() {
emit(state.copyWith(selectedSavedViewId: null));
emit(state.copyWith(selectedSavedViewId: () => null));
}
@override

View File

@@ -25,7 +25,7 @@ class DocumentsState extends DocumentsPagedState {
List<PagedSearchResult<DocumentModel>>? value,
DocumentFilter? filter,
List<DocumentModel>? selection,
int? selectedSavedViewId,
int? Function()? selectedSavedViewId,
}) {
return DocumentsState(
hasLoaded: hasLoaded ?? this.hasLoaded,
@@ -33,7 +33,9 @@ class DocumentsState extends DocumentsPagedState {
value: value ?? this.value,
filter: filter ?? this.filter,
selection: selection ?? this.selection,
selectedSavedViewId: selectedSavedViewId ?? this.selectedSavedViewId,
selectedSavedViewId: selectedSavedViewId != null
? selectedSavedViewId.call()
: this.selectedSavedViewId,
);
}

View File

@@ -11,6 +11,7 @@ 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/workarounds/colored_chip.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/edit_document/cubit/edit_document_cubit.dart';
import 'package:paperless_mobile/features/edit_label/view/impl/add_correspondent_page.dart';
@@ -305,6 +306,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
);
}
///
/// Item builder is typically some sort of [Chip].
///
Widget _buildSuggestionsSkeleton<T>({
required Iterable<T> suggestions,
required ItemBuilder<T> itemBuilder,
@@ -321,8 +325,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: suggestions.length,
itemBuilder: (context, index) =>
itemBuilder(context, suggestions.elementAt(index)),
itemBuilder: (context, index) => ColoredChipWrapper(
child: itemBuilder(context, suggestions.elementAt(index)),
),
separatorBuilder: (BuildContext context, int index) =>
const SizedBox(width: 4.0),
),

View File

@@ -72,7 +72,6 @@ class DocumentGridItem extends StatelessWidget {
TagsWidget(
tagIds: document.tags,
isMultiLine: false,
isSelectedPredicate: isTagSelectedPredicate,
onTagSelected: onTagSelected,
),
const Spacer(),

View File

@@ -73,7 +73,6 @@ class DocumentListItem extends StatelessWidget {
isClickable: isLabelClickable,
tagIds: document.tags,
isMultiLine: false,
isSelectedPredicate: isTagSelectedPredicate,
onTagSelected: (id) => onTagSelected?.call(id),
),
),

View File

@@ -46,8 +46,17 @@ class LabelForm<T extends Label> extends StatefulWidget {
class _LabelFormState<T extends Label> extends State<LabelForm<T>> {
final _formKey = GlobalKey<FormBuilderState>();
late bool _enableMatchFormField;
PaperlessValidationErrors _errors = {};
@override
void initState() {
super.initState();
_enableMatchFormField =
widget.initialValue?.matchingAlgorithm != MatchingAlgorithm.auto;
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -71,15 +80,6 @@ class _LabelFormState<T extends Label> extends State<LabelForm<T>> {
initialValue: widget.initialValue?.name,
onChanged: (val) => setState(() => _errors = {}),
),
FormBuilderTextField(
name: Label.matchKey,
decoration: InputDecoration(
labelText: S.of(context).labelMatchPropertyLabel,
errorText: _errors[Label.matchKey],
),
initialValue: widget.initialValue?.match,
onChanged: (val) => setState(() => _errors = {}),
),
FormBuilderDropdown<int?>(
name: Label.matchingAlgorithmKey,
initialValue: widget.initialValue?.matchingAlgorithm.value ??
@@ -88,16 +88,32 @@ class _LabelFormState<T extends Label> extends State<LabelForm<T>> {
labelText: S.of(context).labelMatchingAlgorithmPropertyLabel,
errorText: _errors[Label.matchingAlgorithmKey],
),
onChanged: (val) => setState(() => _errors = {}),
onChanged: (val) {
setState(() {
_errors = {};
_enableMatchFormField = val != MatchingAlgorithm.auto.value;
});
},
items: MatchingAlgorithm.values
.map(
(algo) => DropdownMenuItem<int?>(
child: Text(translateMatchingAlgorithm(context, algo)),
child: Text(
translateMatchingAlgorithmDescription(context, algo)),
value: algo.value,
),
)
.toList(),
),
if (_enableMatchFormField)
FormBuilderTextField(
name: Label.matchKey,
decoration: InputDecoration(
labelText: S.of(context).labelMatchPropertyLabel,
errorText: _errors[Label.matchKey],
),
initialValue: widget.initialValue?.match,
onChanged: (val) => setState(() => _errors = {}),
),
FormBuilderCheckbox(
name: Label.isInsensitiveKey,
initialValue: widget.initialValue?.isInsensitive ?? true,
@@ -117,6 +133,11 @@ class _LabelFormState<T extends Label> extends State<LabelForm<T>> {
...widget.initialValue?.toJson() ?? {},
..._formKey.currentState!.value
};
if (mergedJson[Label.matchingAlgorithmKey] ==
MatchingAlgorithm.auto.value) {
// If auto is selected, the match will be removed.
mergedJson[Label.matchKey] = '';
}
final createdLabel = await widget.submitButtonConfig
.onSubmit(widget.fromJsonT(mergedJson));
Navigator.pop(context, createdLabel);

View File

@@ -219,7 +219,7 @@ class _InfoDrawerState extends State<InfoDrawer> {
],
),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
color: Theme.of(context).colorScheme.surfaceVariant,
),
),
...[

View File

@@ -4,6 +4,7 @@ import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/repository/provider/label_repositories_provider.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/workarounds/colored_chip.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/document_details/bloc/document_details_cubit.dart';
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
@@ -111,21 +112,23 @@ class _InboxItemState extends State<InboxItem> {
final actions = [
_buildAssignAsnAction(chipShape, context),
const SizedBox(width: 4.0),
ActionChip(
avatar: const Icon(Icons.delete_outline),
shape: chipShape,
label: const Text("Delete document"),
onPressed: () async {
final shouldDelete = await showDialog<bool>(
context: context,
builder: (context) =>
DeleteDocumentConfirmationDialog(document: widget.document),
) ??
false;
if (shouldDelete) {
context.read<InboxCubit>().delete(widget.document);
}
},
ColoredChipWrapper(
child: ActionChip(
avatar: const Icon(Icons.delete_outline),
shape: chipShape,
label: const Text("Delete document"),
onPressed: () async {
final shouldDelete = await showDialog<bool>(
context: context,
builder: (context) => DeleteDocumentConfirmationDialog(
document: widget.document),
) ??
false;
if (shouldDelete) {
context.read<InboxCubit>().delete(widget.document);
}
},
),
),
];
// return FutureBuilder<FieldSuggestions>(
@@ -191,31 +194,33 @@ class _InboxItemState extends State<InboxItem> {
BuildContext context,
) {
final hasAsn = widget.document.archiveSerialNumber != null;
return ActionChip(
avatar: _isAsnAssignLoading
? const CircularProgressIndicator()
: hasAsn
? null
: const Icon(Icons.archive_outlined),
shape: chipShape,
label: hasAsn
? Text(
'${S.of(context).documentArchiveSerialNumberPropertyShortLabel} #${widget.document.archiveSerialNumber}',
)
: const Text("Assign ASN"),
onPressed: !hasAsn
? () {
setState(() {
_isAsnAssignLoading = true;
});
context
.read<InboxCubit>()
.assignAsn(widget.document)
.whenComplete(
() => setState(() => _isAsnAssignLoading = false),
);
}
: null,
return ColoredChipWrapper(
child: ActionChip(
avatar: _isAsnAssignLoading
? const CircularProgressIndicator()
: hasAsn
? null
: const Icon(Icons.archive_outlined),
shape: chipShape,
label: hasAsn
? Text(
'${S.of(context).documentArchiveSerialNumberPropertyShortLabel} #${widget.document.archiveSerialNumber}',
)
: const Text("Assign ASN"),
onPressed: !hasAsn
? () {
setState(() {
_isAsnAssignLoading = true;
});
context
.read<InboxCubit>()
.assignAsn(widget.document)
.whenComplete(
() => setState(() => _isAsnAssignLoading = false),
);
}
: null,
),
);
}
@@ -224,7 +229,6 @@ class _InboxItemState extends State<InboxItem> {
tagIds: widget.document.tags,
isMultiLine: false,
isClickable: false,
isSelectedPredicate: (_) => false,
showShortNames: true,
dense: true,
);

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
import 'package:paperless_mobile/generated/l10n.dart';
class StoragePathAutofillFormBuilderField extends StatefulWidget {
@@ -61,71 +62,78 @@ class _StoragePathAutofillFormBuilderFieldState
"Select to autofill path variable",
style: Theme.of(context).textTheme.bodySmall,
),
Wrap(
alignment: WrapAlignment.start,
spacing: 4.0,
runSpacing: 4.0,
children: [
InputChip(
label: Text(
S.of(context).documentArchiveSerialNumberPropertyLongLabel),
onPressed: () => _addParameterToInput("{asn}", field),
),
InputChip(
label: Text(S.of(context).documentCorrespondentPropertyLabel),
onPressed: () => _addParameterToInput("{correspondent}", field),
),
InputChip(
label: Text(S.of(context).documentDocumentTypePropertyLabel),
onPressed: () => _addParameterToInput("{document_type}", field),
),
InputChip(
label: Text(S.of(context).documentTagsPropertyLabel),
onPressed: () => _addParameterToInput("{tag_list}", field),
),
InputChip(
label: Text(S.of(context).documentTitlePropertyLabel),
onPressed: () => _addParameterToInput("{title}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel),
onPressed: () => _addParameterToInput("{created}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterYearLabel})"),
onPressed: () => _addParameterToInput("{created_year}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterMonthLabel})"),
onPressed: () => _addParameterToInput("{created_month}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterDayLabel})"),
onPressed: () => _addParameterToInput("{created_day}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel),
onPressed: () => _addParameterToInput("{added}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterYearLabel})"),
onPressed: () => _addParameterToInput("{added_year}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterMonthLabel})"),
onPressed: () => _addParameterToInput("{added_month}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterDayLabel})"),
onPressed: () => _addParameterToInput("{added_day}", field),
),
],
ColoredChipWrapper(
child: Wrap(
alignment: WrapAlignment.start,
spacing: 4.0,
runSpacing: 4.0,
children: [
InputChip(
label: Text(S
.of(context)
.documentArchiveSerialNumberPropertyLongLabel),
onPressed: () => _addParameterToInput("{asn}", field),
),
InputChip(
label: Text(S.of(context).documentCorrespondentPropertyLabel),
onPressed: () =>
_addParameterToInput("{correspondent}", field),
),
InputChip(
label: Text(S.of(context).documentDocumentTypePropertyLabel),
onPressed: () =>
_addParameterToInput("{document_type}", field),
),
InputChip(
label: Text(S.of(context).documentTagsPropertyLabel),
onPressed: () => _addParameterToInput("{tag_list}", field),
),
InputChip(
label: Text(S.of(context).documentTitlePropertyLabel),
onPressed: () => _addParameterToInput("{title}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel),
onPressed: () => _addParameterToInput("{created}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterYearLabel})"),
onPressed: () =>
_addParameterToInput("{created_year}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterMonthLabel})"),
onPressed: () =>
_addParameterToInput("{created_month}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterDayLabel})"),
onPressed: () => _addParameterToInput("{created_day}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel),
onPressed: () => _addParameterToInput("{added}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterYearLabel})"),
onPressed: () => _addParameterToInput("{added_year}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterMonthLabel})"),
onPressed: () => _addParameterToInput("{added_month}", field),
),
InputChip(
label: Text(S.of(context).documentCreatedPropertyLabel +
" (${S.of(context).storagePathParameterDayLabel})"),
onPressed: () => _addParameterToInput("{added_day}", field),
),
],
),
)
],
),

View File

@@ -1,11 +1,10 @@
import 'package:flutter/material.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
class TagWidget extends StatelessWidget {
final Tag tag;
final VoidCallback? afterTagTapped;
final VoidCallback onSelected;
final bool isSelected;
final bool isClickable;
final bool showShortName;
final bool dense;
@@ -13,10 +12,8 @@ class TagWidget extends StatelessWidget {
const TagWidget({
super.key,
required this.tag,
required this.afterTagTapped,
this.isClickable = true,
required this.onSelected,
required this.isSelected,
this.showShortName = false,
this.dense = false,
});
@@ -27,24 +24,25 @@ class TagWidget extends StatelessWidget {
padding: const EdgeInsets.only(right: 4.0),
child: AbsorbPointer(
absorbing: !isClickable,
child: FilterChip(
labelPadding:
dense ? const EdgeInsets.symmetric(horizontal: 2) : null,
padding: dense ? const EdgeInsets.all(4) : null,
selected: isSelected,
selectedColor: tag.color,
onSelected: (_) => onSelected(),
visualDensity: const VisualDensity(vertical: -2),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: Text(
showShortName && tag.name.length > 6
? '${tag.name.substring(0, 6)}...'
: tag.name,
style: TextStyle(color: tag.textColor),
child: ColoredChipWrapper(
child: FilterChip(
labelPadding:
dense ? const EdgeInsets.symmetric(horizontal: 2) : null,
padding: dense ? const EdgeInsets.all(4) : null,
selectedColor: tag.color,
onSelected: (_) => onSelected(),
visualDensity: const VisualDensity(vertical: -2),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: Text(
showShortName && tag.name.length > 6
? '${tag.name.substring(0, 6)}...'
: tag.name,
style: TextStyle(color: tag.textColor),
),
checkmarkColor: tag.textColor,
backgroundColor: tag.color,
side: BorderSide.none,
),
checkmarkColor: tag.textColor,
backgroundColor: tag.color,
side: BorderSide.none,
),
),
);

View File

@@ -7,6 +7,7 @@ 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';
import 'package:paperless_mobile/generated/l10n.dart';
@@ -263,13 +264,15 @@ class _TagFormFieldState extends State<TagFormField> {
}
Widget _buildNotAssignedTag(FormFieldState<TagsQuery> field) {
return InputChip(
label: Text(
S.of(context).labelNotAssignedText,
return ColoredChipWrapper(
child: InputChip(
label: Text(
S.of(context).labelNotAssignedText,
),
backgroundColor:
Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
onDeleted: () => field.didChange(const IdsTagsQuery()),
),
backgroundColor:
Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
onDeleted: () => field.didChange(const IdsTagsQuery()),
);
}
@@ -283,33 +286,37 @@ class _TagFormFieldState extends State<TagFormField> {
if (tag == null) {
return Container();
}
return InputChip(
label: Text(
tag.name,
style: TextStyle(
color: tag.textColor,
decorationColor: tag.textColor,
decoration: !isIncludedTag ? TextDecoration.lineThrough : null,
decorationThickness: 2.0,
return ColoredChipWrapper(
child: InputChip(
label: Text(
tag.name,
style: TextStyle(
color: tag.textColor,
decorationColor: tag.textColor,
decoration: !isIncludedTag ? TextDecoration.lineThrough : null,
decorationThickness: 2.0,
),
),
onPressed: widget.excludeAllowed
? () => field.didChange(currentQuery.withIdQueryToggled(tag.id!))
: null,
backgroundColor: tag.color,
deleteIconColor: tag.textColor,
onDeleted: () => field.didChange(
(field.value as IdsTagsQuery).withIdsRemoved([tag.id!]),
),
),
onPressed: widget.excludeAllowed
? () => field.didChange(currentQuery.withIdQueryToggled(tag.id!))
: null,
backgroundColor: tag.color,
deleteIconColor: tag.textColor,
onDeleted: () => field.didChange(
(field.value as IdsTagsQuery).withIdsRemoved([tag.id!]),
),
);
}
Widget _buildAnyAssignedTag(FormFieldState<TagsQuery> field) {
return InputChip(
label: Text(S.of(context).labelAnyAssignedText),
backgroundColor:
Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.12),
onDeleted: () => field.didChange(const IdsTagsQuery()),
return ColoredChipWrapper(
child: InputChip(
label: Text(S.of(context).labelAnyAssignedText),
backgroundColor:
Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.12),
onDeleted: () => field.didChange(const IdsTagsQuery()),
),
);
}
}

View File

@@ -9,20 +9,16 @@ import 'package:paperless_mobile/features/labels/tags/view/widgets/tag_widget.da
class TagsWidget extends StatelessWidget {
final Iterable<int> tagIds;
final bool isMultiLine;
final VoidCallback? afterTagTapped;
final void Function(int tagId)? onTagSelected;
final bool isClickable;
final bool Function(int id) isSelectedPredicate;
final bool showShortNames;
final bool dense;
const TagsWidget({
Key? key,
required this.tagIds,
this.afterTagTapped,
this.isMultiLine = true,
this.isClickable = true,
required this.isSelectedPredicate,
this.onTagSelected,
this.showShortNames = false,
this.dense = true,
@@ -38,9 +34,7 @@ class TagsWidget extends StatelessWidget {
.map(
(id) => TagWidget(
tag: state.getLabel(id)!,
afterTagTapped: afterTagTapped,
isClickable: isClickable,
isSelected: isSelectedPredicate(id),
onSelected: () => onTagSelected?.call(id),
showShortName: showShortNames,
dense: dense,

View File

@@ -174,7 +174,6 @@ class _LabelsPageState extends State<LabelsPage>
)
: null,
),
contentBuilder: (t) => Text(t.match ?? ''),
emptyStateActionButtonLabel:
S.of(context).labelsPageTagsEmptyStateAddNewLabel,
emptyStateDescription:

View File

@@ -68,21 +68,22 @@ class LabelTabView<T extends Label> extends StatelessWidget {
connectivityState.isConnected,
child: ListView(
children: labels
.map(
(l) => LabelItem<T>(
name: l.name,
content: contentBuilder?.call(l) ??
Text(
"${translateMatchingAlgorithm(context, l.matchingAlgorithm)}\n"
"${l.match}",
maxLines: 2,
),
onOpenEditPage: onEdit,
filterBuilder: filterBuilder,
leading: leadingBuilder?.call(l),
label: l,
),
)
.map((l) => 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,
))
.toList(),
),
);

View File

@@ -182,15 +182,15 @@ class SavedViewSelectionWidget extends StatelessWidget {
}
void _onSelected(
bool isSelected,
bool selectionIntent,
BuildContext context,
SavedView view,
) async {
if (isSelected) {
if (selectionIntent) {
context.read<DocumentsCubit>().selectView(view.id!);
} else {
context.read<DocumentsCubit>().resetFilter();
context.read<DocumentsCubit>().unselectView();
context.read<DocumentsCubit>().resetFilter();
}
}

View File

@@ -1,6 +1,6 @@
{
"@@locale": "cs",
"aboutDialogDevelopedByText": "Vyvíjí",
"aboutDialogDevelopedByText": "Vyvíjí {name}",
"@aboutDialogDevelopedByText": {
"placeholders": {
"name": {}
@@ -490,16 +490,28 @@
"@loginPageUsernameValidatorMessageText": {},
"matchingAlgorithmAllDescription": "",
"@matchingAlgorithmAllDescription": {},
"matchingAlgorithmAllName": "",
"@matchingAlgorithmAllName": {},
"matchingAlgorithmAnyDescription": "",
"@matchingAlgorithmAnyDescription": {},
"matchingAlgorithmAnyName": "",
"@matchingAlgorithmAnyName": {},
"matchingAlgorithmAutoDescription": "",
"@matchingAlgorithmAutoDescription": {},
"matchingAlgorithmAutoName": "",
"@matchingAlgorithmAutoName": {},
"matchingAlgorithmExactDescription": "",
"@matchingAlgorithmExactDescription": {},
"matchingAlgorithmExactName": "",
"@matchingAlgorithmExactName": {},
"matchingAlgorithmFuzzyDescription": "",
"@matchingAlgorithmFuzzyDescription": {},
"matchingAlgorithmFuzzyName": "",
"@matchingAlgorithmFuzzyName": {},
"matchingAlgorithmRegexDescription": "",
"@matchingAlgorithmRegexDescription": {},
"matchingAlgorithmRegexName": "",
"@matchingAlgorithmRegexName": {},
"offlineWidgetText": "Nezdařilo se vytvořit připojení k internetu.",
"@offlineWidgetText": {},
"onboardingDoneButtonLabel": "Hotovo",

View File

@@ -1,6 +1,6 @@
{
"@@locale": "de",
"aboutDialogDevelopedByText": "Entwickelt von",
"aboutDialogDevelopedByText": "Entwickelt von {name}",
"@aboutDialogDevelopedByText": {
"placeholders": {
"name": {}
@@ -488,18 +488,30 @@
"@loginPageUsernameLabel": {},
"loginPageUsernameValidatorMessageText": "Nutzername darf nicht leer sein.",
"@loginPageUsernameValidatorMessageText": {},
"matchingAlgorithmAllDescription": "Alle: Dokument enthält alle folgenden Wörter",
"matchingAlgorithmAllDescription": "Dokument enthält alle folgenden Wörter",
"@matchingAlgorithmAllDescription": {},
"matchingAlgorithmAnyDescription": "Irgendein Wort: Dokument enthält eins der folgenden Wörter",
"matchingAlgorithmAllName": "Alle",
"@matchingAlgorithmAllName": {},
"matchingAlgorithmAnyDescription": "Dokument enthält eins der folgenden Wörter",
"@matchingAlgorithmAnyDescription": {},
"matchingAlgorithmAutoDescription": "Auto: Zuweisung automatisch erlernen",
"matchingAlgorithmAnyName": "Irgendein Wort",
"@matchingAlgorithmAnyName": {},
"matchingAlgorithmAutoDescription": "Zuweisung automatisch erlernen",
"@matchingAlgorithmAutoDescription": {},
"matchingAlgorithmExactDescription": "Exakt: Dokument enthält die folgende Zeichenkette",
"matchingAlgorithmAutoName": "Auto",
"@matchingAlgorithmAutoName": {},
"matchingAlgorithmExactDescription": "Dokument enthält die folgende Zeichenkette",
"@matchingAlgorithmExactDescription": {},
"matchingAlgorithmFuzzyDescription": "Ungenau: Dokument enthält ein zum folgenden Wort ähnliches Wort",
"matchingAlgorithmExactName": "Exakt",
"@matchingAlgorithmExactName": {},
"matchingAlgorithmFuzzyDescription": "Dokument enthält ein zum folgenden Wort ähnliches Wort",
"@matchingAlgorithmFuzzyDescription": {},
"matchingAlgorithmRegexDescription": "Regulärer Ausdruck: Dokument passt zum folgenden Ausdruck",
"matchingAlgorithmFuzzyName": "Ungenau",
"@matchingAlgorithmFuzzyName": {},
"matchingAlgorithmRegexDescription": "Dokument passt zum folgenden Ausdruck",
"@matchingAlgorithmRegexDescription": {},
"matchingAlgorithmRegexName": "Regulärer Ausdruck",
"@matchingAlgorithmRegexName": {},
"offlineWidgetText": "Es konte keine Verbindung zum Internet hergestellt werden.",
"@offlineWidgetText": {},
"onboardingDoneButtonLabel": "Fertig",

View File

@@ -488,18 +488,30 @@
"@loginPageUsernameLabel": {},
"loginPageUsernameValidatorMessageText": "Username must not be empty.",
"@loginPageUsernameValidatorMessageText": {},
"matchingAlgorithmAllDescription": "All: Document contains all of these words",
"matchingAlgorithmAllDescription": "Document contains all of these words",
"@matchingAlgorithmAllDescription": {},
"matchingAlgorithmAnyDescription": "Any: Document contains any of these words",
"matchingAlgorithmAllName": "All",
"@matchingAlgorithmAllName": {},
"matchingAlgorithmAnyDescription": "Document contains any of these words",
"@matchingAlgorithmAnyDescription": {},
"matchingAlgorithmAutoDescription": "Auto: Learn matching automatically",
"matchingAlgorithmAnyName": "Any",
"@matchingAlgorithmAnyName": {},
"matchingAlgorithmAutoDescription": "Learn matching automatically",
"@matchingAlgorithmAutoDescription": {},
"matchingAlgorithmExactDescription": "Exact: Document contains this string",
"matchingAlgorithmAutoName": "Auto",
"@matchingAlgorithmAutoName": {},
"matchingAlgorithmExactDescription": "Document contains this string",
"@matchingAlgorithmExactDescription": {},
"matchingAlgorithmFuzzyDescription": "Fuzzy: Document contains a word similar to this word",
"matchingAlgorithmExactName": "Exact",
"@matchingAlgorithmExactName": {},
"matchingAlgorithmFuzzyDescription": "Document contains a word similar to this word",
"@matchingAlgorithmFuzzyDescription": {},
"matchingAlgorithmRegexDescription": "Regular Expression: Document matches this regular expression",
"matchingAlgorithmFuzzyName": "Fuzzy",
"@matchingAlgorithmFuzzyName": {},
"matchingAlgorithmRegexDescription": "Document matches this regular expression",
"@matchingAlgorithmRegexDescription": {},
"matchingAlgorithmRegexName": "Regular Expression",
"@matchingAlgorithmRegexName": {},
"offlineWidgetText": "An internet connection could not be established.",
"@offlineWidgetText": {},
"onboardingDoneButtonLabel": "Done",

View File

@@ -490,16 +490,28 @@
"@loginPageUsernameValidatorMessageText": {},
"matchingAlgorithmAllDescription": "",
"@matchingAlgorithmAllDescription": {},
"matchingAlgorithmAllName": "",
"@matchingAlgorithmAllName": {},
"matchingAlgorithmAnyDescription": "",
"@matchingAlgorithmAnyDescription": {},
"matchingAlgorithmAnyName": "",
"@matchingAlgorithmAnyName": {},
"matchingAlgorithmAutoDescription": "",
"@matchingAlgorithmAutoDescription": {},
"matchingAlgorithmAutoName": "",
"@matchingAlgorithmAutoName": {},
"matchingAlgorithmExactDescription": "",
"@matchingAlgorithmExactDescription": {},
"matchingAlgorithmExactName": "",
"@matchingAlgorithmExactName": {},
"matchingAlgorithmFuzzyDescription": "",
"@matchingAlgorithmFuzzyDescription": {},
"matchingAlgorithmFuzzyName": "",
"@matchingAlgorithmFuzzyName": {},
"matchingAlgorithmRegexDescription": "",
"@matchingAlgorithmRegexDescription": {},
"matchingAlgorithmRegexName": "",
"@matchingAlgorithmRegexName": {},
"offlineWidgetText": "İnternet bağlantısı kurulamadı.",
"@offlineWidgetText": {},
"onboardingDoneButtonLabel": "Bitti",

View File

@@ -204,54 +204,20 @@ class PaperlessMobileEntrypoint extends StatefulWidget {
}
class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
final _lightTheme = ThemeData(
brightness: Brightness.light,
final _lightTheme = ThemeData.from(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.lightGreen,
brightness: Brightness.light,
),
useMaterial3: true,
colorSchemeSeed: Colors.lightGreen,
appBarTheme: const AppBarTheme(
scrolledUnderElevation: 0.0,
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
chipTheme: ChipThemeData(
backgroundColor: Colors.lightGreen[50],
),
listTileTheme: const ListTileThemeData(
tileColor: Colors.transparent,
),
);
final _darkTheme = ThemeData(
brightness: Brightness.dark,
final _darkTheme = ThemeData.from(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.lightGreen,
brightness: Brightness.dark,
),
useMaterial3: true,
colorSchemeSeed: Colors.lightGreen,
appBarTheme: const AppBarTheme(
scrolledUnderElevation: 0.0,
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
chipTheme: ChipThemeData(
backgroundColor: Colors.green[900],
),
listTileTheme: const ListTileThemeData(
tileColor: Colors.transparent,
),
);
@override
@@ -269,8 +235,39 @@ class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
return MaterialApp(
debugShowCheckedModeBanner: true,
title: "Paperless Mobile",
theme: _lightTheme,
darkTheme: _darkTheme,
theme: _lightTheme.copyWith(
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
listTileTheme: const ListTileThemeData(
tileColor: Colors.transparent,
),
),
darkTheme: _darkTheme.copyWith(
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
chipTheme: ChipThemeData(
backgroundColor: Colors.lightGreen[50],
),
listTileTheme: const ListTileThemeData(
tileColor: Colors.transparent,
),
),
themeMode: settings.preferredThemeMode,
supportedLocales: S.delegate.supportedLocales,
locale: Locale.fromSubtags(