#54 run multiple snippets
This commit is contained in:
42
lib/view/widget/tag/btn.dart
Normal file
42
lib/view/widget/tag/btn.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../data/res/color.dart';
|
||||
|
||||
class TagBtn extends StatelessWidget {
|
||||
final String content;
|
||||
final void Function() onTap;
|
||||
final bool isEnable;
|
||||
|
||||
const TagBtn({
|
||||
super.key,
|
||||
required this.onTap,
|
||||
required this.isEnable,
|
||||
required this.content,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 4, right: 5, bottom: 9),
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
color: primaryColor.withAlpha(20),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 2.7),
|
||||
child: Center(
|
||||
child: Text(
|
||||
content,
|
||||
style: TextStyle(
|
||||
color: isEnable ? null : Colors.grey,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ 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 '../../../core/utils/ui.dart';
|
||||
import '../../../data/res/color.dart';
|
||||
|
||||
class TagEditor extends StatelessWidget {
|
||||
final List<String> tags;
|
||||
125
lib/view/widget/tag/picker.dart
Normal file
125
lib/view/widget/tag/picker.dart
Normal file
@@ -0,0 +1,125 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/data/res/ui.dart';
|
||||
import 'package:toolbox/view/widget/tag/btn.dart';
|
||||
|
||||
class TagPicker<T> extends StatefulWidget {
|
||||
final List<T> items;
|
||||
final bool Function(T, String?) containsTag;
|
||||
final String Function(T) name;
|
||||
final Set<String> tags;
|
||||
|
||||
const TagPicker({
|
||||
Key? key,
|
||||
required this.items,
|
||||
required this.containsTag,
|
||||
required this.name,
|
||||
required this.tags,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_TagPickerState<T> createState() => _TagPickerState<T>();
|
||||
}
|
||||
|
||||
class _TagPickerState<T> extends State<TagPicker<T>> {
|
||||
late S _s;
|
||||
late MediaQueryData _media;
|
||||
final List<T> _selected = [];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_s = S.of(context)!;
|
||||
_media = MediaQuery.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final child = widget.tags.isEmpty
|
||||
? Text(_s.noSavedSnippet)
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(_s.tag),
|
||||
height13,
|
||||
SizedBox(
|
||||
height: 37,
|
||||
width: _media.size.width * 0.7,
|
||||
child: _buildTags(),
|
||||
),
|
||||
Text(_s.all),
|
||||
height13,
|
||||
SizedBox(
|
||||
height: 37,
|
||||
width: _media.size.width * 0.7,
|
||||
child: _buildItems(),
|
||||
),
|
||||
],
|
||||
);
|
||||
return AlertDialog(
|
||||
title: Text(_s.choose),
|
||||
content: child,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.pop(_selected);
|
||||
},
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTags() {
|
||||
return ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: widget.tags.length,
|
||||
itemBuilder: (_, idx) {
|
||||
final item = widget.tags.elementAt(idx);
|
||||
final isEnable =
|
||||
widget.items.where((ele) => widget.containsTag(ele, item)).every(
|
||||
(element) => _selected.contains(element),
|
||||
);
|
||||
return TagBtn(
|
||||
isEnable: isEnable,
|
||||
onTap: () {
|
||||
if (isEnable) {
|
||||
_selected.removeWhere(
|
||||
(element) => widget.containsTag(element, item),
|
||||
);
|
||||
} else {
|
||||
_selected.addAll(widget.items.where(
|
||||
(ele) => widget.containsTag(ele, item),
|
||||
));
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
content: item,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildItems() {
|
||||
return ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: widget.items.length,
|
||||
itemBuilder: (context, index) {
|
||||
final e = widget.items[index];
|
||||
return TagBtn(
|
||||
isEnable: _selected.contains(e),
|
||||
onTap: () {
|
||||
if (_selected.contains(e)) {
|
||||
_selected.remove(e);
|
||||
} else {
|
||||
_selected.add(e);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
content: widget.name(e),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
49
lib/view/widget/tag/switcher.dart
Normal file
49
lib/view/widget/tag/switcher.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:nil/nil.dart';
|
||||
import 'package:toolbox/view/widget/tag/view.dart';
|
||||
|
||||
class TagSwitcher extends StatelessWidget {
|
||||
final List<String> tags;
|
||||
final double width;
|
||||
final void Function(String?) onTagChanged;
|
||||
final String? initTag;
|
||||
final String all;
|
||||
|
||||
const TagSwitcher({
|
||||
Key? key,
|
||||
required this.tags,
|
||||
required this.width,
|
||||
required this.onTagChanged,
|
||||
required this.all,
|
||||
this.initTag,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _buildTagsSwitcher(tags);
|
||||
}
|
||||
|
||||
Widget _buildTagsSwitcher(List<String> tags) {
|
||||
if (tags.isEmpty) return nil;
|
||||
final items = <String?>[null, ...tags];
|
||||
return Container(
|
||||
height: 37,
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
color: Colors.transparent,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
final item = items[index];
|
||||
return TagView(
|
||||
tag: item,
|
||||
initTag: initTag,
|
||||
all: all,
|
||||
onTap: onTagChanged,
|
||||
);
|
||||
},
|
||||
itemCount: items.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
26
lib/view/widget/tag/view.dart
Normal file
26
lib/view/widget/tag/view.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/view/widget/tag/btn.dart';
|
||||
|
||||
class TagView extends StatelessWidget {
|
||||
final void Function(String?) onTap;
|
||||
final String? tag;
|
||||
final String? initTag;
|
||||
final String all;
|
||||
|
||||
const TagView({
|
||||
super.key,
|
||||
required this.onTap,
|
||||
this.tag,
|
||||
this.initTag,
|
||||
required this.all,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TagBtn(
|
||||
onTap: () => onTap(tag),
|
||||
isEnable: initTag == tag,
|
||||
content: tag == null ? all : '#$tag',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:nil/nil.dart';
|
||||
|
||||
import '../../data/res/color.dart';
|
||||
|
||||
class TagSwitcher extends StatelessWidget {
|
||||
final List<String> tags;
|
||||
final double width;
|
||||
final void Function(String?) onTagChanged;
|
||||
final String? initTag;
|
||||
final String all;
|
||||
|
||||
const TagSwitcher({
|
||||
Key? key,
|
||||
required this.tags,
|
||||
required this.width,
|
||||
required this.onTagChanged,
|
||||
required this.all,
|
||||
this.initTag,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _buildTagsSwitcher(tags);
|
||||
}
|
||||
|
||||
Widget _buildTagsSwitcher(List<String> tags) {
|
||||
if (tags.isEmpty) return nil;
|
||||
final items = <String?>[null, ...tags];
|
||||
return Container(
|
||||
height: 37,
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
color: Colors.transparent,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) => _buildTagItem(items[index]),
|
||||
itemCount: items.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTagItem(String? tag) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 4, right: 5, bottom: 9),
|
||||
child: GestureDetector(
|
||||
onTap: () => onTagChanged(tag),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
color: primaryColor.withAlpha(20),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 2.7),
|
||||
child: Center(
|
||||
child: Text(
|
||||
tag == null ? all : '#$tag',
|
||||
style: TextStyle(
|
||||
color: initTag == tag ? null : Colors.grey,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user