improve tab (and other lexorank entities) sorting, ordering and reordering
This commit is contained in:
@@ -69,7 +69,8 @@ class _TabsSection extends StatelessWidget {
|
||||
SettingSection(name: 'Tabs'),
|
||||
_NewTabDefaultSection(),
|
||||
_SmallWebTabDefaultSection(),
|
||||
_NewTabPositionSection(),
|
||||
_TabListDirectionSection(),
|
||||
_TabBarDirectionSection(),
|
||||
_ShowContainerUiTile(),
|
||||
_ShowIsolatedTabUiTile(),
|
||||
_CreateChildTabsTile(),
|
||||
@@ -340,13 +341,13 @@ class _ExternalLinkHandlingSection extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _NewTabPositionSection extends HookConsumerWidget {
|
||||
const _NewTabPositionSection();
|
||||
class _TabListDirectionSection extends HookConsumerWidget {
|
||||
const _TabListDirectionSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final newTabPosition = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.newTabPosition),
|
||||
final direction = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
||||
);
|
||||
|
||||
return Padding(
|
||||
@@ -356,8 +357,65 @@ class _NewTabPositionSection extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ListTile(
|
||||
title: Text('New Tab Position'),
|
||||
subtitle: Text('Choose where newly created tabs appear by default'),
|
||||
title: Text('Tab List Direction'),
|
||||
subtitle: Text(
|
||||
'Choose whether the newest tab appears at the top or bottom of the tab list',
|
||||
),
|
||||
leading: Icon(MdiIcons.formatListBulleted),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
Center(
|
||||
child: SegmentedButton(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: TabListDirection.newestFirst,
|
||||
label: Text('Newest first'),
|
||||
icon: Icon(MdiIcons.arrowCollapseUp),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: TabListDirection.oldestFirst,
|
||||
label: Text('Oldest first'),
|
||||
icon: Icon(MdiIcons.arrowCollapseDown),
|
||||
),
|
||||
],
|
||||
selected: {direction},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.tabListDirection(value.first),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TabBarDirectionSection extends HookConsumerWidget {
|
||||
const _TabBarDirectionSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final direction = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.tabBarDirection),
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ListTile(
|
||||
title: Text('Tab Bar Direction'),
|
||||
subtitle: Text(
|
||||
'Choose whether the newest tab appears on the left or right of the quick switcher',
|
||||
),
|
||||
leading: Icon(MdiIcons.reorderHorizontal),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
@@ -366,23 +424,23 @@ class _NewTabPositionSection extends HookConsumerWidget {
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: NewTabPosition.first,
|
||||
label: Text('First'),
|
||||
value: TabBarDirection.newestFirst,
|
||||
label: Text('Newest first'),
|
||||
icon: Icon(MdiIcons.arrowCollapseLeft),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: NewTabPosition.end,
|
||||
label: Text('End'),
|
||||
value: TabBarDirection.oldestFirst,
|
||||
label: Text('Oldest first'),
|
||||
icon: Icon(MdiIcons.arrowCollapseRight),
|
||||
),
|
||||
],
|
||||
selected: {newTabPosition},
|
||||
selected: {direction},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.newTabPosition(value.first),
|
||||
currentSettings.copyWith.tabBarDirection(value.first),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
+34
-11
@@ -106,8 +106,13 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||
else
|
||||
SliverReorderableList(
|
||||
itemCount: visibleConfigs.length,
|
||||
onReorder: (oldIndex, newIndex) =>
|
||||
_onReorder(visibleConfigs, oldIndex, newIndex, repository),
|
||||
onReorder: (oldIndex, newIndex) => _onReorder(
|
||||
visibleConfigs,
|
||||
oldIndex,
|
||||
newIndex,
|
||||
repository,
|
||||
isVisible: true,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final config = visibleConfigs[index];
|
||||
return _ToolbarButtonConfigTile(
|
||||
@@ -145,8 +150,13 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||
else
|
||||
SliverReorderableList(
|
||||
itemCount: hiddenConfigs.length,
|
||||
onReorder: (oldIndex, newIndex) =>
|
||||
_onReorder(hiddenConfigs, oldIndex, newIndex, repository),
|
||||
onReorder: (oldIndex, newIndex) => _onReorder(
|
||||
hiddenConfigs,
|
||||
oldIndex,
|
||||
newIndex,
|
||||
repository,
|
||||
isVisible: false,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final config = hiddenConfigs[index];
|
||||
return _ToolbarButtonConfigTile(
|
||||
@@ -180,8 +190,9 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||
List<ToolbarButtonConfig> configs,
|
||||
int oldIndex,
|
||||
int newIndex,
|
||||
ContextualToolbarConfigRepository repository,
|
||||
) {
|
||||
ContextualToolbarConfigRepository repository, {
|
||||
required bool isVisible,
|
||||
}) {
|
||||
if (oldIndex == newIndex) return;
|
||||
final reorder = _resolveToolbarReorder(configs, oldIndex, newIndex);
|
||||
if (reorder.targetIndex == oldIndex) return;
|
||||
@@ -192,6 +203,7 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||
oldIndex,
|
||||
reorder.targetIndex,
|
||||
reorder.movedId,
|
||||
isVisible: isVisible,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -201,22 +213,33 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||
List<ToolbarButtonConfig> configs,
|
||||
int oldIndex,
|
||||
int targetIndex,
|
||||
String movedId,
|
||||
) async {
|
||||
String movedId, {
|
||||
required bool isVisible,
|
||||
}) async {
|
||||
// [configs] still contains the moved item. [targetIndex] is the
|
||||
// post-removal destination index, clamped to [0, configs.length - 1].
|
||||
// Because of the clamp, `>= configs.length - 1` only fires when the user
|
||||
// dropped past the very last surviving item; `configs[targetIndex + 1]`
|
||||
// is otherwise always a valid neighbour in the original list (since the
|
||||
// moved item sits at oldIndex < targetIndex + 1 in the else branch).
|
||||
final String orderKey;
|
||||
if (targetIndex <= 0) {
|
||||
orderKey = await repository.generateLeadingOrderKey();
|
||||
orderKey = await repository.generateLeadingOrderKey(isVisible: isVisible);
|
||||
} else if (targetIndex >= configs.length - 1) {
|
||||
orderKey = await repository.generateTrailingOrderKey();
|
||||
orderKey = await repository.generateTrailingOrderKey(
|
||||
isVisible: isVisible,
|
||||
);
|
||||
} else if (targetIndex < oldIndex) {
|
||||
orderKey =
|
||||
await repository.generateOrderKeyAfterButtonId(
|
||||
configs[targetIndex - 1].buttonId,
|
||||
isVisible: isVisible,
|
||||
) ??
|
||||
await repository.generateLeadingOrderKey();
|
||||
await repository.generateLeadingOrderKey(isVisible: isVisible);
|
||||
} else {
|
||||
orderKey = await repository.generateOrderKeyBeforeButtonId(
|
||||
configs[targetIndex + 1].buttonId,
|
||||
isVisible: isVisible,
|
||||
);
|
||||
}
|
||||
await repository.assignOrderKey(movedId, orderKey: orderKey);
|
||||
|
||||
Reference in New Issue
Block a user