2024-11-16 13:54:36 +08:00
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:gap/gap.dart';
|
|
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import 'package:material_symbols_icons/symbols.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
2025-02-20 22:09:05 +08:00
|
|
|
import 'package:surface/providers/config.dart';
|
2024-11-16 13:54:36 +08:00
|
|
|
import 'package:surface/providers/sn_network.dart';
|
2024-12-11 23:23:11 +08:00
|
|
|
import 'package:surface/providers/userinfo.dart';
|
2024-11-16 13:54:36 +08:00
|
|
|
import 'package:surface/types/realm.dart';
|
2024-12-05 22:22:38 +08:00
|
|
|
import 'package:surface/widgets/app_bar_leading.dart';
|
2024-11-16 13:54:36 +08:00
|
|
|
import 'package:surface/widgets/dialog.dart';
|
|
|
|
import 'package:surface/widgets/loading_indicator.dart';
|
2025-01-21 20:35:04 +08:00
|
|
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
2025-02-20 22:09:05 +08:00
|
|
|
import 'package:surface/widgets/realm/realm_item.dart';
|
2024-12-11 23:23:11 +08:00
|
|
|
import 'package:surface/widgets/unauthorized_hint.dart';
|
2024-11-16 13:54:36 +08:00
|
|
|
|
|
|
|
class RealmScreen extends StatefulWidget {
|
|
|
|
const RealmScreen({super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<RealmScreen> createState() => _RealmScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _RealmScreenState extends State<RealmScreen> {
|
|
|
|
bool _isBusy = false;
|
|
|
|
bool _isCompactView = false;
|
|
|
|
|
|
|
|
List<SnRealm>? _realms;
|
|
|
|
|
|
|
|
Future<void> _fetchRealms() async {
|
2024-12-08 15:25:59 +08:00
|
|
|
final ua = context.read<UserProvider>();
|
|
|
|
if (!ua.isAuthorized) return;
|
|
|
|
|
2024-11-16 13:54:36 +08:00
|
|
|
setState(() => _isBusy = true);
|
|
|
|
try {
|
|
|
|
final sn = context.read<SnNetworkProvider>();
|
|
|
|
final resp = await sn.client.get('/cgi/id/realms/me/available');
|
|
|
|
_realms = List<SnRealm>.from(
|
|
|
|
resp.data?.map((e) => SnRealm.fromJson(e)) ?? [],
|
|
|
|
);
|
|
|
|
} catch (err) {
|
|
|
|
if (mounted) context.showErrorDialog(err);
|
|
|
|
} finally {
|
|
|
|
setState(() => _isBusy = false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _deleteRealm(SnRealm realm) async {
|
|
|
|
final confirm = await context.showConfirmDialog(
|
|
|
|
'realmDelete'.tr(args: ['#${realm.alias}']),
|
|
|
|
'realmDeleteDescription'.tr(),
|
|
|
|
);
|
|
|
|
if (!confirm) return;
|
|
|
|
|
|
|
|
if (!mounted) return;
|
|
|
|
final sn = context.read<SnNetworkProvider>();
|
|
|
|
|
|
|
|
setState(() => _isBusy = true);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await sn.client.delete('/cgi/id/realms/${realm.alias}');
|
|
|
|
if (!mounted) return;
|
|
|
|
context.showSnackbar('realmDeleted'.tr(args: ['#${realm.alias}']));
|
|
|
|
_fetchRealms();
|
|
|
|
} catch (err) {
|
|
|
|
if (!mounted) return;
|
|
|
|
context.showErrorDialog(err);
|
|
|
|
} finally {
|
|
|
|
setState(() => _isBusy = false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
2025-02-20 22:09:05 +08:00
|
|
|
_isCompactView = context.read<ConfigProvider>().realmCompactView;
|
2024-11-16 13:54:36 +08:00
|
|
|
_fetchRealms();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-12-08 15:25:59 +08:00
|
|
|
final ua = context.read<UserProvider>();
|
|
|
|
|
|
|
|
if (!ua.isAuthorized) {
|
2025-01-21 20:35:04 +08:00
|
|
|
return AppScaffold(
|
2024-12-08 15:25:59 +08:00
|
|
|
appBar: AppBar(
|
|
|
|
leading: AutoAppBarLeading(),
|
|
|
|
title: Text('screenRealm').tr(),
|
|
|
|
),
|
|
|
|
body: Center(
|
|
|
|
child: UnauthorizedHint(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2024-11-16 13:54:36 +08:00
|
|
|
|
2025-01-21 20:35:04 +08:00
|
|
|
return AppScaffold(
|
2024-11-16 13:54:36 +08:00
|
|
|
appBar: AppBar(
|
2024-12-05 22:22:38 +08:00
|
|
|
leading: AutoAppBarLeading(),
|
2024-11-16 13:54:36 +08:00
|
|
|
title: Text('screenRealm').tr(),
|
|
|
|
actions: [
|
2025-02-11 21:31:53 +08:00
|
|
|
IconButton(
|
|
|
|
icon: const Icon(Symbols.globe),
|
|
|
|
onPressed: () {
|
|
|
|
GoRouter.of(context).pushNamed('realmDiscovery');
|
|
|
|
},
|
|
|
|
),
|
2024-11-16 13:54:36 +08:00
|
|
|
IconButton(
|
2024-12-11 23:23:11 +08:00
|
|
|
icon: !_isCompactView ? const Icon(Symbols.view_list) : const Icon(Symbols.view_module),
|
2024-11-16 13:54:36 +08:00
|
|
|
onPressed: () {
|
|
|
|
setState(() => _isCompactView = !_isCompactView);
|
2025-02-20 22:09:05 +08:00
|
|
|
context.read<ConfigProvider>().realmCompactView = _isCompactView;
|
2024-11-16 13:54:36 +08:00
|
|
|
},
|
|
|
|
),
|
2024-11-24 20:23:06 +08:00
|
|
|
const Gap(8),
|
2024-11-16 13:54:36 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
floatingActionButton: FloatingActionButton(
|
|
|
|
child: const Icon(Symbols.group_add),
|
|
|
|
onPressed: () {
|
|
|
|
GoRouter.of(context).pushNamed('realmManage');
|
|
|
|
},
|
|
|
|
),
|
|
|
|
body: Column(
|
|
|
|
children: [
|
|
|
|
LoadingIndicator(isActive: _isBusy),
|
|
|
|
Expanded(
|
2025-01-21 20:50:07 +08:00
|
|
|
child: MediaQuery.removePadding(
|
|
|
|
context: context,
|
|
|
|
removeTop: true,
|
|
|
|
child: RefreshIndicator(
|
|
|
|
onRefresh: _fetchRealms,
|
|
|
|
child: ListView.builder(
|
|
|
|
itemCount: _realms?.length ?? 0,
|
|
|
|
itemBuilder: (context, idx) {
|
|
|
|
final realm = _realms![idx];
|
|
|
|
|
2025-02-20 22:09:05 +08:00
|
|
|
return RealmItemWidget(
|
2025-02-20 23:44:28 +08:00
|
|
|
showPopularity: false,
|
2025-02-20 22:09:05 +08:00
|
|
|
item: realm,
|
|
|
|
isListView: _isCompactView,
|
|
|
|
actionListView: [
|
|
|
|
PopupMenuItem(
|
|
|
|
child: Row(
|
2025-01-21 20:50:07 +08:00
|
|
|
children: [
|
2025-02-20 22:09:05 +08:00
|
|
|
const Icon(Symbols.edit),
|
|
|
|
const Gap(16),
|
|
|
|
Text('edit').tr(),
|
2025-01-21 20:50:07 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
onTap: () {
|
|
|
|
GoRouter.of(context).pushNamed(
|
2025-02-20 22:09:05 +08:00
|
|
|
'realmManage',
|
|
|
|
queryParameters: {'editing': realm.alias},
|
2025-02-16 19:50:34 +08:00
|
|
|
).then((value) {
|
2025-02-20 22:09:05 +08:00
|
|
|
if (value != null) {
|
2025-02-16 19:50:34 +08:00
|
|
|
_fetchRealms();
|
|
|
|
}
|
|
|
|
});
|
2025-01-21 20:50:07 +08:00
|
|
|
},
|
|
|
|
),
|
2025-02-20 22:09:05 +08:00
|
|
|
PopupMenuItem(
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
const Icon(Symbols.delete),
|
|
|
|
const Gap(16),
|
|
|
|
Text('delete').tr(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
onTap: () {
|
|
|
|
_deleteRealm(realm);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
onUpdate: _fetchRealms,
|
|
|
|
);
|
2025-01-21 20:50:07 +08:00
|
|
|
},
|
|
|
|
),
|
2024-11-16 13:54:36 +08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|