feat: logout (#497)

* feat: logout

* update api type
This commit is contained in:
My-Responsitories
2025-03-23 13:46:26 +08:00
committed by GitHub
parent 7c3e3cb1f8
commit d6587cf3b6
11 changed files with 139 additions and 129 deletions

View File

@@ -13,6 +13,7 @@ import 'package:PiliPlus/models/github/latest.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/utils.dart';
import '../../utils/cache_manage.dart';
import '../mine/controller.dart';
class AboutPage extends StatefulWidget {
const AboutPage({super.key, this.showAppBar});
@@ -302,6 +303,9 @@ Commit Hash: ${BuildConfig.commitHash}''',
.putAll(res)
.then((_) => Accounts.refresh())
.then((_) {
MineController.anonymity.value =
!Accounts.get(AccountType.heartbeat)
.isLogin;
if (Accounts.main.isLogin) {
return LoginUtils.onLoginMain();
}

View File

@@ -646,7 +646,9 @@ class LoginPageController extends GetxController
LoginAccount(BiliCookieJar.fromList(cookieInfo),
tokenInfo['access_token'], tokenInfo['refresh_token'])
.onChange(),
AnonymousAccount().logout().then((i) => Request.buvidActive(i))
AnonymousAccount()
.delete()
.then((_) => Request.buvidActive(AnonymousAccount()))
]);
if (Accounts.main.isLogin) {
SmartDialog.showToast('登录成功');

View File

@@ -35,7 +35,7 @@ class MainController extends GetxController {
late int homeIndex = -1;
late DynamicBadgeMode msgBadgeMode = GStorage.msgBadgeMode;
late List<MsgUnReadType> msgUnReadTypes = GStorage.msgUnReadTypeV2;
late Set<MsgUnReadType> msgUnReadTypes = GStorage.msgUnReadTypeV2.toSet();
late final RxString msgUnReadCount = ''.obs;
late int lastCheckUnreadAt = 0;
@@ -83,7 +83,7 @@ class MainController extends GetxController {
try {
bool shouldCheckPM = msgUnReadTypes.contains(MsgUnReadType.pm);
bool shouldCheckFeed =
([...msgUnReadTypes]..remove(MsgUnReadType.pm)).isNotEmpty;
shouldCheckPM ? msgUnReadTypes.length > 1 : msgUnReadTypes.isNotEmpty;
List res = await Future.wait([
if (shouldCheckPM) _queryPMUnread(),
if (shouldCheckFeed) _queryMsgFeedUnread(),

View File

@@ -7,13 +7,15 @@ import 'package:PiliPlus/pages/setting/privacy_setting.dart';
import 'package:PiliPlus/pages/setting/recommend_setting.dart';
import 'package:PiliPlus/pages/setting/style_setting.dart';
import 'package:PiliPlus/pages/setting/video_setting.dart';
import 'package:PiliPlus/utils/accounts/account.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/login.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'widgets/multi_select_dialog.dart';
class _SettingsModel {
final String name;
final String title;
@@ -37,7 +39,7 @@ class SettingPage extends StatefulWidget {
class _SettingPageState extends State<SettingPage> {
late String _type = 'privacySetting';
final RxBool _isLogin = Accounts.main.isLogin.obs;
final RxBool _noAccount = Accounts.accountMode.isEmpty.obs;
TextStyle get _titleStyle => Theme.of(context).textTheme.titleMedium!;
TextStyle get _subTitleStyle => Theme.of(context)
.textTheme
@@ -173,8 +175,15 @@ class _SettingPageState extends State<SettingPage> {
leading: const Icon(Icons.switch_account_outlined),
title: const Text('设置账号模式'),
),
// TODO: 多账号登出
_buildLoginItem,
Obx(
() => _noAccount.value
? const SizedBox.shrink()
: ListTile(
leading: const Icon(Icons.logout_outlined),
onTap: () => _logoutDialog(context),
title: Text('退出登录', style: _titleStyle),
),
),
ListTile(
tileColor: _getTileColor(_items.last.name),
onTap: () => _toPage(_items.last.name),
@@ -186,70 +195,69 @@ class _SettingPageState extends State<SettingPage> {
);
}
Widget get _buildLoginItem => Obx(
() => _isLogin.value.not
? const SizedBox.shrink()
: ListTile(
leading: const Icon(Icons.logout_outlined),
onTap: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content: const Text('确认要退出登录吗'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'点错了',
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
),
),
),
TextButton(
onPressed: () {
Get.back();
_isLogin.value = false;
LoginUtils.onLogoutMain();
final account = Accounts.main;
Accounts.accountMode
.removeWhere((_, a) => a == account);
account.logout().then((_) => Accounts.refresh());
},
child: Text(
'仅登出',
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
),
),
TextButton(
onPressed: () async {
SmartDialog.showLoading();
final res = await LoginHttp.logout(Accounts.main);
if (res['status']) {
await Accounts.main.logout();
await LoginUtils.onLogoutMain();
_isLogin.value = false;
SmartDialog.dismiss();
Get.back();
} else {
SmartDialog.dismiss();
SmartDialog.showToast(res['msg'].toString());
}
},
child: const Text('确认'),
)
],
);
},
);
},
title: Text('退出登录', style: _titleStyle),
Future<void> _logoutDialog(BuildContext context) async {
final result = await showDialog<Set<LoginAccount>>(
context: context,
builder: (context) {
return MultiSelectDialog<LoginAccount>(
title: '选择要登出的账号uid',
initValues: Iterable.empty(),
values: {for (var i in Accounts.account.values) i: i.mid.toString()},
);
},
);
if (!context.mounted || result.isNullOrEmpty) return;
Future<void> logout() {
_noAccount.value = result!.length == Accounts.account.length;
return Accounts.deleteAll(result);
}
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content: Text(
"确认要退出以下账号登录吗\n\n${result!.map((i) => i.mid.toString()).join('\n')}"),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'点错了',
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
),
),
),
);
TextButton(
onPressed: () {
Get.back();
logout();
},
child: Text(
'仅登出',
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
),
TextButton(
onPressed: () async {
SmartDialog.showLoading();
final res = await LoginHttp.logout(Accounts.main);
if (res['status']) {
SmartDialog.dismiss();
logout();
Get.back();
} else {
SmartDialog.dismiss();
SmartDialog.showToast(res['msg'].toString());
}
},
child: const Text('确认'),
)
],
);
});
}
Widget get _buildSearchItem => Padding(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 5),

View File

@@ -344,15 +344,13 @@ List<SettingsModel> get styleSettings => [
SettingsModel(
settingsType: SettingsType.normal,
onTap: (setState) async {
List<MsgUnReadType>? result = await showDialog(
final result = await showDialog<Set<MsgUnReadType>>(
context: Get.context!,
builder: (context) {
return MultiSelectDialog<MsgUnReadType>(
title: '消息未读类型',
initValues: GStorage.msgUnReadTypeV2,
values: MsgUnReadType.values.map((e) {
return {'title': e.title, 'value': e};
}).toList(),
values: {for (var i in MsgUnReadType.values) i: i.title},
);
},
);

View File

@@ -2,16 +2,15 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
class MultiSelectDialog<T> extends StatefulWidget {
final List<T> initValues;
final Iterable<T> initValues;
final String title;
final List<dynamic> values;
final Map<T, String> values;
const MultiSelectDialog({
super.key,
required this.initValues,
required this.values,
required this.title,
});
const MultiSelectDialog(
{super.key,
required this.initValues,
required this.values,
required this.title});
@override
State<MultiSelectDialog<T>> createState() => _MultiSelectDialogState<T>();
@@ -36,30 +35,24 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(
widget.values.length,
(index) {
bool isChecked =
_tempValues.contains(widget.values[index]['value']);
return CheckboxListTile(
dense: true,
value: isChecked,
controlAffinity: ListTileControlAffinity.leading,
title: Text(
widget.values[index]['title'],
style: Theme.of(context).textTheme.titleMedium!,
),
onChanged: (value) {
if (isChecked) {
_tempValues.remove(widget.values[index]['value']);
} else {
_tempValues.add(widget.values[index]['value']);
}
setState(() {});
},
);
},
),
children: widget.values.entries.map((i) {
bool isChecked = _tempValues.contains(i.key);
return CheckboxListTile(
dense: true,
value: isChecked,
controlAffinity: ListTileControlAffinity.leading,
title: Text(
i.value,
style: Theme.of(context).textTheme.titleMedium!,
),
onChanged: (value) {
isChecked
? _tempValues.remove(i.key)
: _tempValues.add(i.key);
setState(() {});
},
);
}).toList(),
),
);
}),
@@ -75,7 +68,7 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
),
),
TextButton(
onPressed: () => Get.back(result: _tempValues.toList()),
onPressed: () => Get.back(result: _tempValues),
child: const Text('确定'),
),
],