mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-18 01:50:57 -06:00
158 lines
5.8 KiB
Dart
158 lines
5.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:phylum/libphylum/db/resource_helpers.dart';
|
|
import 'package:phylum/libphylum/phylum_account.dart';
|
|
import 'package:phylum/ui/app/shortcuts.dart';
|
|
import 'package:phylum/libphylum/db/db.dart';
|
|
import 'package:phylum/ui/explorer/explorer_controller.dart';
|
|
import 'package:phylum/ui/app/routes.dart';
|
|
import 'package:phylum/ui/explorer/resource_drop_and_drop.dart';
|
|
import 'package:phylum/util/permissions.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
const reverse = false;
|
|
|
|
class PathView extends StatelessWidget {
|
|
final bool small;
|
|
|
|
const PathView({super.key, required this.small});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final route = context.select<ExplorerState, ExplorerRoute>((state) => state.route);
|
|
final account = context.read<PhylumAccount>();
|
|
final folderId = route.folderId(account);
|
|
if (folderId != null) {
|
|
return StreamBuilder(
|
|
stream: account.db.watchParents(folderId),
|
|
initialData: <ParentsResult>[ParentsResult(id: folderId, name: 'Folder', userPermission: 0)],
|
|
builder: (context, snapshot) {
|
|
final path = <PathInfo>[];
|
|
DateTime? deleted;
|
|
for (int i = snapshot.data!.length - 1; i >= 0; i--) {
|
|
final entry = snapshot.data![i];
|
|
final permission = entry.userPermission;
|
|
if (permission != 0) {
|
|
if (entry.id == account.user.home) {
|
|
path.add(PathInfo(title: 'My Files', dropTargetId: entry.id, target: ExplorerRouteHome()));
|
|
} else {
|
|
if (path.isEmpty) {
|
|
path.add(
|
|
PathInfo(title: 'Shared With Me', dropTargetId: null, target: const ExplorerRouteShared()));
|
|
}
|
|
if (deleted != entry.deleted) {
|
|
deleted = entry.deleted;
|
|
path.clear();
|
|
path.add(PathInfo(title: 'Trash', dropTargetId: null, target: const ExplorerRouteTrash()));
|
|
}
|
|
path.add(PathInfo(
|
|
title: entry.name,
|
|
dropTargetId: permission & permissionSetReadWrite == 0 ? null : entry.id,
|
|
target: ExplorerRouteFolder(folderId: entry.id),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
if (path.isEmpty) {
|
|
path.add(const PathInfo(title: 'Folder', dropTargetId: null, target: null, last: true));
|
|
} else {
|
|
path[path.length - 1] = PathInfo(
|
|
title: path.last.title,
|
|
dropTargetId: null,
|
|
target: null,
|
|
last: true,
|
|
);
|
|
}
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Padding(
|
|
padding: small
|
|
? const EdgeInsets.symmetric(horizontal: 8, vertical: 4)
|
|
: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
child: Row(
|
|
children: path.map((info) => PathItem(info, small: small)).toList(growable: false),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
}
|
|
final info = PathInfo(title: route.title, dropTargetId: null, target: null, last: true);
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Padding(
|
|
padding: small
|
|
? const EdgeInsets.symmetric(horizontal: 8, vertical: 4)
|
|
: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
child: Row(
|
|
children: [PathItem(info, small: small)],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class PathInfo {
|
|
final String title;
|
|
final String? dropTargetId;
|
|
final ExplorerRoute? target;
|
|
final bool last;
|
|
|
|
const PathInfo({
|
|
required this.title,
|
|
required this.dropTargetId,
|
|
required this.target,
|
|
this.last = false,
|
|
});
|
|
}
|
|
|
|
class PathItem extends StatelessWidget {
|
|
final PathInfo info;
|
|
final bool small;
|
|
|
|
const PathItem(this.info, {required this.small, super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return info.dropTargetId == null
|
|
? buildView(context, false)
|
|
: ResourceDragTarget(
|
|
resourceId: info.dropTargetId!,
|
|
buildItem: (context, dropTargetActive) => buildView(context, dropTargetActive),
|
|
);
|
|
}
|
|
|
|
Widget buildView(BuildContext context, bool dropTargetActive) {
|
|
if (info.last) return buildCard(context, dropTargetActive);
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
buildCard(context, dropTargetActive),
|
|
Icon(Icons.chevron_right, size: small ? 15 : 18),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildCard(BuildContext context, bool dropTargetActive) {
|
|
final theme = Theme.of(context);
|
|
final textStyle = small ? theme.textTheme.bodyMedium! : theme.textTheme.bodyLarge!;
|
|
final color = info.target == null ? theme.colorScheme.primary : theme.colorScheme.onSurfaceVariant;
|
|
return Card(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: small ? const BorderRadius.all(Radius.circular(3)) : const BorderRadius.all(Radius.circular(6)),
|
|
side: dropTargetActive ? BorderSide(width: small ? 1 : 2, color: theme.colorScheme.primary) : BorderSide.none,
|
|
),
|
|
elevation: info.target == null ? 0 : null,
|
|
margin: small ? const EdgeInsets.symmetric(horizontal: 3) : const EdgeInsets.symmetric(horizontal: 6),
|
|
child: InkWell(
|
|
onTap: info.target == null ? null : () => Actions.maybeInvoke(context, NavIntent(target: info.target!)),
|
|
child: Padding(
|
|
padding: small
|
|
? const EdgeInsets.symmetric(horizontal: 6, vertical: 4)
|
|
: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
child: Text(info.title, style: textStyle.copyWith(color: color)),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|