fix: keep invoice list visible when keyboard opens
This commit is contained in:
parent
976ac6be20
commit
54135fa466
1 changed files with 148 additions and 134 deletions
|
|
@ -46,14 +46,11 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
}
|
||||
|
||||
Future<void> _showInvoiceActions(Invoice invoice) async {
|
||||
if (!_requireUnlock()) return;
|
||||
if (invoice.isLocked) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("ロック中の伝票は操作できません")));
|
||||
return;
|
||||
}
|
||||
if (!_isUnlocked) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("操作するにはアンロックが必要です")));
|
||||
return;
|
||||
}
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
|
||||
|
|
@ -93,24 +90,26 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
ListTile(
|
||||
leading: const Icon(Icons.edit),
|
||||
title: const Text("編集"),
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
onTap: _isUnlocked
|
||||
? () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => InvoiceInputForm(
|
||||
existingInvoice: invoice,
|
||||
onInvoiceGenerated: (inv, path) {},
|
||||
builder: (context) => InvoiceDetailPage(
|
||||
invoice: invoice,
|
||||
isUnlocked: _isUnlocked, // 状態を渡す
|
||||
),
|
||||
),
|
||||
);
|
||||
_loadData();
|
||||
},
|
||||
}
|
||||
: null,
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.delete, color: Colors.redAccent),
|
||||
title: const Text("削除", style: TextStyle(color: Colors.redAccent)),
|
||||
onTap: () async {
|
||||
onTap: _isUnlocked
|
||||
? () async {
|
||||
Navigator.pop(context);
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
|
|
@ -127,7 +126,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
await _invoiceRepo.deleteInvoice(invoice.id);
|
||||
_loadData();
|
||||
}
|
||||
},
|
||||
}
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -135,6 +135,12 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
);
|
||||
}
|
||||
|
||||
bool _requireUnlock() {
|
||||
if (_isUnlocked) return true;
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("スライドでロック解除してください")));
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _loadVersion() async {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
setState(() {
|
||||
|
|
@ -193,9 +199,10 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
Widget build(BuildContext context) {
|
||||
final amountFormatter = NumberFormat("#,###");
|
||||
final dateFormatter = DateFormat('yyyy/MM/dd');
|
||||
|
||||
return Scaffold(
|
||||
drawer: Drawer(
|
||||
resizeToAvoidBottomInset: false,
|
||||
drawer: _isUnlocked
|
||||
? Drawer(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
|
|
@ -214,7 +221,9 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
ListTile(
|
||||
leading: const Icon(Icons.receipt_long),
|
||||
title: const Text("伝票マスター"),
|
||||
onTap: () => Navigator.pop(context),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.people),
|
||||
|
|
@ -251,7 +260,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
appBar: AppBar(
|
||||
// leading removed
|
||||
title: GestureDetector(
|
||||
|
|
@ -317,7 +327,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
|
|
@ -342,7 +353,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.only(bottom: 100), // キーボードやFAB考慮
|
||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
padding: const EdgeInsets.only(bottom: 120), // 固定: FAB+安全余白
|
||||
itemCount: _filteredInvoices.length,
|
||||
itemBuilder: (context, index) {
|
||||
final invoice = _filteredInvoices[index];
|
||||
|
|
@ -383,23 +395,20 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
subtitle: Text("${dateFormatter.format(invoice.date)} - ${invoice.invoiceNumber}"),
|
||||
trailing: SizedBox(
|
||||
height: 56,
|
||||
height: 60,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text("¥${amountFormatter.format(invoice.totalAmount)}",
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
const SizedBox(height: 2),
|
||||
if (invoice.isSynced)
|
||||
const Icon(Icons.sync, size: 14, color: Colors.green)
|
||||
else
|
||||
const Icon(Icons.sync_disabled, size: 14, color: Colors.orange),
|
||||
const SizedBox(height: 4),
|
||||
IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints.tightFor(width: 32, height: 28),
|
||||
constraints: const BoxConstraints.tightFor(width: 32, height: 26),
|
||||
icon: const Icon(Icons.edit, size: 18),
|
||||
tooltip: invoice.isLocked ? "ロック中" : (_isUnlocked ? "編集" : "アンロックして編集"),
|
||||
onPressed: (invoice.isLocked || !_isUnlocked)
|
||||
|
|
@ -420,7 +429,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
],
|
||||
),
|
||||
),
|
||||
onTap: () async {
|
||||
onTap: _isUnlocked
|
||||
? () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
|
@ -431,16 +441,19 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
);
|
||||
_loadData();
|
||||
},
|
||||
onLongPress: () => _showInvoiceActions(invoice),
|
||||
}
|
||||
: () => _requireUnlock(),
|
||||
onLongPress: _isUnlocked ? () => _showInvoiceActions(invoice) : () => _requireUnlock(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () async {
|
||||
onPressed: _isUnlocked
|
||||
? () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
|
@ -448,7 +461,8 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
|||
),
|
||||
);
|
||||
_loadData();
|
||||
},
|
||||
}
|
||||
: _requireUnlock,
|
||||
label: const Text("新規伝票作成"),
|
||||
icon: const Icon(Icons.add),
|
||||
backgroundColor: Colors.indigo,
|
||||
|
|
|
|||
Loading…
Reference in a new issue