첫 커밋: 로컬 프로젝트 업로드
This commit is contained in:
74
baron-sso/userfront/lib/core/widgets/language_selector.dart
Normal file
74
baron-sso/userfront/lib/core/widgets/language_selector.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'package:easy_localization/easy_localization.dart' hide tr;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:userfront/i18n.dart';
|
||||
|
||||
import '../i18n/locale_storage.dart';
|
||||
import '../i18n/locale_utils.dart';
|
||||
|
||||
class LanguageSelector extends StatelessWidget {
|
||||
const LanguageSelector({super.key, this.compact = false});
|
||||
|
||||
final bool compact;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = EasyLocalization.of(context);
|
||||
final resolvedCurrent = normalizeLocaleCode(
|
||||
localization?.currentLocale?.languageCode,
|
||||
);
|
||||
final current = (resolvedCurrent == 'ko' || resolvedCurrent == 'en')
|
||||
? resolvedCurrent
|
||||
: 'en';
|
||||
final items = [
|
||||
DropdownMenuItem(value: 'ko', child: Text(tr('ui.common.language_ko'))),
|
||||
DropdownMenuItem(
|
||||
value: 'en',
|
||||
child: Text(tr('ui.common.language_en', fallback: 'English')),
|
||||
),
|
||||
];
|
||||
|
||||
final iconSize = compact ? 16.0 : 18.0;
|
||||
final dropdown = DropdownButtonHideUnderline(
|
||||
child: DropdownButton<String>(
|
||||
value: current,
|
||||
items: items,
|
||||
isDense: true,
|
||||
icon: Icon(Icons.arrow_drop_down, size: compact ? 18 : 20),
|
||||
onChanged: (value) async {
|
||||
if (value == null || value == current) {
|
||||
return;
|
||||
}
|
||||
LocaleStorage.write(value);
|
||||
if (localization != null) {
|
||||
await localization.setLocale(Locale(value));
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
Uri uri;
|
||||
try {
|
||||
uri = GoRouterState.of(context).uri;
|
||||
} catch (_) {
|
||||
uri = Uri.base;
|
||||
}
|
||||
final target = buildLocalizedPath(value, uri);
|
||||
context.go(target);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: compact ? 0 : 2),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minHeight: compact ? 24 : 28),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.language, size: iconSize),
|
||||
const SizedBox(width: 6),
|
||||
dropdown,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:userfront/i18n.dart';
|
||||
|
||||
import '../theme/theme_scope.dart';
|
||||
|
||||
class ThemeToggleButton extends StatelessWidget {
|
||||
const ThemeToggleButton({super.key, this.compact = false});
|
||||
|
||||
final bool compact;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Localizations.localeOf(context);
|
||||
final controller = ThemeScope.of(context);
|
||||
|
||||
return ValueListenableBuilder<ThemeMode>(
|
||||
valueListenable: controller,
|
||||
builder: (context, mode, _) {
|
||||
final isLight = mode == ThemeMode.light;
|
||||
final icon = isLight
|
||||
? Icons.light_mode_outlined
|
||||
: Icons.dark_mode_outlined;
|
||||
final label = isLight
|
||||
? tr('ui.common.theme_light', fallback: 'Light')
|
||||
: tr('ui.common.theme_dark', fallback: 'Dark');
|
||||
final tooltip = tr('ui.common.theme_toggle', fallback: '테마 전환');
|
||||
|
||||
if (compact) {
|
||||
return IconButton(
|
||||
tooltip: tooltip,
|
||||
onPressed: () => controller.toggle(),
|
||||
icon: Icon(icon),
|
||||
);
|
||||
}
|
||||
|
||||
return OutlinedButton.icon(
|
||||
onPressed: () => controller.toggle(),
|
||||
icon: Icon(icon, size: 18),
|
||||
label: Text(label),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user