JJ_MKVMaker/lib/ui/secret_field.dart

69 lines
2.3 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';
import 'jj_field.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 JjField(
controller: widget.controller,
label: widget.label,
helper: widget.helper,
errorText: widget.errorText,
isDense: widget.isDense,
obscureText: hidden,
plainText: true,
onChanged: widget.onChanged,
suffix: toggle == null
? null
: IconButton(
tooltip: hidden ? tr('보이기') : tr('가리기'),
icon: Icon(hidden ? Icons.visibility_outlined : Icons.visibility_off_outlined, size: 18),
onPressed: toggle,
),
);
}
}