mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 06:07:54 -06:00
feat: Add improved date input, fix bugs, restructurings
This commit is contained in:
@@ -9,7 +9,8 @@ import 'package:provider/provider.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
class DocumentPreview extends StatelessWidget {
|
||||
final DocumentModel document;
|
||||
final int documentId;
|
||||
final String? title;
|
||||
final BoxFit fit;
|
||||
final Alignment alignment;
|
||||
final double borderRadius;
|
||||
@@ -19,13 +20,14 @@ class DocumentPreview extends StatelessWidget {
|
||||
|
||||
const DocumentPreview({
|
||||
super.key,
|
||||
required this.document,
|
||||
required this.documentId,
|
||||
this.fit = BoxFit.cover,
|
||||
this.alignment = Alignment.topCenter,
|
||||
this.borderRadius = 12.0,
|
||||
this.enableHero = true,
|
||||
this.scale = 1.1,
|
||||
this.isClickable = true,
|
||||
this.title,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -34,12 +36,12 @@ class DocumentPreview extends StatelessWidget {
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: isClickable
|
||||
? () => DocumentPreviewRoute($extra: document).push(context)
|
||||
? () => DocumentPreviewRoute(id: documentId).push(context)
|
||||
: null,
|
||||
child: Builder(builder: (context) {
|
||||
if (enableHero) {
|
||||
return Hero(
|
||||
tag: "thumb_${document.id}",
|
||||
tag: "thumb_$documentId",
|
||||
child: _buildPreview(context),
|
||||
);
|
||||
}
|
||||
@@ -57,10 +59,9 @@ class DocumentPreview extends StatelessWidget {
|
||||
child: CachedNetworkImage(
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
cacheKey: "thumb_${document.id}",
|
||||
imageUrl: context
|
||||
.read<PaperlessDocumentsApi>()
|
||||
.getThumbnailUrl(document.id),
|
||||
cacheKey: "thumb_$documentId",
|
||||
imageUrl:
|
||||
context.read<PaperlessDocumentsApi>().getThumbnailUrl(documentId),
|
||||
errorWidget: (ctxt, msg, __) => Text(msg),
|
||||
placeholder: (context, value) => Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
@@ -56,6 +57,7 @@ class DocumentDetailedItem extends DocumentItem {
|
||||
final maxHeight = highlights != null
|
||||
? min(600.0, availableHeight)
|
||||
: min(500.0, availableHeight);
|
||||
final labels = context.watch<LabelRepository>().state;
|
||||
return Card(
|
||||
color: isSelected ? Theme.of(context).colorScheme.inversePrimary : null,
|
||||
child: InkWell(
|
||||
@@ -79,39 +81,71 @@ class DocumentDetailedItem extends DocumentItem {
|
||||
width: double.infinity,
|
||||
height: maxHeight / 2,
|
||||
),
|
||||
child: DocumentPreview(
|
||||
document: document,
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
DocumentPreview(
|
||||
documentId: document.id,
|
||||
title: document.title,
|
||||
),
|
||||
if (paperlessUser.canViewTags)
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: TagsWidget(
|
||||
tags:
|
||||
document.tags.map((e) => labels.tags[e]!).toList(),
|
||||
onTagSelected: onTagSelected,
|
||||
).padded(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.apply(color: Theme.of(context).hintColor),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.apply(color: Theme.of(context).hintColor),
|
||||
text: DateFormat.yMMMMd(
|
||||
Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
children: [
|
||||
if (paperlessUser.canViewDocumentTypes &&
|
||||
document.documentType != null) ...[
|
||||
const TextSpan(text: '\u30FB'),
|
||||
TextSpan(
|
||||
text: labels
|
||||
.documentTypes[document.documentType]?.name,
|
||||
recognizer: onDocumentTypeSelected != null
|
||||
? (TapGestureRecognizer()
|
||||
..onTap = () => onDocumentTypeSelected!(
|
||||
document.documentType))
|
||||
: null,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (document.archiveSerialNumber != null)
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'#${document.archiveSerialNumber}',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.apply(color: Theme.of(context).hintColor),
|
||||
),
|
||||
],
|
||||
Text(
|
||||
'#${document.archiveSerialNumber}',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.apply(color: Theme.of(context).hintColor),
|
||||
),
|
||||
],
|
||||
).paddedLTRB(8, 8, 8, 4),
|
||||
Text(
|
||||
document.title.isEmpty ? '-' : document.title,
|
||||
document.title.isEmpty ? '(-)' : document.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -128,39 +162,11 @@ class DocumentDetailedItem extends DocumentItem {
|
||||
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
correspondent: context
|
||||
.watch<LabelRepository>()
|
||||
.state
|
||||
.correspondents[document.correspondent],
|
||||
correspondent:
|
||||
labels.correspondents[document.correspondent],
|
||||
),
|
||||
],
|
||||
).paddedLTRB(8, 0, 8, 4),
|
||||
if (paperlessUser.canViewDocumentTypes)
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.description_outlined,
|
||||
size: 16,
|
||||
).paddedOnly(right: 4.0),
|
||||
DocumentTypeWidget(
|
||||
onSelected: onDocumentTypeSelected,
|
||||
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
documentType: context
|
||||
.watch<LabelRepository>()
|
||||
.state
|
||||
.documentTypes[document.documentType],
|
||||
),
|
||||
],
|
||||
).paddedLTRB(8, 0, 8, 4),
|
||||
if (paperlessUser.canViewTags)
|
||||
TagsWidget(
|
||||
tags: document.tags
|
||||
.map((e) => context.watch<LabelRepository>().state.tags[e]!)
|
||||
.toList(),
|
||||
onTagSelected: onTagSelected,
|
||||
).padded(),
|
||||
).paddedLTRB(8, 0, 8, 8),
|
||||
if (highlights != null)
|
||||
Html(
|
||||
data: '<p>${highlights!}</p>',
|
||||
|
||||
@@ -49,7 +49,7 @@ class DocumentGridItem extends DocumentItem {
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: DocumentPreview(
|
||||
document: document,
|
||||
documentId: document.id,
|
||||
borderRadius: 12.0,
|
||||
enableHero: enableHeroAnimation,
|
||||
),
|
||||
|
||||
@@ -75,31 +75,34 @@ class DocumentListItem extends DocumentItem {
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: RichText(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
text: DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall
|
||||
?.apply(color: Colors.grey),
|
||||
children: document.documentType != null
|
||||
? [
|
||||
const TextSpan(text: '\u30FB'),
|
||||
TextSpan(
|
||||
text: labels.documentTypes[document.documentType]?.name,
|
||||
recognizer: onDocumentTypeSelected != null
|
||||
? (TapGestureRecognizer()
|
||||
..onTap = () =>
|
||||
onDocumentTypeSelected!(document.documentType))
|
||||
: null,
|
||||
),
|
||||
]
|
||||
: null,
|
||||
subtitle: IntrinsicWidth(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: RichText(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
text:
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall
|
||||
?.apply(color: Colors.grey),
|
||||
children: document.documentType != null
|
||||
? [
|
||||
const TextSpan(text: '\u30FB'),
|
||||
TextSpan(
|
||||
text: labels.documentTypes[document.documentType]?.name,
|
||||
recognizer: onDocumentTypeSelected != null
|
||||
? (TapGestureRecognizer()
|
||||
..onTap = () => onDocumentTypeSelected!(
|
||||
document.documentType))
|
||||
: null,
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -108,7 +111,7 @@ class DocumentListItem extends DocumentItem {
|
||||
aspectRatio: _a4AspectRatio,
|
||||
child: GestureDetector(
|
||||
child: DocumentPreview(
|
||||
document: document,
|
||||
documentId: document.id,
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
enableHero: enableHeroAnimation,
|
||||
|
||||
Reference in New Issue
Block a user