mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 22:07:53 -06:00
feat: Implemented new view type, fix connectivity issues, fix offline issues, fix loading animations, fix documents page paging
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/widgets/shimmer_placeholder.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/tags_placeholder.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/text_placeholder.dart';
|
||||
|
||||
class DocumentGridLoadingWidget extends StatelessWidget {
|
||||
final bool _isSliver;
|
||||
@override
|
||||
const DocumentGridLoadingWidget({super.key}) : _isSliver = false;
|
||||
|
||||
const DocumentGridLoadingWidget.sliver({super.key}) : _isSliver = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const delegate = SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 4,
|
||||
crossAxisSpacing: 4,
|
||||
childAspectRatio: 1 / 2,
|
||||
);
|
||||
if (_isSliver) {
|
||||
return SliverGrid.builder(
|
||||
gridDelegate: delegate,
|
||||
itemBuilder: (context, index) => _buildPlaceholderGridItem(context),
|
||||
);
|
||||
}
|
||||
return GridView.builder(
|
||||
gridDelegate: delegate,
|
||||
itemBuilder: (context, index) => _buildPlaceholderGridItem(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPlaceholderGridItem(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Card(
|
||||
elevation: 1.0,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ShimmerPlaceholder(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ShimmerPlaceholder(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const TextPlaceholder(
|
||||
length: 70,
|
||||
fontSize: 16,
|
||||
).padded(1),
|
||||
const TextPlaceholder(
|
||||
length: 50,
|
||||
fontSize: 16,
|
||||
).padded(1),
|
||||
TextPlaceholder(
|
||||
length: 200,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleMedium?.fontSize ??
|
||||
10,
|
||||
).padded(1),
|
||||
const Spacer(),
|
||||
const TagsPlaceholder(
|
||||
count: 2,
|
||||
dense: true,
|
||||
),
|
||||
const Spacer(),
|
||||
TextPlaceholder(
|
||||
length: 100,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.bodySmall!.fontSize!,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import 'dart:math';
|
||||
|
||||
mixin DocumentItemPlaceholder {
|
||||
static const _tags = [" ", " ", " "];
|
||||
static const _titleLengths = <double>[double.infinity, 150.0, 200.0];
|
||||
static const _correspondentLengths = <double>[120.0, 80.0, 40.0];
|
||||
|
||||
Random get random;
|
||||
|
||||
RandomDocumentItemPlaceholderValues get nextValues {
|
||||
return RandomDocumentItemPlaceholderValues(
|
||||
tagCount: random.nextInt(_tags.length + 1),
|
||||
correspondentLength: _correspondentLengths[
|
||||
random.nextInt(_correspondentLengths.length - 1)],
|
||||
titleLength: _titleLengths[random.nextInt(_titleLengths.length - 1)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RandomDocumentItemPlaceholderValues {
|
||||
final int tagCount;
|
||||
final double correspondentLength;
|
||||
final double titleLength;
|
||||
|
||||
RandomDocumentItemPlaceholderValues({
|
||||
required this.tagCount,
|
||||
required this.correspondentLength,
|
||||
required this.titleLength,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/widgets/shimmer_placeholder.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/tags_placeholder.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/text_placeholder.dart';
|
||||
|
||||
class DocumentsListLoadingWidget extends StatelessWidget {
|
||||
final bool _isSliver;
|
||||
const DocumentsListLoadingWidget({super.key}) : _isSliver = false;
|
||||
|
||||
const DocumentsListLoadingWidget.sliver({super.key}) : _isSliver = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isSliver) {
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => _buildFakeListItem(context),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ListView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) => _buildFakeListItem(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildFakeListItem(BuildContext context) {
|
||||
const fontSize = 14.0;
|
||||
return ShimmerPlaceholder(
|
||||
child: ListTile(
|
||||
contentPadding: const EdgeInsets.all(8),
|
||||
dense: true,
|
||||
isThreeLine: true,
|
||||
leading: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
height: double.infinity,
|
||||
width: 35,
|
||||
),
|
||||
),
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const TextPlaceholder(
|
||||
length: 120,
|
||||
fontSize: fontSize,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
TextPlaceholder(
|
||||
length: 220,
|
||||
fontSize: Theme.of(context).textTheme.titleMedium!.fontSize!,
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TagsPlaceholder(count: 2, dense: true),
|
||||
SizedBox(height: 2),
|
||||
TextPlaceholder(
|
||||
length: 250,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize!,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ class TagsPlaceholder extends StatelessWidget {
|
||||
return SizedBox(
|
||||
height: 32,
|
||||
child: ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: count,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) => FilterChip(
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
|
||||
class TextPlaceholder extends StatelessWidget {
|
||||
final double length;
|
||||
|
||||
Reference in New Issue
Block a user