mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.
This commit is contained in:
@@ -99,7 +99,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: 13,
|
left: 13,
|
||||||
right: 13,
|
right: 13,
|
||||||
top: 13,
|
|
||||||
bottom: _media.padding.bottom + 77,
|
bottom: _media.padding.bottom + 77,
|
||||||
),
|
),
|
||||||
itemCount: buildFuncs ? _cardsOrder.length + 1 : _cardsOrder.length,
|
itemCount: buildFuncs ? _cardsOrder.length + 1 : _cardsOrder.length,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import '../../../data/res/ui.dart';
|
|||||||
import '../../../data/store/private_key.dart';
|
import '../../../data/store/private_key.dart';
|
||||||
import '../../../locator.dart';
|
import '../../../locator.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/custom_appbar.dart';
|
||||||
import '../../widget/tag/editor.dart';
|
import '../../widget/tag/btn.dart';
|
||||||
import '../private_key/edit.dart';
|
import '../private_key/edit.dart';
|
||||||
|
|
||||||
class ServerEditPage extends StatefulWidget {
|
class ServerEditPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
Widget _buildBodySmall({
|
Widget _buildBodySmall({
|
||||||
required ServerProvider provider,
|
required ServerProvider provider,
|
||||||
required List<String> filtered,
|
required List<String> filtered,
|
||||||
EdgeInsets? padding = const EdgeInsets.fromLTRB(7, 10, 7, 7),
|
EdgeInsets? padding = const EdgeInsets.fromLTRB(7, 0, 7, 7),
|
||||||
bool buildTags = true,
|
bool buildTags = true,
|
||||||
}) {
|
}) {
|
||||||
final count = buildTags ? filtered.length + 2 : filtered.length + 1;
|
final count = buildTags ? filtered.length + 2 : filtered.length + 1;
|
||||||
@@ -164,7 +164,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
child: _buildBodySmall(
|
child: _buildBodySmall(
|
||||||
provider: pro,
|
provider: pro,
|
||||||
filtered: left,
|
filtered: left,
|
||||||
padding: const EdgeInsets.fromLTRB(7, 10, 0, 7),
|
padding: const EdgeInsets.fromLTRB(7, 0, 0, 7),
|
||||||
buildTags: false,
|
buildTags: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -172,7 +172,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
child: _buildBodySmall(
|
child: _buildBodySmall(
|
||||||
provider: pro,
|
provider: pro,
|
||||||
filtered: right,
|
filtered: right,
|
||||||
padding: const EdgeInsets.fromLTRB(0, 10, 7, 7),
|
padding: const EdgeInsets.fromLTRB(0, 0, 7, 7),
|
||||||
buildTags: false,
|
buildTags: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import '../../../data/provider/snippet.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/tag/editor.dart';
|
import '../../widget/tag/btn.dart';
|
||||||
|
|
||||||
class SnippetEditPage extends StatefulWidget {
|
class SnippetEditPage extends StatefulWidget {
|
||||||
const SnippetEditPage({Key? key, this.snippet}) : super(key: key);
|
const SnippetEditPage({Key? key, this.snippet}) : super(key: key);
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:toolbox/core/extension/navigator.dart';
|
||||||
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
|
import '../../../core/utils/ui.dart';
|
||||||
import '../../../data/res/color.dart';
|
import '../../../data/res/color.dart';
|
||||||
|
|
||||||
class TagBtn extends StatelessWidget {
|
class TagBtn extends StatelessWidget {
|
||||||
@@ -16,28 +22,174 @@ class TagBtn extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return _wrap(
|
||||||
|
Text(
|
||||||
|
content,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: isEnable ? null : Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: onTap,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TagEditor extends StatelessWidget {
|
||||||
|
final List<String> tags;
|
||||||
|
final S s;
|
||||||
|
final void Function(List<String>)? onChanged;
|
||||||
|
final void Function(String old, String new_)? onRenameTag;
|
||||||
|
final List<String>? tagSuggestions;
|
||||||
|
|
||||||
|
const TagEditor({
|
||||||
|
super.key,
|
||||||
|
required this.tags,
|
||||||
|
required this.s,
|
||||||
|
this.onChanged,
|
||||||
|
this.onRenameTag,
|
||||||
|
this.tagSuggestions,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RoundRectCard(ListTile(
|
||||||
|
leading: const Icon(Icons.tag),
|
||||||
|
title: _buildTags(context, tags),
|
||||||
|
trailing: InkWell(
|
||||||
|
child: const Icon(Icons.add),
|
||||||
|
onTap: () {
|
||||||
|
_showTagDialog(context, tags, onChanged);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTags(BuildContext context, List<String> tags) {
|
||||||
|
tagSuggestions?.removeWhere((element) => tags.contains(element));
|
||||||
|
final suggestionLen = tagSuggestions?.length ?? 0;
|
||||||
|
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
||||||
|
if (counts == 0) return Text(s.tag);
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxHeight: 27),
|
||||||
|
child: ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index < tags.length) {
|
||||||
|
return _buildTagItem(context, tags[index], false);
|
||||||
|
} else if (index > tags.length) {
|
||||||
|
return _buildTagItem(
|
||||||
|
context,
|
||||||
|
tagSuggestions![index - tags.length - 1],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const VerticalDivider();
|
||||||
|
},
|
||||||
|
itemCount: counts,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTagItem(BuildContext context, String tag, bool isAdd) {
|
||||||
|
return _wrap(
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'#$tag',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: textSize13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4.0),
|
||||||
|
Icon(
|
||||||
|
isAdd ? Icons.add_circle : Icons.cancel,
|
||||||
|
size: 13.7,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (isAdd) {
|
||||||
|
tags.add(tag);
|
||||||
|
} else {
|
||||||
|
tags.remove(tag);
|
||||||
|
}
|
||||||
|
onChanged?.call(tags);
|
||||||
|
},
|
||||||
|
onLongPress: () => _showRenameDialog(context, tag),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showTagDialog(
|
||||||
|
BuildContext context,
|
||||||
|
List<String> tags,
|
||||||
|
void Function(List<String>)? onChanged,
|
||||||
|
) {
|
||||||
|
final textEditingController = TextEditingController();
|
||||||
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
title: Text(s.add),
|
||||||
|
child: Input(
|
||||||
|
controller: textEditingController,
|
||||||
|
hint: s.tag,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
final tag = textEditingController.text;
|
||||||
|
tags.add(tag.trim());
|
||||||
|
onChanged?.call(tags);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(s.add),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showRenameDialog(BuildContext context, String tag) {
|
||||||
|
final textEditingController = TextEditingController(text: tag);
|
||||||
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
title: Text(s.rename),
|
||||||
|
child: Input(
|
||||||
|
controller: textEditingController,
|
||||||
|
hint: s.tag,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
final newTag = textEditingController.text.trim();
|
||||||
|
if (newTag.isEmpty) return;
|
||||||
|
onRenameTag?.call(tag, newTag);
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
child: Text(s.rename),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _wrap(Widget child, {void Function()? onTap,
|
||||||
|
void Function()? onLongPress,}) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 4, right: 5, bottom: 9),
|
padding: const EdgeInsets.all(3),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: primaryColor.withAlpha(20),
|
color: primaryColor.withAlpha(20),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding: const EdgeInsets.symmetric(horizontal: 9.7, vertical: 1.7),
|
||||||
const EdgeInsets.symmetric(horizontal: 11, vertical: 2.7),
|
child: child,
|
||||||
child: Text(
|
|
||||||
content,
|
|
||||||
style: TextStyle(
|
|
||||||
color: isEnable ? null : Colors.grey,
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:toolbox/core/extension/navigator.dart';
|
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
|
|
||||||
import '../../../core/utils/ui.dart';
|
|
||||||
import '../../../data/res/color.dart';
|
|
||||||
|
|
||||||
class TagEditor extends StatelessWidget {
|
|
||||||
final List<String> tags;
|
|
||||||
final S s;
|
|
||||||
final void Function(List<String>)? onChanged;
|
|
||||||
final void Function(String old, String new_)? onRenameTag;
|
|
||||||
final List<String>? tagSuggestions;
|
|
||||||
|
|
||||||
const TagEditor({
|
|
||||||
super.key,
|
|
||||||
required this.tags,
|
|
||||||
required this.s,
|
|
||||||
this.onChanged,
|
|
||||||
this.onRenameTag,
|
|
||||||
this.tagSuggestions,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return RoundRectCard(ListTile(
|
|
||||||
leading: const Icon(Icons.tag),
|
|
||||||
title: _buildTags(context, tags),
|
|
||||||
trailing: InkWell(
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
onTap: () {
|
|
||||||
_showTagDialog(context, tags, onChanged);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildTags(BuildContext context, List<String> tags) {
|
|
||||||
tagSuggestions?.removeWhere((element) => tags.contains(element));
|
|
||||||
final suggestionLen = tagSuggestions?.length ?? 0;
|
|
||||||
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
|
||||||
if (counts == 0) return Text(s.tag);
|
|
||||||
return ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(maxHeight: 27),
|
|
||||||
child: ListView.builder(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (index < tags.length) {
|
|
||||||
return _buildTagItem(context, tags[index], false);
|
|
||||||
} else if (index > tags.length) {
|
|
||||||
return _buildTagItem(
|
|
||||||
context,
|
|
||||||
tagSuggestions![index - tags.length - 1],
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const VerticalDivider();
|
|
||||||
},
|
|
||||||
itemCount: counts,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildTagItem(BuildContext context, String tag, bool isAdd) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
if (isAdd) {
|
|
||||||
tags.add(tag);
|
|
||||||
} else {
|
|
||||||
tags.remove(tag);
|
|
||||||
}
|
|
||||||
onChanged?.call(tags);
|
|
||||||
},
|
|
||||||
onLongPress: () => _showRenameDialog(context, tag),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'#$tag',
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4.0),
|
|
||||||
Icon(
|
|
||||||
isAdd ? Icons.add_circle : Icons.cancel,
|
|
||||||
size: 14.0,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showTagDialog(
|
|
||||||
BuildContext context,
|
|
||||||
List<String> tags,
|
|
||||||
void Function(List<String>)? onChanged,
|
|
||||||
) {
|
|
||||||
final textEditingController = TextEditingController();
|
|
||||||
showRoundDialog(
|
|
||||||
context: context,
|
|
||||||
title: Text(s.add),
|
|
||||||
child: Input(
|
|
||||||
controller: textEditingController,
|
|
||||||
hint: s.tag,
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
final tag = textEditingController.text;
|
|
||||||
tags.add(tag.trim());
|
|
||||||
onChanged?.call(tags);
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: Text(s.add),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showRenameDialog(BuildContext context, String tag) {
|
|
||||||
final textEditingController = TextEditingController(text: tag);
|
|
||||||
showRoundDialog(
|
|
||||||
context: context,
|
|
||||||
title: Text(s.rename),
|
|
||||||
child: Input(
|
|
||||||
controller: textEditingController,
|
|
||||||
hint: s.tag,
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
final newTag = textEditingController.text.trim();
|
|
||||||
if (newTag.isEmpty) return;
|
|
||||||
onRenameTag?.call(tag, newTag);
|
|
||||||
context.pop();
|
|
||||||
},
|
|
||||||
child: Text(s.rename),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:toolbox/core/extension/navigator.dart';
|
import 'package:toolbox/core/extension/navigator.dart';
|
||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/widget/tag/btn.dart';
|
|
||||||
|
import 'btn.dart';
|
||||||
|
|
||||||
class TagPicker<T> extends StatefulWidget {
|
class TagPicker<T> extends StatefulWidget {
|
||||||
final List<T> items;
|
final List<T> items;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class TagSwitcher extends StatelessWidget {
|
|||||||
if (tags.isEmpty) return placeholder;
|
if (tags.isEmpty) return placeholder;
|
||||||
final items = <String?>[null, ...tags];
|
final items = <String?>[null, ...tags];
|
||||||
return Container(
|
return Container(
|
||||||
height: 37,
|
height: 31,
|
||||||
width: width,
|
width: width,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:toolbox/view/widget/tag/btn.dart';
|
|
||||||
|
import 'btn.dart';
|
||||||
|
|
||||||
class TagView extends StatelessWidget {
|
class TagView extends StatelessWidget {
|
||||||
final void Function(String?) onTap;
|
final void Function(String?) onTap;
|
||||||
|
|||||||
Reference in New Issue
Block a user