refactored container tab with unassign
This commit is contained in:
@@ -121,6 +121,7 @@ class BrowserScreen extends HookConsumerWidget {
|
|||||||
ref.read(willAcceptDropProvider.notifier).clear();
|
ref.read(willAcceptDropProvider.notifier).clear();
|
||||||
},
|
},
|
||||||
onAcceptWithDetails: (details) async {
|
onAcceptWithDetails: (details) async {
|
||||||
|
ref.read(willAcceptDropProvider.notifier).clear();
|
||||||
await ref
|
await ref
|
||||||
.read(tabRepositoryProvider.notifier)
|
.read(tabRepositoryProvider.notifier)
|
||||||
.closeTab(details.data.tabId);
|
.closeTab(details.data.tabId);
|
||||||
|
|||||||
+32
-98
@@ -23,14 +23,12 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:nullability/nullability.dart';
|
import 'package:nullability/nullability.dart';
|
||||||
import 'package:weblibre/core/providers/global_drop.dart';
|
|
||||||
import 'package:weblibre/core/routing/routes.dart';
|
import 'package:weblibre/core/routing/routes.dart';
|
||||||
import 'package:weblibre/data/models/drag_data.dart';
|
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_title.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_title.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/tab_drag_container_target.dart';
|
||||||
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
|
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
|
||||||
|
|
||||||
class ContainerChips extends HookConsumerWidget {
|
class ContainerChips extends HookConsumerWidget {
|
||||||
@@ -63,8 +61,6 @@ class ContainerChips extends HookConsumerWidget {
|
|||||||
matchSortedContainersWithCountProvider(searchText),
|
matchSortedContainersWithCountProvider(searchText),
|
||||||
);
|
);
|
||||||
|
|
||||||
final dragTargetTabId = useValueNotifier<String?>(null);
|
|
||||||
|
|
||||||
return containersAsync.when(
|
return containersAsync.when(
|
||||||
data: (containers) {
|
data: (containers) {
|
||||||
final availableContainers =
|
final availableContainers =
|
||||||
@@ -100,103 +96,41 @@ class ContainerChips extends HookConsumerWidget {
|
|||||||
ContainerTitle(container: container),
|
ContainerTitle(container: container),
|
||||||
itemBadgeCount: (container) => container.tabCount,
|
itemBadgeCount: (container) => container.tabCount,
|
||||||
itemWrap: (child, container) {
|
itemWrap: (child, container) {
|
||||||
return HookBuilder(
|
return TabDragContainerTarget(
|
||||||
builder: (context) {
|
container: container,
|
||||||
final overlayController =
|
child: child,
|
||||||
useOverlayPortalController();
|
|
||||||
|
|
||||||
return DragTarget<TabDragData>(
|
|
||||||
onMove: (details) {
|
|
||||||
ref
|
|
||||||
.read(willAcceptDropProvider.notifier)
|
|
||||||
.setData(
|
|
||||||
ContainerDropData(details.data.tabId),
|
|
||||||
);
|
|
||||||
|
|
||||||
dragTargetTabId.value = details.data.tabId;
|
|
||||||
overlayController.show();
|
|
||||||
},
|
|
||||||
onLeave: (data) {
|
|
||||||
ref.read(willAcceptDropProvider.notifier).clear();
|
|
||||||
|
|
||||||
dragTargetTabId.value = null;
|
|
||||||
overlayController.hide();
|
|
||||||
},
|
|
||||||
onAcceptWithDetails: (details) async {
|
|
||||||
await ref
|
|
||||||
.read(tabDataRepositoryProvider.notifier)
|
|
||||||
.assignContainer(
|
|
||||||
details.data.tabId,
|
|
||||||
container,
|
|
||||||
);
|
|
||||||
|
|
||||||
dragTargetTabId.value = null;
|
|
||||||
overlayController.hide();
|
|
||||||
},
|
|
||||||
builder: (context, candidateData, rejectedData) {
|
|
||||||
final renderBox =
|
|
||||||
context.findRenderObject() as RenderBox?;
|
|
||||||
final position =
|
|
||||||
renderBox?.localToGlobal(Offset.zero) ??
|
|
||||||
Offset.zero;
|
|
||||||
|
|
||||||
return OverlayPortal(
|
|
||||||
controller: overlayController,
|
|
||||||
overlayChildBuilder: (context) => Positioned(
|
|
||||||
top: position.dy,
|
|
||||||
left: position.dx,
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: Transform.scale(
|
|
||||||
scale: 1.1,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: HookBuilder(
|
|
||||||
builder: (context) {
|
|
||||||
final dragTabId = useValueListenable(
|
|
||||||
dragTargetTabId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Opacity(
|
|
||||||
opacity: (dragTabId == null) ? 1.0 : 0.0,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
prefixListItems: [
|
prefixListItems: [
|
||||||
Consumer(
|
TabDragContainerTarget(
|
||||||
builder: (context, ref, child) {
|
container: null,
|
||||||
final tabCount = ref.watch(
|
child: Consumer(
|
||||||
containerTabCountProvider(
|
builder: (context, ref, child) {
|
||||||
// ignore: provider_parameters
|
final tabCount = ref.watch(
|
||||||
ContainerFilterById(containerId: null),
|
containerTabCountProvider(
|
||||||
).select((value) => value.valueOrNull ?? 0),
|
// ignore: provider_parameters
|
||||||
);
|
ContainerFilterById(containerId: null),
|
||||||
|
).select((value) => value.valueOrNull ?? 0),
|
||||||
|
);
|
||||||
|
|
||||||
return FilterChip(
|
return FilterChip(
|
||||||
avatar: const Icon(MdiIcons.folderHidden),
|
avatar: const Icon(MdiIcons.folderHidden),
|
||||||
labelPadding: (tabCount > 0)
|
labelPadding: (tabCount > 0)
|
||||||
? null
|
? null
|
||||||
: const EdgeInsets.only(right: 2.0),
|
: const EdgeInsets.only(right: 2.0),
|
||||||
label: (tabCount > 0)
|
label: (tabCount > 0)
|
||||||
? Text(tabCount.toString())
|
? Text(tabCount.toString())
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
selected: selectedContainer == null,
|
selected: selectedContainer == null,
|
||||||
showCheckmark: false,
|
showCheckmark: false,
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
onSelected?.call(null);
|
onSelected?.call(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
availableItems: availableContainers,
|
availableItems: availableContainers,
|
||||||
|
|||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:weblibre/core/providers/global_drop.dart';
|
||||||
|
import 'package:weblibre/data/models/drag_data.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||||
|
|
||||||
|
class TabDragContainerTarget extends HookConsumerWidget {
|
||||||
|
final ContainerData? container;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const TabDragContainerTarget({
|
||||||
|
super.key,
|
||||||
|
required this.container,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final overlayController = useOverlayPortalController();
|
||||||
|
|
||||||
|
return DragTarget<TabDragData>(
|
||||||
|
onMove: (details) {
|
||||||
|
ref
|
||||||
|
.read(willAcceptDropProvider.notifier)
|
||||||
|
.setData(ContainerDropData(details.data.tabId));
|
||||||
|
|
||||||
|
overlayController.show();
|
||||||
|
},
|
||||||
|
onLeave: (data) {
|
||||||
|
ref.read(willAcceptDropProvider.notifier).clear();
|
||||||
|
|
||||||
|
overlayController.hide();
|
||||||
|
},
|
||||||
|
onAcceptWithDetails: (details) async {
|
||||||
|
ref.read(willAcceptDropProvider.notifier).clear();
|
||||||
|
overlayController.hide();
|
||||||
|
|
||||||
|
if (container != null) {
|
||||||
|
await ref
|
||||||
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
|
.assignContainer(details.data.tabId, container!);
|
||||||
|
} else {
|
||||||
|
await ref
|
||||||
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
|
.unassignContainer(details.data.tabId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, candidateData, rejectedData) {
|
||||||
|
final renderBox = context.findRenderObject() as RenderBox?;
|
||||||
|
final position = renderBox?.localToGlobal(Offset.zero) ?? Offset.zero;
|
||||||
|
|
||||||
|
return OverlayPortal(
|
||||||
|
controller: overlayController,
|
||||||
|
overlayChildBuilder: (context) => Positioned(
|
||||||
|
top: position.dy,
|
||||||
|
left: position.dx,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Transform.scale(scale: 1.1, child: child),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Consumer(
|
||||||
|
child: child,
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final dragTabId = ref.watch(willAcceptDropProvider);
|
||||||
|
|
||||||
|
return Opacity(
|
||||||
|
opacity: (dragTabId == null) ? 1.0 : 0.0,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user