The-Agency/lib/ui/widgets/common/settings_sheet.dart

214 lines
6.1 KiB
Dart

import "package:provider/provider.dart";
import "package:shadcn_flutter/shadcn_flutter.dart";
import "../../providers/settings_provider.dart";
import "../chat/models_panel.dart";
class SettingsSheet extends StatelessWidget {
const SettingsSheet();
@override
Widget build(BuildContext context) {
return Consumer<SettingsProvider>(
builder: (context, settingsProvider, _) {
return Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Settings",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
),
const SizedBox(height: 16),
const ModelsPanel(),
const SizedBox(height: 16),
// API key setting
const Text(
"OpenRouter API Key",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
),
const SizedBox(height: 8),
_ApiKeyInput(settingsProvider: settingsProvider),
const SizedBox(height: 16),
// theme setting
const Text(
"Theme",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
),
const SizedBox(height: 8),
_SimpleDropdown<String>(
value: settingsProvider.settings.theme,
items: const ["dark", "light"],
onChanged: (newTheme) {
settingsProvider.updateTheme(newTheme);
},
),
const SizedBox(height: 16),
// effort level setting
const Text(
"Effort Level",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
),
const SizedBox(height: 8),
_SimpleDropdown<String>(
value: settingsProvider.settings.effortLevel,
items: const ["low", "medium", "high", "max"],
onChanged: (newLevel) {
settingsProvider.updateEffortLevel(newLevel);
},
),
const SizedBox(height: 24),
// reset button
Button.ghost(
onPressed: () {
settingsProvider.resetToDefaults();
Navigator.pop(context);
},
child: const Text("Reset to Defaults"),
),
],
),
);
},
);
}
}
class _ApiKeyInput extends StatefulWidget {
final SettingsProvider settingsProvider;
const _ApiKeyInput({required this.settingsProvider});
@override
State<_ApiKeyInput> createState() => _ApiKeyInputState();
}
class _ApiKeyInputState extends State<_ApiKeyInput> {
late TextEditingController _controller;
bool _obscureText = true;
@override
void initState() {
super.initState();
_controller = TextEditingController(
text: widget.settingsProvider.settings.openRouterApiKey ?? "",
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: TextField(
controller: _controller,
obscureText: _obscureText,
onChanged: (value) {
widget.settingsProvider.updateApiKey(value);
},
placeholder: const Text("sk-or-v1-..."),
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Text(
_obscureText ? "Show" : "Hide",
style: const TextStyle(fontSize: 12, color: Color(0xFF999999)),
),
),
],
);
}
}
class _SimpleDropdown<T> extends StatelessWidget {
final T value;
final List<T> items;
final Function(T) onChanged;
const _SimpleDropdown({
required this.value,
required this.items,
required this.onChanged,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _showMenu(context),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFFE2E8F0)),
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(value.toString()),
const Text("", style: TextStyle(fontSize: 12)),
],
),
),
);
}
void _showMenu(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: items
.map((item) {
final isSelected = item == value;
return Container(
color: isSelected ? const Color(0xFFF1F5F9) : Colors.transparent,
child: GestureDetector(
onTap: () {
onChanged(item);
Navigator.pop(ctx);
},
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (isSelected)
const Padding(
padding: EdgeInsets.only(right: 8),
child: Text("", style: TextStyle(fontWeight: FontWeight.bold)),
),
Text(item.toString()),
],
),
),
),
);
})
.toList(),
),
),
);
}
}