Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: scroll bottom after switching chat #160

Merged
merged 1 commit into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/data/store/setting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,7 @@ class SettingStore extends PersistentStore {
late final avatar = property('avatar', '🧐');

late final introVer = property('introVer', 0);

/// Auto scroll to the bottom after switching chat.
late final scrollAfterSwitch = property('scrollAfterSwitch', false);
}
2 changes: 2 additions & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Neuer Chat",
"noDuplication": "Keine Duplikate",
"notSupported": "{val} wird nicht unterstützt",
"onMsgCome": "Wenn neue Nachrichten vorhanden sind",
"onSwitchChat": "Beim Wechseln der Konversation",
"onlyRestoreHistory": "Nur Chat-Verlauf wiederherstellen (API-URL und geheimer Schlüssel werden nicht wiederhergestellt)",
"onlySyncOnLaunch": "Nur beim Start synchronisieren",
"other": "Andere",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "New chat",
"noDuplication": "No duplication",
"notSupported": "{val} is not supported",
"onMsgCome": "When there are new messages",
"onSwitchChat": "When switching conversations",
"onlyRestoreHistory": "Only restore histories (exclude api url / secret key)",
"onlySyncOnLaunch": "Only sync on launch",
"other": "Other",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Nuevo chat",
"noDuplication": "Sin duplicados",
"notSupported": "{val} no es compatible",
"onMsgCome": "Cuando hay nuevos mensajes",
"onSwitchChat": "Al cambiar de conversación",
"onlyRestoreHistory": "Solo restaurar historial de chat (no restaurar URL de API ni clave secreta)",
"onlySyncOnLaunch": "Sincronizar solo al iniciar",
"other": "Otro",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Nouveau chat",
"noDuplication": "Pas de doublon",
"notSupported": "{val} n'est pas pris en charge",
"onMsgCome": "Lorsqu'il y a de nouveaux messages",
"onSwitchChat": "Lors du changement de conversation",
"onlyRestoreHistory": "Restaurer uniquement l'historique des chats (ne pas restaurer l'URL de l'API et la clé secrète)",
"onlySyncOnLaunch": "Synchroniser uniquement au lancement",
"other": "Autre",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_id.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Obrolan baru",
"noDuplication": "Tidak ada duplikasi",
"notSupported": "{val} tidak didukung",
"onMsgCome": "Ketika ada pesan baru",
"onSwitchChat": "Saat beralih percakapan",
"onlyRestoreHistory": "Hanya pulihkan riwayat obrolan (tidak memulihkan URL API dan Kunci Rahasia)",
"onlySyncOnLaunch": "Hanya sinkronkan saat peluncuran",
"other": "Lainnya",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_ja.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "新しいチャット",
"noDuplication": "重複はありません",
"notSupported": "{val}はサポートされていません",
"onMsgCome": "新しいメッセージがある時",
"onSwitchChat": "会話を切り替える時",
"onlyRestoreHistory": "チャット履歴のみを復元(API URLと秘密キーは復元しない)",
"onlySyncOnLaunch": "起動時のみ同期",
"other": "その他",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_nl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Nieuwe chat",
"noDuplication": "Geen duplicaten",
"notSupported": "{val} wordt niet ondersteund",
"onMsgCome": "Wanneer er nieuwe berichten zijn",
"onSwitchChat": "Bij het wisselen van gesprekken",
"onlyRestoreHistory": "Alleen chatgeschiedenis herstellen (API-URL en geheime sleutel niet herstellen)",
"onlySyncOnLaunch": "Alleen synchroniseren bij opstarten",
"other": "Overig",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_pt.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Novo chat",
"noDuplication": "Sem duplicação",
"notSupported": "{val} não é suportado",
"onMsgCome": "Quando houver novas mensagens",
"onSwitchChat": "Ao alternar conversas",
"onlyRestoreHistory": "Restaurar apenas o histórico de chat (não restaurar URL da API e chave secreta)",
"onlySyncOnLaunch": "Sincronizar apenas na inicialização",
"other": "Outro",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_ru.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Новый чат",
"noDuplication": "Нет дубликатов",
"notSupported": "{val} не поддерживается",
"onMsgCome": "Когда есть новые сообщения",
"onSwitchChat": "При переключении разговора",
"onlyRestoreHistory": "Восстановить только историю чатов (не восстанавливать URL API и секретный ключ)",
"onlySyncOnLaunch": "Синхронизировать только при запуске",
"other": "Другое",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_tr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "Yeni sohbet",
"noDuplication": "Yineleme yok",
"notSupported": "{val} desteklenmiyor",
"onMsgCome": "Yeni mesajlar olduğunda",
"onSwitchChat": "Konuşmalar arasında geçiş yaparken",
"onlyRestoreHistory": "Sadece sohbet geçmişini geri yükle (API URL'sini ve gizli anahtarı geri yükleme)",
"onlySyncOnLaunch": "Sadece başlatırken senkronize et",
"other": "Diğer",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "新建聊天",
"noDuplication": "没有重复项目",
"notSupported": "{val} 不支持",
"onMsgCome": "当有新消息",
"onSwitchChat": "当切换对话",
"onlyRestoreHistory": "仅恢复历史聊天(不恢复 API Url 和 Secret Key)",
"onlySyncOnLaunch": "仅在启动时同步",
"other": "其他",
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_zh_tw.arb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"newChat": "新建聊天",
"noDuplication": "沒有重複項目",
"notSupported": "{val} 不支援",
"onMsgCome": "當有新訊息",
"onSwitchChat": "當切換對話時",
"onlyRestoreHistory": "僅恢復歷史聊天(不恢復 API Url 和 Secret Key)",
"onlySyncOnLaunch": "僅在啟動時同步",
"other": "其他",
Expand Down
26 changes: 19 additions & 7 deletions lib/view/page/home/ctrl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ part of 'home.dart';

void _switchChat([String? id]) {
id ??= _allHistories.keys.firstOrNull ?? _newChat().id;

final chat = _allHistories[id];
if (chat == null) {
final msg = 'Switch Chat($id) not found';
Loggers.app.warning(msg);
return;
}

_curChatId = id;
_chatItemRNMap.clear();
_chatRN.notify();
Expand All @@ -10,14 +18,10 @@ void _switchChat([String? id]) {
Future.delayed(_durationMedium, () {
// Different chats have different height
_chatFabRN.notify();
if (Stores.setting.scrollAfterSwitch.fetch()) {
_scrollBottom();
}
});

final chat = _allHistories[id];
if (chat == null) {
final msg = 'Switch Chat($id) not found';
Loggers.app.warning(msg);
return;
}
}

void _switchPreviousChat() {
Expand Down Expand Up @@ -593,3 +597,11 @@ Future<bool> _askToolConfirm(
}
return permitted == true;
}

void _onChatScroll() {
Funcs.throttle(_chatFabRN.notify, id: 'chat_fab_rn', duration: 30);
}

void _onIsWideChanged() {
_curPage.value = HomePageEnum.chat;
}
12 changes: 3 additions & 9 deletions lib/view/page/home/var.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
part of 'home.dart';

final _inputCtrl = TextEditingController();
final _chatScrollCtrl = ScrollController()
..addListener(() {
Funcs.throttle(_chatFabRN.notify, id: 'chat_fab_rn', duration: 30);
});
final _chatScrollCtrl = ScrollController()..addListener(_onChatScroll);
final _historyScrollCtrl = ScrollController()
..addListener(_locateHistoryListener);
final _pageCtrl = PageController(initialPage: _curPage.value.index);
Expand All @@ -31,7 +28,7 @@ final _chatFabRN = RNode();
final _homeBottomRN = RNode();

var _allHistories = <String, ChatHistory>{};
String _curChatId = 'fake-non-exist-id';
var _curChatId = 'fake-non-exist-id';
ChatHistory? get _curChat => _allHistories[_curChatId];

/// [ChatHistory.id] or [ChatHistoryItem.id]
Expand All @@ -43,10 +40,7 @@ final _curPage = HomePageEnum.chat.vn;
final _imeFocus = FocusNode();

MediaQueryData? _media;
final _isWide = false.vn
..addListener(() {
_curPage.value = HomePageEnum.chat;
});
final _isWide = false.vn..addListener(_onIsWideChanged);

const _boxShadow = [
BoxShadow(
Expand Down
23 changes: 20 additions & 3 deletions lib/view/page/setting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class _SettingPageState extends State<SettingPage> {
if (isMobile) _buildScrollSwitchChat(),
//_buildFontSize(),
_buildGenTitle(),
_buildScrollBottom(),
_buildAutoScrollBottom(),
_buildSoftWrap(),
//_buildCalcTokenLen(),
//_buildReplay(),
Expand Down Expand Up @@ -246,10 +246,20 @@ class _SettingPageState extends State<SettingPage> {
);
}

Widget _buildScrollBottom() {
return ListTile(
Widget _buildAutoScrollBottom() {
return ExpandTile(
leading: const Icon(Icons.keyboard_arrow_down),
title: Text(l10n.autoScrollBottom),
children: [
_buildScrollBottomOnMsg(),
_buildScrollAfterSwitch(),
],
);
}

Widget _buildScrollBottomOnMsg() {
return ListTile(
title: Text(l10n.onMsgCome),
trailing: StoreSwitch(prop: _store.scrollBottom),
);
}
Expand Down Expand Up @@ -411,4 +421,11 @@ class _SettingPageState extends State<SettingPage> {
trailing: StoreSwitch(prop: _store.hideTitleBar),
);
}

Widget _buildScrollAfterSwitch() {
return ListTile(
title: Text(l10n.onSwitchChat),
trailing: StoreSwitch(prop: _store.scrollAfterSwitch),
);
}
}
Loading