Skip to content

Commit

Permalink
fix & opt.
Browse files Browse the repository at this point in the history
fix: config reseted after restarting
opt.: always show search btn
fix: lang setting initial val
fix: pick single when no-multi & noConfirm
  • Loading branch information
lollipopkit committed May 8, 2024
1 parent 1f124fb commit e9e0054
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 49 deletions.
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ linter:
# producing the lint.
rules:
use_build_context_synchronously: false
constant_identifier_names: false
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

Expand Down
33 changes: 16 additions & 17 deletions lib/core/ext/context/dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,28 @@ extension DialogX on BuildContext {
}
}

/// [noConfirm] Return value immediately without confirmation,
/// only valid if [multi] is false
Future<List<T>?> showPickDialog<T>({
required List<T?> items,
required List<T> items,
String Function(T)? name,
bool multi = true,
List<T>? initial,
bool clearable = false,
bool clearable = true,
List<Widget>? actions,

/// Return value immediately without confirmation, only valid for non-multi
bool noConfirm = true,
String? title,
}) async {
assert(!noConfirm || !multi);
var vals = initial ?? <T>[];
final actions_ = [
if (actions != null) ...actions,
if (!noConfirm)
TextButton(
onPressed: () => pop(true),
child: Text(l10n.ok),
),
];
final sure = await showRoundDialog<bool>(
title: title ?? l10n.choose,
child: SingleChildScrollView(
Expand All @@ -80,14 +88,13 @@ extension DialogX on BuildContext {
items.length,
(index) {
final item = items[index];
if (item == null) return UIs.placeholder;
return ChoiceChipX<T>(
label: name?.call(item) ?? item.toString(),
state: state,
value: item,
onSelected: noConfirm
? (_) {
state.onSelected(item);
vals = [item];
pop(true);
}
: null,
Expand All @@ -98,15 +105,7 @@ extension DialogX on BuildContext {
},
),
),
actions: noConfirm
? null
: [
if (actions != null) ...actions,
TextButton(
onPressed: () => pop(true),
child: Text(l10n.ok),
),
],
actions: actions_.isEmpty ? null : actions_,
);
if (sure == true && vals.isNotEmpty) {
return vals;
Expand All @@ -115,10 +114,9 @@ extension DialogX on BuildContext {
}

Future<T?> showPickSingleDialog<T>({
required List<T?> items,
required List<T> items,
String Function(T)? name,
T? initial,
bool clearable = false,
List<Widget>? actions,

/// Return value immediately without confirmation
Expand All @@ -134,6 +132,7 @@ extension DialogX on BuildContext {
actions: actions,
);
if (vals != null && vals.isNotEmpty) {
assert(vals.length == 1);
return vals.first;
}
return null;
Expand Down
24 changes: 15 additions & 9 deletions lib/data/res/openai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,35 @@ import 'package:flutter_chatgpt/data/store/all.dart';

abstract final class OpenAICfg {
static final nameNotifier = ValueNotifier(_cfg.name);
static ChatConfig _cfg =
Stores.config.fetch(ChatConfig.defaultId) ?? ChatConfig.defaultOne;

static ChatConfig _cfg = () {
final selectedKey = Stores.config.selectedKey.fetch();
final selected = Stores.config.fetch(selectedKey);
return selected ?? ChatConfig.defaultOne;
}();

static ChatConfig get current => _cfg;
static set current(ChatConfig config) {
_cfg = config;
apply();
config.save();
Stores.config.selectedKey.put(config.id);
nameNotifier.value = config.name;
}

static void apply() {
Loggers.app.info('Switch profile [${_cfg.name}]');
OpenAI.apiKey = _cfg.key;
OpenAI.baseUrl = _cfg.url;
}

static bool switchTo(String id) {
final cfg = Stores.config.fetch(id);
static void switchToDefault() {
final cfg = Stores.config.fetch(ChatConfig.defaultId);
if (cfg != null) {
_cfg = cfg;
apply();
return true;
current = cfg;
} else {
current = ChatConfig.defaultOne;
Loggers.app.warning('Default config not found');
}
Loggers.app.warning('Config not found: $id');
return false;
}
}
4 changes: 4 additions & 0 deletions lib/data/store/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import 'package:flutter_chatgpt/data/model/chat/config.dart';
final class ConfigStore extends Store {
ConfigStore() : super('config');

static const SELECTED_KEY = 'selectedKey';
late final selectedKey = property(SELECTED_KEY, ChatConfig.defaultId);

ChatConfig? fetch(String id) {
final val = box.get(id) as ChatConfig?;
if (val == null && id == ChatConfig.defaultId) {
Expand All @@ -29,6 +32,7 @@ final class ConfigStore extends Store {
final map = <String, ChatConfig>{};
var errCount = 0;
for (final key in box.keys) {
if (key == SELECTED_KEY) continue;
final item = box.get(key);
if (item != null) {
if (item is ChatConfig) {
Expand Down
21 changes: 9 additions & 12 deletions lib/view/page/home/enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,25 @@ enum HomePageEnum {
final items = <IconButton>[
IconButton(
onPressed: () async {
final profiles = Stores.config.fetchAll().values.toList();
final select = await context.showPickSingleDialog(
title: l10n.profile,
items: profiles,
items: Stores.config.fetchAll().values.toList(),
name: (p0) => p0.name.isEmpty ? l10n.defaulT : p0.name,
initial: OpenAICfg.current,
);
if (select == null) return;
OpenAICfg.switchTo(select.id);
OpenAICfg.current = select;
},
icon: const Icon(Iconsax.profile_2user_bold),
tooltip: l10n.profile,
),
IconButton(
onPressed: () => showSearch(
context: context,
delegate: _ChatSearchDelegate(),
),
icon: const Icon(Icons.search),
)
];

/// Put it here, or it's l10n string won't rebuild every time
Expand All @@ -67,15 +73,6 @@ enum HomePageEnum {
onTap: () => _onShareChat(context),
onHomePage: [HomePageEnum.chat],
),
_MoreAction(
title: l10n.search,
icon: Icons.search,
onHomePage: [HomePageEnum.history],
onTap: () => showSearch(
context: context,
delegate: _ChatSearchDelegate(),
),
),
]) {
if (!_isWide.value && !item.onHomePage.contains(this)) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion lib/view/page/home/history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class _HistoryPageState extends State<_HistoryPage>
);
},
),
contentPadding: const EdgeInsets.only(left: 17, right: 13),
contentPadding: const EdgeInsets.only(left: 17, right: 15),
// trailing: Row(
// mainAxisSize: MainAxisSize.min,
// children: [
Expand Down
18 changes: 8 additions & 10 deletions lib/view/page/setting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class _SettingPageState extends State<SettingPage> {
title: Text(l10n.themeMode),
onTap: () async {
final result = await context.showPickSingleDialog(
title: l10n.themeMode,
items: ThemeMode.values,
name: (e) => e.name,
initial: ThemeMode.values[val],
Expand Down Expand Up @@ -183,9 +184,10 @@ class _SettingPageState extends State<SettingPage> {
),
onTap: () async {
final result = await context.showPickSingleDialog<Locale>(
title: l10n.lang,
items: AppLocalizations.supportedLocales,
name: (e) => e.toLanguageTag(),
initial: val.toLocale,
initial: val.toLocale ?? l10n.localeName.toLocale,
);
if (result != null) {
final newLocaleStr = result.toLanguageTag();
Expand Down Expand Up @@ -261,7 +263,7 @@ class _SettingPageState extends State<SettingPage> {
_cfgRN.build();
context.pop();
if (cfg.id == value.id) {
OpenAICfg.switchTo(ChatConfig.defaultId);
OpenAICfg.switchToDefault();
_cfgRN.build();
}
},
Expand All @@ -275,14 +277,14 @@ class _SettingPageState extends State<SettingPage> {
value: cfg.id == value.id,
onChanged: (val) {
if (val != true) return;
OpenAICfg.switchTo(value.id);
OpenAICfg.current = value;
_cfgRN.build();
},
),
title: Text(value.name.isEmpty ? l10n.defaulT : value.name),
onTap: () {
if (cfg.id == value.id) return;
OpenAICfg.switchTo(value.id);
OpenAICfg.current = value;
_cfgRN.build();
},
trailing: value.id != ChatConfig.defaultId ? delBtn : null,
Expand All @@ -305,7 +307,7 @@ class _SettingPageState extends State<SettingPage> {
id: shortid.generate(),
name: name,
)..save();
OpenAICfg.switchTo(cfg.id);
OpenAICfg.current = cfg;
_cfgRN.build();
},
title: Text(l10n.add),
Expand Down Expand Up @@ -691,11 +693,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildReplay() {
return ListTile(
leading: const Icon(Icons.replay),
title: Text(l10n.replay),
subtitle: Text(
'${l10n.attention}: experimental feature',
style: UIs.text13Grey,
),
title: Text('${l10n.replay} (experimental)'),
trailing: StoreSwitch(prop: _store.replay),
);
}
Expand Down

0 comments on commit e9e0054

Please sign in to comment.