new: pick dialog support tags

This commit is contained in:
lollipopkit
2024-02-20 16:13:36 +08:00
parent 1a64dc5cba
commit ba564a886b
9 changed files with 125 additions and 40 deletions

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/context/common.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/view/widget/choice_chip.dart';
import 'package:toolbox/view/widget/tag.dart';
import '../../../data/res/ui.dart';
import '../../../view/widget/input_field.dart';
@@ -119,4 +120,77 @@ extension DialogX on BuildContext {
}
return null;
}
Future<List<T>?> showPickWithTagDialog<T>({
required List<T?> Function(String? tag) itemsBuilder,
required ValueNotifier<List<String>> tags,
String Function(T)? name,
List<T>? initial,
bool clearable = false,
bool multi = false,
List<Widget>? actions,
}) async {
var vals = initial ?? <T>[];
final tag = ValueNotifier<String?>(null);
final sure = await showRoundDialog<bool>(
title: Text(l10n.choose),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListenableBuilder(
listenable: tag,
builder: (_, __) => TagSwitcher(
tags: tags,
width: 300,
initTag: tag.value,
onTagChanged: (e) => tag.value = e,
),
),
const Divider(),
SingleChildScrollView(
child: ValueListenableBuilder(
valueListenable: tag,
builder: (_, val, __) {
final items = itemsBuilder(val);
return Choice<T>(
onChanged: (value) => vals = value,
multiple: multi,
clearable: clearable,
value: vals,
builder: (state, _) {
return Wrap(
children: List<Widget>.generate(
items.length,
(index) {
final item = items[index];
if (item == null) return UIs.placeholder;
return ChoiceChipX<T>(
label: name?.call(item) ?? item.toString(),
state: state,
value: item,
);
},
),
);
},
);
},
),
)
],
),
actions: [
if (actions != null) ...actions,
TextButton(
onPressed: () => pop(true),
child: Text(l10n.ok),
),
],
);
if (sure == true && vals.isNotEmpty) {
return vals;
}
return null;
}
}

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 770;
static const int build = 771;
static const String engine = "3.19.0";
static const String buildAt = "2024-02-20 15:34:30";
static const int modifications = 10;
static const String buildAt = "2024-02-20 16:12:21";
static const int modifications = 8;
static const int script = 38;
}

View File

@@ -120,7 +120,6 @@ class _ServerPageState extends State<ServerPage>
_tag = p0;
}),
initTag: _tag,
all: l10n.all,
);
}

View File

@@ -71,7 +71,6 @@ class _SnippetListPageState extends State<SnippetListPage> {
tags: provider.tags,
onTagChanged: (tag) => setState(() => _tag = tag),
initTag: _tag,
all: l10n.all,
width: _media.size.width,
),
footer: UIs.height77,

View File

@@ -275,12 +275,20 @@ class _SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin {
}
break;
case VirtualKeyFunc.snippet:
final s = await context.showPickSingleDialog<Snippet>(
items: Pros.snippet.snippets,
name: (p0) => p0.name,
final snippets = await context.showPickWithTagDialog<Snippet>(
tags: Pros.snippet.tags,
itemsBuilder: (e) {
if (e == null) return Pros.snippet.snippets;
return Pros.snippet.snippets
.where((element) => element.tags?.contains(e) ?? false)
.toList();
},
name: (e) => e.name,
);
if (s == null) return;
_terminal.textInput(s.script);
if (snippets == null || snippets.isEmpty) return;
final snippet = snippets.first;
_terminal.textInput(snippet.script);
_terminal.keyInput(TerminalKey.enter);
break;
case VirtualKeyFunc.file:

View File

@@ -122,11 +122,18 @@ void _onTapMoreBtns(
);
break;
case ServerFuncBtn.snippet:
final snippet = await context.showPickSingleDialog<Snippet>(
items: Pros.snippet.snippets,
final snippets = await context.showPickWithTagDialog<Snippet>(
tags: Pros.snippet.tags,
itemsBuilder: (e) {
if (e == null) return Pros.snippet.snippets;
return Pros.snippet.snippets
.where((element) => element.tags?.contains(e) ?? false)
.toList();
},
name: (e) => e.name,
);
if (snippet == null) return;
if (snippets == null || snippets.isEmpty) return;
final snippet = snippets.first;
AppRoute.ssh(spi: spi, initCmd: snippet.fmtWith(spi)).checkGo(
context: context,

View File

@@ -184,14 +184,12 @@ class TagSwitcher extends StatelessWidget implements PreferredSizeWidget {
final double width;
final void Function(String?) onTagChanged;
final String? initTag;
final String all;
const TagSwitcher({
super.key,
required this.tags,
required this.width,
required this.onTagChanged,
required this.all,
this.initTag,
});
@@ -213,7 +211,7 @@ class TagSwitcher extends StatelessWidget implements PreferredSizeWidget {
itemBuilder: (context, index) {
final item = items[index];
return TagBtn(
content: item == null ? all : '#$item',
content: item == null ? l10n.all : '#$item',
isEnable: initTag == item,
onTap: () => onTagChanged(item),
);