Skip to content

Commit

Permalink
new: switch model on home (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
lollipopkit committed May 29, 2024
1 parent 0ffaa4b commit 8091260
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 90 deletions.
6 changes: 3 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 166;
CURRENT_PROJECT_VERSION = 167;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
Expand Down Expand Up @@ -494,7 +494,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 166;
CURRENT_PROJECT_VERSION = 167;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
Expand All @@ -519,7 +519,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 166;
CURRENT_PROJECT_VERSION = 167;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
Expand Down
19 changes: 2 additions & 17 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class MyApp extends StatelessWidget {
supportedLocales: AppLocalizations.supportedLocales,
themeMode: themeMode,
theme: ThemeData(colorSchemeSeed: UIs.colorSeed),
darkTheme: _getAmoledTheme(ThemeData(
darkTheme: ThemeData(
brightness: Brightness.dark,
colorSchemeSeed: UIs.colorSeed,
)),
).toAmoled,
home: Builder(
builder: (context) {
final l10n_ = AppLocalizations.of(context);
Expand All @@ -50,18 +50,3 @@ class MyApp extends StatelessWidget {
);
}
}

ThemeData _getAmoledTheme(ThemeData darkTheme) => darkTheme.copyWith(
scaffoldBackgroundColor: Colors.black,
dialogBackgroundColor: Colors.black,
drawerTheme: const DrawerThemeData(backgroundColor: Colors.black),
appBarTheme: const AppBarTheme(backgroundColor: Colors.black),
dialogTheme: const DialogTheme(backgroundColor: Colors.black),
bottomSheetTheme:
const BottomSheetThemeData(backgroundColor: Colors.black),
listTileTheme: const ListTileThemeData(tileColor: Colors.transparent),
cardTheme: const CardTheme(color: Colors.black12),
navigationBarTheme:
const NavigationBarThemeData(backgroundColor: Colors.black),
popupMenuTheme: const PopupMenuThemeData(color: Colors.black),
);
6 changes: 3 additions & 3 deletions lib/data/res/build.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

class Build {
static const String name = "GPTBox";
static const int build = 166;
static const int build = 167;
static const String engine = "3.22.1";
static const String buildAt = "2024-05-29 16:09:39";
static const int modifications = 5;
static const String buildAt = "2024-05-29 17:09:26";
static const int modifications = 1;
}
53 changes: 33 additions & 20 deletions lib/data/res/openai.dart
Original file line number Diff line number Diff line change
@@ -1,56 +1,69 @@
import 'package:dart_openai/dart_openai.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gpt_box/data/model/chat/config.dart';
import 'package:gpt_box/data/res/l10n.dart';
import 'package:gpt_box/data/store/all.dart';

abstract final class OpenAICfg {
static final nameNotifier = ValueNotifier(_cfg.name);
static final models = <String>[].vn;

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

static ChatConfig get current => _cfg;
static set current(ChatConfig config) {
_cfg = config;
static ChatConfig get current => vn.value;

static void setTo(ChatConfig config, BuildContext context) {
final old = vn.value;
vn.value = config;
apply();
config.save();
Stores.config.selectedKey.put(config.id);
nameNotifier.value = config.name;

updateModels();
if (old.id != config.id) {
Funcs.throttle(
updateModels,
id: 'setTo-${config.id}',
duration: 1000 * 30,
)?.then((ok) {
if (!ok && context.mounted) {
context.showSnackBar('${l10n.failed}: update models list');
}
});
}
}

static void updateModels() {
static Future<bool> updateModels() async {
try {
OpenAI.instance.model.list().then((value) {
models.value = value.map((e) => e.id).toList();
});
final val = await OpenAI.instance.model.list();
models.value = val.map((e) => e.id).toList();
return true;
} catch (e) {
Loggers.app.warning('Failed to update models', e);
return false;
}
}

static void apply() {
if (_cfg.id == ChatConfig.defaultId) {
if (vn.value.id == ChatConfig.defaultId) {
Loggers.app.info('Using default profile');
} else {
Loggers.app.info('Profile [${_cfg.name}]');
Loggers.app.info('Profile [${vn.value.name}]');
}
OpenAI.apiKey = _cfg.key;
OpenAI.baseUrl = _cfg.url;
OpenAI.apiKey = vn.value.key;
OpenAI.baseUrl = vn.value.url;
}

static void switchToDefault() {
static void switchToDefault(BuildContext context) {
final cfg = Stores.config.fetch(ChatConfig.defaultId);
if (cfg != null) {
current = cfg;
setTo(cfg, context);
} else {
current = ChatConfig.defaultOne;
setTo(ChatConfig.defaultOne, context);
Loggers.app.warning('Default config not found');
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"empty": "Empty",
"emptyFields": "{fields} is empty",
"error": "Error",
"failed": "Failed",
"file": "File",
"fileNotFound": "File({file}) not found",
"fileTooLarge": "File too large: {size}",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"empty": "空",
"emptyFields": "{fields} 为空",
"error": "错误",
"failed": "失败",
"file": "文件",
"fileNotFound": "文件({file})未能找到",
"fileTooLarge": "文件过大:{size}",
Expand Down
109 changes: 86 additions & 23 deletions lib/view/page/home/appbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ CustomAppBar _buildAppBar(BuildContext context) {
builder: (_, __) {
final entity = _curChat;
if (entity == null) return Text(l10n.empty);
final len = '${entity.items.length} ${l10n.message}';
final time = entity.items.lastOrNull?.createdAt
.difference(DateTime.now())
.toAgoStr;
return AnimatedSwitcher(
duration: _durationMedium,
switchInCurve: Easing.standardDecelerate,
Expand All @@ -25,39 +21,80 @@ CustomAppBar _buildAppBar(BuildContext context) {
child: SizedBox(
key: Key(entity.id),
width: (_media?.size.width ?? 300) * 0.5,
child: RichText(
maxLines: 2,
child: Text(
_curChat?.name ?? l10n.untitled,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
text: TextSpan(
children: [
TextSpan(
text: _curChat?.name ?? l10n.untitled,
style: UIs.text13
.copyWith(color: UIs.textColor.fromBool(context.isDark)),
),
TextSpan(
text: '\n$len · ${time ?? l10n.empty}',
style: UIs.text11Grey,
),
],
),
style: UIs.text15,
),
),
);
},
);

final subtitle = ValBuilder(
listenable: OpenAICfg.vn,
builder: (val) {
final text = val.name.isEmpty ? l10n.defaulT : val.name;
return AnimatedSwitcher(
duration: _durationMedium,
switchInCurve: Easing.standardDecelerate,
switchOutCurve: Easing.standardDecelerate,
transitionBuilder: (child, animation) => SlideTransitionX(
position: animation,
child: FadeTransition(
opacity: animation,
child: child,
),
),
// Use a SizedBox to avoid the title jumping when switching chats.
child: Text(
key: ValueKey(val),
'$text·${val.model}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: UIs.text12Grey,
),
);
},
);

return CustomAppBar(
centerTitle: false,
title: GestureDetector(
onLongPress: () => Routes.debug.go(
context,
args: DebugPageArgs(
notifier: Pros.debug.widgets,
onClear: Pros.debug.clear,
title: 'Logs(${Build.build})'),
notifier: Pros.debug.widgets,
onClear: Pros.debug.clear,
title: 'Logs(${Build.build})',
),
),
onTap: () => _onSwitchModel(context),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title,
SizedBox(
width: (_media?.size.width ?? 300) * 0.5,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
subtitle,
const Icon(
Icons.keyboard_arrow_down,
size: 15,
color: Colors.grey,
)
],
),
),
],
),
child: title,
),
actions: [
ValueListenableBuilder(
Expand All @@ -67,3 +104,29 @@ CustomAppBar _buildAppBar(BuildContext context) {
],
);
}

void _onSwitchModel(BuildContext context) async {
final cfg = OpenAICfg.current;
if (cfg.key.isEmpty) {
context.showRoundDialog(
title: l10n.attention,
child: Text(l10n.needOpenAIKey),
actions: Btns.oks(onTap: context.pop),
);
return;
}
final models = OpenAICfg.models.value;
final modelStrs = List<String>.from(models);
modelStrs.removeWhere((element) => !element.startsWith('gpt'));
if (modelStrs.isEmpty) {
modelStrs.addAll(models);
}

final model = await context.showPickSingleDialog(
items: modelStrs,
initial: cfg.model,
title: l10n.model,
);
if (model == null) return;
OpenAICfg.setTo(cfg.copyWith(model: model), context);
}
2 changes: 1 addition & 1 deletion lib/view/page/home/enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum HomePageEnum {
: null,
);
if (select == null) return;
OpenAICfg.current = select;
OpenAICfg.setTo(select, context);
},
icon: const Icon(Icons.switch_account),
tooltip: l10n.profile,
Expand Down
11 changes: 7 additions & 4 deletions lib/view/page/home/url_scheme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,13 @@ abstract final class AppLink {
Loggers.app.warning(msg);
return true;
}
OpenAICfg.current = OpenAICfg.current.copyWith(
url: openAiUrl,
key: openAiKey,
model: openAiModel,
OpenAICfg.setTo(
OpenAICfg.current.copyWith(
url: openAiUrl,
key: openAiKey,
model: openAiModel,
),
context,
);
return true;
default:
Expand Down
Loading

0 comments on commit 8091260

Please sign in to comment.