72 lines
2.5 KiB
Dart
72 lines
2.5 KiB
Dart
/// 약속 (W 공용 위젯, 설계 7-2 JjField - 비밀 칸): 비밀번호 · API 키 · 키 암호 칸 하나.
|
|
/// 입력: 글 칸 · 칸 이름 (짧게) · 도움 글 (칸 아래, 3줄까지) · 오류 글 · 가리기 (스스로 들거나 [hidden] · [onToggle] 로 바깥에서).
|
|
/// 출력: 가린 글 칸 + 눈 단추 (가렸으면 "보이기", 보이면 "가리기" - 아이콘 · 크기 · 툴팁이 어디서나 같음). 자동 고침 · 추천은 늘 끔.
|
|
/// 오류 없음. 쓰는 곳: WebDAV · FTP · SFTP · SMB 서버 설정 · AI 서비스 · 압축 비밀번호. 화면은 부르기만 한다
|
|
library;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../l10n/tr.dart';
|
|
|
|
class SecretField extends StatefulWidget {
|
|
const SecretField({
|
|
super.key,
|
|
required this.controller,
|
|
required this.label,
|
|
this.helper,
|
|
this.errorText,
|
|
this.isDense = false,
|
|
this.onChanged,
|
|
this.hidden,
|
|
this.onToggle,
|
|
});
|
|
|
|
final TextEditingController controller;
|
|
final String label;
|
|
final String? helper;
|
|
final String? errorText;
|
|
final bool isDense;
|
|
final ValueChanged<String>? onChanged;
|
|
|
|
/// 바깥에서 가리기를 정할 때 (눈 단추 하나로 칸 여럿 - 비밀번호와 확인 칸 등). null 이면 칸이 스스로 든다
|
|
final bool? hidden;
|
|
|
|
/// [hidden] 을 바깥에서 줄 때의 눈 단추 (null 이면 이 칸에는 단추 없음)
|
|
final VoidCallback? onToggle;
|
|
|
|
@override
|
|
State<SecretField> createState() => _SecretFieldState();
|
|
}
|
|
|
|
class _SecretFieldState extends State<SecretField> {
|
|
bool _hidden = true;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final outside = widget.hidden != null;
|
|
final hidden = widget.hidden ?? _hidden;
|
|
final toggle = outside ? widget.onToggle : () => setState(() => _hidden = !_hidden);
|
|
return TextField(
|
|
controller: widget.controller,
|
|
obscureText: hidden,
|
|
autocorrect: false,
|
|
enableSuggestions: false,
|
|
onChanged: widget.onChanged,
|
|
decoration: InputDecoration(
|
|
labelText: widget.label,
|
|
helperText: widget.helper,
|
|
helperMaxLines: 3,
|
|
errorText: widget.errorText,
|
|
isDense: widget.isDense,
|
|
suffixIcon: toggle == null
|
|
? null
|
|
: IconButton(
|
|
tooltip: hidden ? tr('보이기') : tr('가리기'),
|
|
icon: Icon(hidden ? Icons.visibility_outlined : Icons.visibility_off_outlined, size: 18),
|
|
onPressed: toggle,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|