Improve display of current path
This commit is contained in:
parent
83c92a4152
commit
5c61a89805
3 changed files with 77 additions and 45 deletions
|
@ -6,7 +6,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,10 @@ class InventoryClient extends ChangeNotifier {
|
||||||
InventoryClient({required this.apiClient});
|
InventoryClient({required this.apiClient});
|
||||||
|
|
||||||
Future<List<Record>> _getDirectory(Record record) async {
|
Future<List<Record>> _getDirectory(Record record) async {
|
||||||
final dir = await _currentDirectory;
|
NeosDirectory? dir;
|
||||||
|
try {
|
||||||
|
dir = await _currentDirectory;
|
||||||
|
} catch(_) {}
|
||||||
final List<Record> records;
|
final List<Record> records;
|
||||||
if (dir == null || record.isRoot) {
|
if (dir == null || record.isRoot) {
|
||||||
records = await RecordApi.getUserRecordsAt(
|
records = await RecordApi.getUserRecordsAt(
|
||||||
|
@ -84,8 +87,8 @@ class InventoryClient extends ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> navigateUp() async {
|
Future<void> navigateUp({int times = 1}) async {
|
||||||
final dir = await _currentDirectory;
|
var dir = await _currentDirectory;
|
||||||
if (dir == null) {
|
if (dir == null) {
|
||||||
throw "Failed to navigate up: No directory loaded.";
|
throw "Failed to navigate up: No directory loaded.";
|
||||||
}
|
}
|
||||||
|
@ -93,7 +96,11 @@ class InventoryClient extends ChangeNotifier {
|
||||||
throw "Failed navigate up: Already at root";
|
throw "Failed navigate up: Already at root";
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentDirectory = Future.value(dir.parent);
|
for (int i = 0; i < times; i++) {
|
||||||
|
dir = dir?.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentDirectory = Future.value(dir);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:contacts_plus_plus/auxiliary.dart';
|
import 'package:contacts_plus_plus/auxiliary.dart';
|
||||||
import 'package:contacts_plus_plus/clients/inventory_client.dart';
|
import 'package:contacts_plus_plus/clients/inventory_client.dart';
|
||||||
import 'package:contacts_plus_plus/models/inventory/neos_path.dart';
|
import 'package:contacts_plus_plus/models/inventory/neos_path.dart';
|
||||||
|
@ -38,9 +39,8 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
value: Provider.of<InventoryClient>(context),
|
value: Provider.of<InventoryClient>(context),
|
||||||
child: Consumer<InventoryClient>(
|
child: Consumer<InventoryClient>(builder: (BuildContext context, InventoryClient iClient, Widget? child) {
|
||||||
builder: (BuildContext context, InventoryClient iClient, Widget? child) {
|
return FutureBuilder<NeosDirectory>(
|
||||||
return FutureBuilder<NeosDirectory>(
|
|
||||||
future: iClient.directoryFuture,
|
future: iClient.directoryFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final currentDir = snapshot.data;
|
final currentDir = snapshot.data;
|
||||||
|
@ -66,12 +66,12 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
FlutterError.reportError(FlutterErrorDetails(exception: snapshot.error!, stack: snapshot.stackTrace));
|
FlutterError.reportError(
|
||||||
|
FlutterErrorDetails(exception: snapshot.error!, stack: snapshot.stackTrace));
|
||||||
return DefaultErrorWidget(
|
return DefaultErrorWidget(
|
||||||
message: snapshot.error.toString(),
|
message: snapshot.error.toString(),
|
||||||
onRetry: () async {
|
onRetry: () {
|
||||||
iClient.loadInventoryRoot();
|
iClient.loadInventoryRoot();
|
||||||
await iClient.directoryFuture;
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,36 +80,56 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
|
||||||
|
|
||||||
records.sort((a, b) => a.name.compareTo(b.name));
|
records.sort((a, b) => a.name.compareTo(b.name));
|
||||||
final paths = records
|
final paths = records
|
||||||
.where((element) => element.recordType == RecordType.link || element.recordType == RecordType.directory)
|
.where((element) =>
|
||||||
|
element.recordType == RecordType.link || element.recordType == RecordType.directory)
|
||||||
.toList();
|
.toList();
|
||||||
final objects = records
|
final objects = records
|
||||||
.where((element) => element.recordType != RecordType.link && element.recordType != RecordType.directory)
|
.where((element) =>
|
||||||
|
element.recordType != RecordType.link && element.recordType != RecordType.directory)
|
||||||
.toList();
|
.toList();
|
||||||
|
final pathSegments = directory?.absolutePathSegments ?? [];
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
ListView(
|
ListView(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
||||||
child: Text(
|
child: Wrap(
|
||||||
directory?.absolutePath ?? NeosDirectory.rootName,
|
children: pathSegments
|
||||||
style: Theme
|
.mapIndexed(
|
||||||
.of(context)
|
(idx, segment) => Row(
|
||||||
.textTheme
|
mainAxisSize: MainAxisSize.min,
|
||||||
.labelLarge
|
children: [
|
||||||
?.copyWith(color: Theme
|
if (idx != 0) const Icon(Icons.chevron_right),
|
||||||
.of(context)
|
Padding(
|
||||||
.colorScheme
|
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
.primary),
|
child: TextButton(
|
||||||
),
|
style: TextButton.styleFrom(
|
||||||
),
|
foregroundColor: idx == pathSegments.length - 1
|
||||||
|
? Theme.of(context).colorScheme.primary
|
||||||
|
: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
iClient.navigateUp(times: pathSegments.length - 1 - idx);
|
||||||
|
},
|
||||||
|
child: Text(segment),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
)),
|
||||||
GridView.builder(
|
GridView.builder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: paths.length,
|
itemCount: paths.length,
|
||||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
maxCrossAxisExtent: 256, childAspectRatio: 4, crossAxisSpacing: 8, mainAxisSpacing: 8),
|
maxCrossAxisExtent: 256,
|
||||||
|
childAspectRatio: 4,
|
||||||
|
crossAxisSpacing: 8,
|
||||||
|
mainAxisSpacing: 8),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final record = paths[index];
|
final record = paths[index];
|
||||||
return PathInventoryTile(
|
return PathInventoryTile(
|
||||||
|
@ -144,13 +164,12 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
|
||||||
await Navigator.push(
|
await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) => PhotoView(
|
||||||
PhotoView(
|
minScale: PhotoViewComputedScale.contained,
|
||||||
minScale: PhotoViewComputedScale.contained,
|
imageProvider:
|
||||||
imageProvider: CachedNetworkImageProvider(
|
CachedNetworkImageProvider(Aux.neosDbToHttp(record.thumbnailUri)),
|
||||||
Aux.neosDbToHttp(record.thumbnailUri)),
|
heroAttributes: PhotoViewHeroAttributes(tag: record.id),
|
||||||
heroAttributes: PhotoViewHeroAttributes(tag: record.id),
|
),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -169,26 +188,32 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (snapshot.connectionState == ConnectionState.waiting)
|
Align(
|
||||||
Align(
|
alignment: Alignment.topCenter,
|
||||||
alignment: Alignment.center,
|
child: AnimatedSwitcher(
|
||||||
child: Container(
|
duration: const Duration(milliseconds: 250),
|
||||||
|
child: snapshot.connectionState == ConnectionState.waiting ? const LinearProgressIndicator() : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
child: snapshot.connectionState == ConnectionState.waiting ? Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
color: Colors.black38,
|
color: Colors.black38,
|
||||||
child: const Center(child: CircularProgressIndicator()),
|
) : null,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
}),
|
||||||
}
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue