mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix: tag changed without saving
This commit is contained in:
@@ -14,6 +14,19 @@ class PrivateKeyInfo {
|
|||||||
required this.key,
|
required this.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
String? get type {
|
||||||
|
final lines = key.split('\n');
|
||||||
|
if (lines.length < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final firstLine = lines[0];
|
||||||
|
final splited = firstLine.split(RegExp(r'\s+'));
|
||||||
|
if (splited.length < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return splited[1];
|
||||||
|
}
|
||||||
|
|
||||||
PrivateKeyInfo.fromJson(Map<String, dynamic> json)
|
PrivateKeyInfo.fromJson(Map<String, dynamic> json)
|
||||||
: id = json["id"].toString(),
|
: id = json["id"].toString(),
|
||||||
key = json["private_key"].toString();
|
key = json["private_key"].toString();
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ import '../model/app/net_view.dart';
|
|||||||
import '../res/default.dart';
|
import '../res/default.dart';
|
||||||
|
|
||||||
class SettingStore extends PersistentStore {
|
class SettingStore extends PersistentStore {
|
||||||
|
/// Convert all settings into json
|
||||||
|
Map<String, dynamic> toJson() => {for (var e in box.keys) e: box.get(e)};
|
||||||
|
|
||||||
// ------BEGIN------
|
// ------BEGIN------
|
||||||
// These settings are not displayed in the settings page
|
// These settings are not displayed in the settings page
|
||||||
// You can edit them in the settings json editor (by long press the settings
|
// You can edit them in the settings json editor (by long press the settings
|
||||||
// item in the drawer of the server tab page)
|
// item in the drawer of the home page)
|
||||||
|
|
||||||
/// Discussion #146
|
/// Discussion #146
|
||||||
late final serverTabUseOldUI = StoreProperty(
|
late final serverTabUseOldUI = StoreProperty(
|
||||||
@@ -31,10 +34,16 @@ class SettingStore extends PersistentStore {
|
|||||||
'recordHistory',
|
'recordHistory',
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
// ------END------
|
|
||||||
|
|
||||||
/// Convert all settings into json
|
/// Bigger for bigger font size
|
||||||
Map<String, dynamic> toJson() => {for (var e in box.keys) e: box.get(e)};
|
/// 1.0 means 100%
|
||||||
|
/// Warning: This may cause some UI issues
|
||||||
|
late final textFactor = StoreProperty(
|
||||||
|
box,
|
||||||
|
'textFactor',
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
// ------END------
|
||||||
|
|
||||||
late final primaryColor = StoreProperty(
|
late final primaryColor = StoreProperty(
|
||||||
box,
|
box,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:after_layout/after_layout.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -30,8 +29,7 @@ class PrivateKeyEditPage extends StatefulWidget {
|
|||||||
_PrivateKeyEditPageState createState() => _PrivateKeyEditPageState();
|
_PrivateKeyEditPageState createState() => _PrivateKeyEditPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||||
with AfterLayoutMixin {
|
|
||||||
final _nameController = TextEditingController();
|
final _nameController = TextEditingController();
|
||||||
final _keyController = TextEditingController();
|
final _keyController = TextEditingController();
|
||||||
final _pwdController = TextEditingController();
|
final _pwdController = TextEditingController();
|
||||||
@@ -40,7 +38,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
final _pwdNode = FocusNode();
|
final _pwdNode = FocusNode();
|
||||||
|
|
||||||
late FocusScopeNode _focusScope;
|
late FocusScopeNode _focusScope;
|
||||||
late PrivateKeyProvider _provider;
|
final _provider = locator<PrivateKeyProvider>();
|
||||||
late S _s;
|
late S _s;
|
||||||
|
|
||||||
Widget? _loading;
|
Widget? _loading;
|
||||||
@@ -48,7 +46,18 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_provider = locator<PrivateKeyProvider>();
|
if (widget.pki != null) {
|
||||||
|
_nameController.text = widget.pki!.id;
|
||||||
|
_keyController.text = widget.pki!.key;
|
||||||
|
} else {
|
||||||
|
Clipboard.getData(_format).then((value) {
|
||||||
|
if (value == null) return;
|
||||||
|
final clipdata = value.text?.trim() ?? '';
|
||||||
|
if (clipdata.startsWith('-----BEGIN') && clipdata.endsWith('-----')) {
|
||||||
|
_keyController.text = clipdata;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -216,17 +225,4 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> afterFirstLayout(BuildContext context) async {
|
|
||||||
if (widget.pki != null) {
|
|
||||||
_nameController.text = widget.pki!.id;
|
|
||||||
_keyController.text = widget.pki!.key;
|
|
||||||
} else {
|
|
||||||
final clipdata = ((await Clipboard.getData(_format))?.text ?? '').trim();
|
|
||||||
if (clipdata.startsWith('-----BEGIN') && clipdata.endsWith('-----')) {
|
|
||||||
_keyController.text = clipdata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,15 +60,21 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
|||||||
padding: const EdgeInsets.all(13),
|
padding: const EdgeInsets.all(13),
|
||||||
itemCount: key.pkis.length,
|
itemCount: key.pkis.length,
|
||||||
itemBuilder: (context, idx) {
|
itemBuilder: (context, idx) {
|
||||||
|
final item = key.pkis[idx];
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(key.pkis[idx].id),
|
leading: Text(
|
||||||
trailing: TextButton(
|
'#$idx',
|
||||||
onPressed: () =>
|
style: const TextStyle(
|
||||||
AppRoute.keyEdit(pki: key.pkis[idx]).go(context),
|
fontSize: 15,
|
||||||
child: Text(_s.edit),
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
title: Text(item.id),
|
||||||
|
subtitle: Text(item.type ?? _s.unknown, style: grey),
|
||||||
|
onTap: () => AppRoute.keyEdit(pki: item).go(context),
|
||||||
|
trailing: const Icon(Icons.edit),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import 'package:after_layout/after_layout.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context.dart';
|
import 'package:toolbox/core/extension/context.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
|
||||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
|
||||||
|
|
||||||
import '../../../core/route.dart';
|
import '../../../core/route.dart';
|
||||||
import '../../../core/utils/ui.dart';
|
import '../../../core/utils/ui.dart';
|
||||||
@@ -16,7 +12,10 @@ import '../../../data/provider/server.dart';
|
|||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../../locator.dart';
|
import '../../../locator.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/custom_appbar.dart';
|
||||||
|
import '../../widget/input_field.dart';
|
||||||
|
import '../../widget/round_rect_card.dart';
|
||||||
import '../../widget/tag.dart';
|
import '../../widget/tag.dart';
|
||||||
|
import '../../widget/value_notifier.dart';
|
||||||
|
|
||||||
class ServerEditPage extends StatefulWidget {
|
class ServerEditPage extends StatefulWidget {
|
||||||
const ServerEditPage({Key? key, this.spi}) : super(key: key);
|
const ServerEditPage({Key? key, this.spi}) : super(key: key);
|
||||||
@@ -27,7 +26,7 @@ class ServerEditPage extends StatefulWidget {
|
|||||||
_ServerEditPageState createState() => _ServerEditPageState();
|
_ServerEditPageState createState() => _ServerEditPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
class _ServerEditPageState extends State<ServerEditPage> {
|
||||||
final _nameController = TextEditingController();
|
final _nameController = TextEditingController();
|
||||||
final _ipController = TextEditingController();
|
final _ipController = TextEditingController();
|
||||||
final _altUrlController = TextEditingController();
|
final _altUrlController = TextEditingController();
|
||||||
@@ -43,12 +42,42 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
late FocusScopeNode _focusScope;
|
late FocusScopeNode _focusScope;
|
||||||
late S _s;
|
late S _s;
|
||||||
|
|
||||||
final _serverProvider = locator<ServerProvider>();
|
final _srvs = locator<ServerProvider>();
|
||||||
final _keyProvider = locator<PrivateKeyProvider>();
|
final _keys = locator<PrivateKeyProvider>();
|
||||||
|
|
||||||
final _keyIdx = ValueNotifier<int?>(null);
|
final _keyIdx = ValueNotifier<int?>(null);
|
||||||
final _autoConnect = ValueNotifier(true);
|
final _autoConnect = ValueNotifier(true);
|
||||||
List<String> _tags = <String>[];
|
|
||||||
|
var _tags = <String>[];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
if (widget.spi != null) {
|
||||||
|
_nameController.text = widget.spi?.name ?? '';
|
||||||
|
_ipController.text = widget.spi?.ip ?? '';
|
||||||
|
_portController.text = (widget.spi?.port ?? 22).toString();
|
||||||
|
_usernameController.text = widget.spi?.user ?? '';
|
||||||
|
if (widget.spi?.pubKeyId == null) {
|
||||||
|
_passwordController.text = widget.spi?.pwd ?? '';
|
||||||
|
} else {
|
||||||
|
_keyIdx.value = _keys.pkis.indexWhere(
|
||||||
|
(e) => e.id == widget.spi!.pubKeyId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (widget.spi?.tags != null) {
|
||||||
|
/// List in dart is passed by pointer, so you need to copy it here
|
||||||
|
_tags.addAll(widget.spi!.tags!);
|
||||||
|
}
|
||||||
|
if (widget.spi?.alterUrl != null) {
|
||||||
|
_altUrlController.text = widget.spi!.alterUrl!;
|
||||||
|
}
|
||||||
|
if (widget.spi?.autoConnect != null) {
|
||||||
|
_autoConnect.value = widget.spi!.autoConnect!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@@ -92,7 +121,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_serverProvider.delServer(widget.spi!.id);
|
_srvs.delServer(widget.spi!.id);
|
||||||
context.pop();
|
context.pop();
|
||||||
context.pop(true);
|
context.pop(true);
|
||||||
},
|
},
|
||||||
@@ -159,14 +188,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
),
|
),
|
||||||
TagEditor(
|
TagEditor(
|
||||||
tags: _tags,
|
tags: _tags,
|
||||||
onChanged: (p0) {
|
onChanged: (p0) => _tags = p0,
|
||||||
setState(() {
|
|
||||||
_tags = p0;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
s: _s,
|
s: _s,
|
||||||
tagSuggestions: [..._serverProvider.tags],
|
allTags: [..._srvs.tags],
|
||||||
onRenameTag: _serverProvider.renameTag,
|
onRenameTag: _srvs.renameTag,
|
||||||
),
|
),
|
||||||
_buildAuth(),
|
_buildAuth(),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -240,7 +265,16 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
final e = key.pkis[index];
|
final e = key.pkis[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: Text(
|
||||||
|
'#${index + 1}',
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
|
||||||
|
),
|
||||||
title: Text(e.id, textAlign: TextAlign.start),
|
title: Text(e.id, textAlign: TextAlign.start),
|
||||||
|
subtitle: Text(
|
||||||
|
e.type ?? _s.unknown,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: grey,
|
||||||
|
),
|
||||||
trailing: _buildRadio(index, e),
|
trailing: _buildRadio(index, e),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -287,28 +321,6 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void afterFirstLayout(BuildContext context) {
|
|
||||||
if (widget.spi != null) {
|
|
||||||
_nameController.text = widget.spi?.name ?? '';
|
|
||||||
_ipController.text = widget.spi?.ip ?? '';
|
|
||||||
_portController.text = (widget.spi?.port ?? 22).toString();
|
|
||||||
_usernameController.text = widget.spi?.user ?? '';
|
|
||||||
if (widget.spi?.pubKeyId == null) {
|
|
||||||
_passwordController.text = widget.spi?.pwd ?? '';
|
|
||||||
} else {
|
|
||||||
_keyIdx.value =
|
|
||||||
_keyProvider.pkis.indexWhere((e) => e.id == widget.spi!.pubKeyId);
|
|
||||||
}
|
|
||||||
if (widget.spi?.tags != null) {
|
|
||||||
_tags = widget.spi!.tags!;
|
|
||||||
}
|
|
||||||
_altUrlController.text = widget.spi?.alterUrl ?? '';
|
|
||||||
_autoConnect.value = widget.spi?.autoConnect ?? true;
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onSave() async {
|
void _onSave() async {
|
||||||
if (_ipController.text == '') {
|
if (_ipController.text == '') {
|
||||||
showSnackBar(context, Text(_s.plzEnterHost));
|
showSnackBar(context, Text(_s.plzEnterHost));
|
||||||
@@ -353,7 +365,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
user: _usernameController.text,
|
user: _usernameController.text,
|
||||||
pwd: _passwordController.text.isEmpty ? null : _passwordController.text,
|
pwd: _passwordController.text.isEmpty ? null : _passwordController.text,
|
||||||
pubKeyId: _keyIdx.value != null
|
pubKeyId: _keyIdx.value != null
|
||||||
? _keyProvider.pkis.elementAt(_keyIdx.value!).id
|
? _keys.pkis.elementAt(_keyIdx.value!).id
|
||||||
: null,
|
: null,
|
||||||
tags: _tags,
|
tags: _tags,
|
||||||
alterUrl: _altUrlController.text.isEmpty ? null : _altUrlController.text,
|
alterUrl: _altUrlController.text.isEmpty ? null : _altUrlController.text,
|
||||||
@@ -361,9 +373,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (widget.spi == null) {
|
if (widget.spi == null) {
|
||||||
_serverProvider.addServer(spi);
|
_srvs.addServer(spi);
|
||||||
} else {
|
} else {
|
||||||
_serverProvider.updateServer(widget.spi!, spi);
|
_srvs.updateServer(widget.spi!, spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.pop();
|
context.pop();
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
_tags = p0;
|
_tags = p0;
|
||||||
}),
|
}),
|
||||||
s: _s,
|
s: _s,
|
||||||
tagSuggestions: [..._provider.tags],
|
allTags: [..._provider.tags],
|
||||||
onRenameTag: (old, n) => setState(() {
|
onRenameTag: (old, n) => setState(() {
|
||||||
_provider.renameTag(old, n);
|
_provider.renameTag(old, n);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ class TagBtn extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TagEditor extends StatelessWidget {
|
class TagEditor extends StatefulWidget {
|
||||||
final List<String> tags;
|
final List<String> tags;
|
||||||
final S s;
|
final S s;
|
||||||
final void Function(List<String>)? onChanged;
|
final void Function(List<String>)? onChanged;
|
||||||
final void Function(String old, String new_)? onRenameTag;
|
final void Function(String old, String new_)? onRenameTag;
|
||||||
final List<String>? tagSuggestions;
|
final List<String> allTags;
|
||||||
|
|
||||||
const TagEditor({
|
const TagEditor({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -50,40 +50,46 @@ class TagEditor extends StatelessWidget {
|
|||||||
required this.s,
|
required this.s,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.onRenameTag,
|
this.onRenameTag,
|
||||||
this.tagSuggestions,
|
this.allTags = const <String>[],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _TagEditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TagEditorState extends State<TagEditor> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RoundRectCard(ListTile(
|
return RoundRectCard(ListTile(
|
||||||
leading: const Icon(Icons.tag),
|
leading: const Icon(Icons.tag),
|
||||||
title: _buildTags(context, tags),
|
title: _buildTags(widget.tags),
|
||||||
trailing: InkWell(
|
trailing: InkWell(
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_showAddTagDialog(context, tags, onChanged);
|
_showAddTagDialog();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTags(BuildContext context, List<String> tags) {
|
Widget _buildTags(List<String> tags) {
|
||||||
tagSuggestions?.removeWhere((element) => tags.contains(element));
|
final suggestions = widget.allTags.where((e) => !tags.contains(e)).toList();
|
||||||
final suggestionLen = tagSuggestions?.length ?? 0;
|
final suggestionLen = suggestions.length;
|
||||||
|
|
||||||
|
/// Add vertical divider if suggestions.length > 0
|
||||||
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
||||||
if (counts == 0) return Text(s.tag);
|
if (counts == 0) return Text(widget.s.tag);
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxHeight: _kTagBtnHeight),
|
constraints: const BoxConstraints(maxHeight: _kTagBtnHeight),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index < tags.length) {
|
if (index < tags.length) {
|
||||||
return _buildTagItem(context, tags[index], false);
|
return _buildTagItem(tags[index]);
|
||||||
} else if (index > tags.length) {
|
} else if (index > tags.length) {
|
||||||
return _buildTagItem(
|
return _buildTagItem(
|
||||||
context,
|
suggestions[index - tags.length - 1],
|
||||||
tagSuggestions![index - tags.length - 1],
|
isAdd: true,
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return const VerticalDivider();
|
return const VerticalDivider();
|
||||||
@@ -93,7 +99,7 @@ class TagEditor extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTagItem(BuildContext context, String tag, bool isAdd) {
|
Widget _buildTagItem(String tag, {bool isAdd = false}) {
|
||||||
return _wrap(
|
return _wrap(
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -114,65 +120,63 @@ class TagEditor extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (isAdd) {
|
if (isAdd) {
|
||||||
tags.add(tag);
|
widget.tags.add(tag);
|
||||||
} else {
|
} else {
|
||||||
tags.remove(tag);
|
widget.tags.remove(tag);
|
||||||
}
|
}
|
||||||
onChanged?.call(tags);
|
widget.onChanged?.call(widget.tags);
|
||||||
|
setState(() {});
|
||||||
},
|
},
|
||||||
onLongPress: () => _showRenameDialog(context, tag),
|
onLongPress: () => _showRenameDialog(tag),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showAddTagDialog(
|
void _showAddTagDialog() {
|
||||||
BuildContext context,
|
|
||||||
List<String> tags,
|
|
||||||
void Function(List<String>)? onChanged,
|
|
||||||
) {
|
|
||||||
final textEditingController = TextEditingController();
|
final textEditingController = TextEditingController();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context: context,
|
context: context,
|
||||||
title: Text(s.add),
|
title: Text(widget.s.add),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.tag,
|
icon: Icons.tag,
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
hint: s.tag,
|
hint: widget.s.tag,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final tag = textEditingController.text;
|
final tag = textEditingController.text;
|
||||||
tags.add(tag.trim());
|
widget.tags.add(tag.trim());
|
||||||
onChanged?.call(tags);
|
widget.onChanged?.call(widget.tags);
|
||||||
Navigator.pop(context);
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(s.add),
|
child: Text(widget.s.add),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showRenameDialog(BuildContext context, String tag) {
|
void _showRenameDialog(String tag) {
|
||||||
final textEditingController = TextEditingController(text: tag);
|
final textEditingController = TextEditingController(text: tag);
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context: context,
|
context: context,
|
||||||
title: Text(s.rename),
|
title: Text(widget.s.rename),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.abc,
|
icon: Icons.abc,
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
hint: s.tag,
|
hint: widget.s.tag,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final newTag = textEditingController.text.trim();
|
final newTag = textEditingController.text.trim();
|
||||||
if (newTag.isEmpty) return;
|
if (newTag.isEmpty) return;
|
||||||
onRenameTag?.call(tag, newTag);
|
widget.onRenameTag?.call(tag, newTag);
|
||||||
context.pop();
|
context.pop();
|
||||||
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: Text(s.rename),
|
child: Text(widget.s.rename),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user