水印优化+ORC优化
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/storage/local_storage.dart';
|
||||
import '../../../models/watermark.dart';
|
||||
|
||||
/// 编辑这一张照片的水印内容(地址 / 天气 / 温度 / 备注)
|
||||
/// 编辑这一张照片的水印内容(时间 / 地址 / 天气 / 温度 / 备注)
|
||||
///
|
||||
/// 返回 null 表示用户取消了。时间不在这里改 —— 它总是「现在」,
|
||||
/// 让用户手改反而容易把水印弄成假的时间。
|
||||
/// 返回 null 表示用户取消了。
|
||||
Future<WatermarkData?> showWatermarkContentSheet(
|
||||
BuildContext context, {
|
||||
required WatermarkData initial,
|
||||
@@ -36,9 +36,18 @@ class _WatermarkContentSheetState extends State<_WatermarkContentSheet> {
|
||||
late final TextEditingController _temperature;
|
||||
late final TextEditingController _remark;
|
||||
|
||||
/// 时间可以改 —— 补加水印、或者当时手机时间不对时要靠它
|
||||
late DateTime _time;
|
||||
|
||||
/// 常用地址,从 LocalStorage 读(同步可读)
|
||||
late List<String> _addresses;
|
||||
bool _managing = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_time = widget.initial.time;
|
||||
_addresses = List<String>.from(LocalStorage.instance.getWatermarkAddresses());
|
||||
_address = TextEditingController(text: widget.initial.address);
|
||||
_weather = TextEditingController(text: widget.initial.weather);
|
||||
_temperature = TextEditingController(text: widget.initial.temperature);
|
||||
@@ -57,6 +66,7 @@ class _WatermarkContentSheetState extends State<_WatermarkContentSheet> {
|
||||
void _submit() {
|
||||
Navigator.of(context).pop(
|
||||
widget.initial.copyWith(
|
||||
time: _time,
|
||||
address: _address.text.trim(),
|
||||
weather: _weather.text.trim(),
|
||||
temperature: _temperature.text.trim(),
|
||||
@@ -65,6 +75,88 @@ class _WatermarkContentSheetState extends State<_WatermarkContentSheet> {
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------- 时间 ----------------
|
||||
|
||||
Future<void> _pickTime() async {
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: _time,
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
if (date == null || !mounted) return;
|
||||
|
||||
final time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.fromDateTime(_time),
|
||||
);
|
||||
if (time == null || !mounted) return;
|
||||
|
||||
setState(() {
|
||||
_time = DateTime(date.year, date.month, date.day, time.hour, time.minute);
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------- 常用地址 ----------------
|
||||
|
||||
Future<void> _addAddress() async {
|
||||
if (_addresses.length >= LocalStorage.watermarkAddressLimit) return;
|
||||
// 预填当前地址:常见的用法是「改一改然后存成常用」,省得再敲一遍
|
||||
final text = await _promptAddress(initial: _address.text.trim());
|
||||
if (text == null || !mounted) return;
|
||||
|
||||
final next = [..._addresses, text];
|
||||
await LocalStorage.instance.saveWatermarkAddresses(next);
|
||||
if (!mounted) return;
|
||||
setState(() => _addresses = next);
|
||||
}
|
||||
|
||||
Future<void> _removeAddress(int index) async {
|
||||
final next = [..._addresses]..removeAt(index);
|
||||
await LocalStorage.instance.saveWatermarkAddresses(next);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_addresses = next;
|
||||
if (_addresses.isEmpty) _managing = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<String?> _promptAddress({String initial = ''}) {
|
||||
final controller = TextEditingController(text: initial);
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: const Text('添加常用地址', style: TextStyle(fontSize: 16)),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
maxLines: 2,
|
||||
minLines: 1,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '例如:云南省昆明市五华区…',
|
||||
hintStyle: TextStyle(fontSize: 13, color: Color(0xFFD7CCC8)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
child: const Text('取消', style: TextStyle(color: Color(0xFF8D6E63))),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final text = controller.text.trim();
|
||||
Navigator.of(dialogContext).pop(text.isEmpty ? null : text);
|
||||
},
|
||||
child: const Text('添加', style: TextStyle(color: Color(0xFFC8956E))),
|
||||
),
|
||||
],
|
||||
),
|
||||
).whenComplete(controller.dispose);
|
||||
}
|
||||
|
||||
// ---------------- 构建 ----------------
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
@@ -89,12 +181,17 @@ class _WatermarkContentSheetState extends State<_WatermarkContentSheet> {
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
|
||||
_timeRow(),
|
||||
const SizedBox(height: 16),
|
||||
_quickAddressSection(),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
_field(label: '地址', controller: _address, hint: '自动定位,也可手改'),
|
||||
_field(label: '天气', controller: _weather, hint: '如:晴'),
|
||||
_field(label: '温度', controller: _temperature, hint: '如:25℃'),
|
||||
_field(label: '备注', controller: _remark, hint: '想写点什么'),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -139,6 +236,150 @@ class _WatermarkContentSheetState extends State<_WatermarkContentSheet> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 时间行:点一下弹日期 + 时间选择器
|
||||
Widget _timeRow() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('时间', style: TextStyle(fontSize: 13, color: Color(0xFF8D6E63))),
|
||||
const SizedBox(height: 6),
|
||||
InkWell(
|
||||
onTap: _pickTime,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 13),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF7F4F1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
formatWatermarkTime(_time),
|
||||
style: const TextStyle(fontSize: 14, color: Color(0xFF5D4037)),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.event, size: 17, color: Color(0xFFBCAAA4)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _quickAddressSection() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Text(
|
||||
'常用地址',
|
||||
style: TextStyle(fontSize: 13, color: Color(0xFF8D6E63)),
|
||||
),
|
||||
const Spacer(),
|
||||
if (_addresses.isNotEmpty)
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => _managing = !_managing),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||
child: Text(
|
||||
_managing ? '完成' : '管理',
|
||||
style: const TextStyle(fontSize: 12.5, color: Color(0xFFC8956E)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
for (var i = 0; i < _addresses.length; i++)
|
||||
_addressChip(i, _addresses[i]),
|
||||
if (!_managing && _addresses.length < LocalStorage.watermarkAddressLimit)
|
||||
_addChip(),
|
||||
],
|
||||
),
|
||||
if (_addresses.isEmpty && !_managing)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
'把常去的地点存下来,以后一键替换',
|
||||
style: TextStyle(fontSize: 11.5, color: Color(0xFFBCAAA4)),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _addressChip(int index, String address) {
|
||||
return GestureDetector(
|
||||
// 管理模式下点整体是删除,正常模式点一下填进地址框
|
||||
onTap: _managing
|
||||
? () => _removeAddress(index)
|
||||
: () => setState(() => _address.text = address),
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 210),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7),
|
||||
decoration: BoxDecoration(
|
||||
color: _managing ? const Color(0xFFFDECEA) : const Color(0xFFFFF3E6),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
address,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12.5,
|
||||
color: _managing
|
||||
? const Color(0xFFE53935)
|
||||
: const Color(0xFF8D6E63),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_managing) ...[
|
||||
const SizedBox(width: 6),
|
||||
const Icon(Icons.close, size: 14, color: Color(0xFFE53935)),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _addChip() {
|
||||
return GestureDetector(
|
||||
onTap: _addAddress,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: const Color(0xFFE0C9A6)),
|
||||
),
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.add, size: 14, color: Color(0xFFC8956E)),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'添加',
|
||||
style: TextStyle(fontSize: 12.5, color: Color(0xFFC8956E)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _field({
|
||||
required String label,
|
||||
required TextEditingController controller,
|
||||
|
||||
Reference in New Issue
Block a user