✨ Complete the realm system
This commit is contained in:
parent
0b9439262c
commit
22c2a80650
@ -87,6 +87,8 @@
|
|||||||
"realmDescriptionLabel": "Realm Description",
|
"realmDescriptionLabel": "Realm Description",
|
||||||
"realmPublicLabel": "It's public",
|
"realmPublicLabel": "It's public",
|
||||||
"realmCommunityLabel": "It's community realm",
|
"realmCommunityLabel": "It's community realm",
|
||||||
|
"realmMember": "Member",
|
||||||
|
"realmManage": "Realm Manage",
|
||||||
"chatNew": "New Chat",
|
"chatNew": "New Chat",
|
||||||
"chatNewCreate": "Create a channel",
|
"chatNewCreate": "Create a channel",
|
||||||
"chatNewJoin": "Join a exists channel",
|
"chatNewJoin": "Join a exists channel",
|
||||||
|
@ -21,8 +21,10 @@ import 'package:solian/screens/posts/moment_editor.dart';
|
|||||||
import 'package:solian/screens/posts/screen.dart';
|
import 'package:solian/screens/posts/screen.dart';
|
||||||
import 'package:solian/screens/auth/signin.dart';
|
import 'package:solian/screens/auth/signin.dart';
|
||||||
import 'package:solian/screens/realms/realm.dart';
|
import 'package:solian/screens/realms/realm.dart';
|
||||||
|
import 'package:solian/screens/realms/realm_manage.dart';
|
||||||
import 'package:solian/screens/realms/realm_editor.dart';
|
import 'package:solian/screens/realms/realm_editor.dart';
|
||||||
import 'package:solian/screens/realms/realm_list.dart';
|
import 'package:solian/screens/realms/realm_list.dart';
|
||||||
|
import 'package:solian/screens/realms/realm_member.dart';
|
||||||
import 'package:solian/screens/users/userinfo.dart';
|
import 'package:solian/screens/users/userinfo.dart';
|
||||||
import 'package:solian/utils/theme.dart';
|
import 'package:solian/utils/theme.dart';
|
||||||
import 'package:solian/widgets/empty.dart';
|
import 'package:solian/widgets/empty.dart';
|
||||||
@ -103,6 +105,16 @@ abstract class SolianRouter {
|
|||||||
realm: state.uri.queryParameters['realm'],
|
realm: state.uri.queryParameters['realm'],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/realms/:realm/manage',
|
||||||
|
name: 'realms.manage',
|
||||||
|
builder: (context, state) => RealmManageScreen(realm: state.extra as Realm),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/realms/:realm/member',
|
||||||
|
name: 'realms.member',
|
||||||
|
builder: (context, state) => RealmMemberScreen(realm: state.extra as Realm),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/realms/:realm/posts/:dataset/:alias',
|
path: '/realms/:realm/posts/:dataset/:alias',
|
||||||
name: 'realms.posts.details',
|
name: 'realms.posts.details',
|
||||||
|
@ -6,7 +6,6 @@ import 'package:solian/providers/realm.dart';
|
|||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/screens/chat/chat_list.dart';
|
import 'package:solian/screens/chat/chat_list.dart';
|
||||||
import 'package:solian/screens/explore.dart';
|
import 'package:solian/screens/explore.dart';
|
||||||
import 'package:solian/screens/realms/realm_member.dart';
|
|
||||||
import 'package:solian/utils/theme.dart';
|
import 'package:solian/utils/theme.dart';
|
||||||
import 'package:solian/widgets/scaffold.dart';
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ class _RealmWidgetState extends State<RealmWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return DefaultTabController(
|
return DefaultTabController(
|
||||||
length: 3,
|
length: 2,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
TabBar(
|
||||||
@ -90,7 +89,6 @@ class _RealmWidgetState extends State<RealmWidget> {
|
|||||||
tabs: const [
|
tabs: const [
|
||||||
Tab(icon: Icon(Icons.newspaper)),
|
Tab(icon: Icon(Icons.newspaper)),
|
||||||
Tab(icon: Icon(Icons.message)),
|
Tab(icon: Icon(Icons.message)),
|
||||||
Tab(icon: Icon(Icons.supervisor_account))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -98,11 +96,6 @@ class _RealmWidgetState extends State<RealmWidget> {
|
|||||||
children: [
|
children: [
|
||||||
ExplorePostWidget(realm: widget.alias),
|
ExplorePostWidget(realm: widget.alias),
|
||||||
ChatListWidget(realm: widget.alias),
|
ChatListWidget(realm: widget.alias),
|
||||||
_realm.focusRealm != null
|
|
||||||
? RealmMemberWidget(realm: _realm.focusRealm!)
|
|
||||||
: const Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -127,8 +120,9 @@ class RealmManageAction extends StatelessWidget {
|
|||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final did = await SolianRouter.router.pushNamed(
|
final did = await SolianRouter.router.pushNamed(
|
||||||
'realms.editor',
|
'realms.manage',
|
||||||
extra: realm,
|
extra: realm,
|
||||||
|
pathParameters: {'realm': realm.alias},
|
||||||
);
|
);
|
||||||
if (did == true) onUpdate();
|
if (did == true) onUpdate();
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@ import 'package:solian/models/realm.dart';
|
|||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/utils/service_url.dart';
|
import 'package:solian/utils/service_url.dart';
|
||||||
|
import 'package:solian/utils/theme.dart';
|
||||||
import 'package:solian/widgets/exts.dart';
|
import 'package:solian/widgets/exts.dart';
|
||||||
import 'package:solian/widgets/scaffold.dart';
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
@ -117,6 +118,7 @@ class _RealmEditorScreenState extends State<RealmEditorScreen> {
|
|||||||
child: Text(AppLocalizations.of(context)!.apply.toUpperCase()),
|
child: Text(AppLocalizations.of(context)!.apply.toUpperCase()),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_isSubmitting ? const LinearProgressIndicator().animate().scaleX() : Container(),
|
_isSubmitting ? const LinearProgressIndicator().animate().scaleX() : Container(),
|
||||||
|
119
lib/screens/realms/realm_manage.dart
Normal file
119
lib/screens/realms/realm_manage.dart
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:solian/models/realm.dart';
|
||||||
|
import 'package:solian/providers/auth.dart';
|
||||||
|
import 'package:solian/router.dart';
|
||||||
|
import 'package:solian/widgets/realms/realm_deletion.dart';
|
||||||
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
class RealmManageScreen extends StatefulWidget {
|
||||||
|
final Realm realm;
|
||||||
|
|
||||||
|
const RealmManageScreen({super.key, required this.realm});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RealmManageScreen> createState() => _RealmManageScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RealmManageScreenState extends State<RealmManageScreen> {
|
||||||
|
bool _isOwned = false;
|
||||||
|
|
||||||
|
void promptLeaveChannel() async {
|
||||||
|
final did = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => RealmDeletion(
|
||||||
|
realm: widget.realm,
|
||||||
|
isOwned: _isOwned,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (did == true && SolianRouter.router.canPop()) {
|
||||||
|
SolianRouter.router.pop('disposed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
final auth = context.read<AuthProvider>();
|
||||||
|
final prof = await auth.getProfiles();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isOwned = prof['id'] == widget.realm.accountId;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final authorizedItems = [
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.settings),
|
||||||
|
title: Text(AppLocalizations.of(context)!.settings),
|
||||||
|
onTap: () async {
|
||||||
|
SolianRouter.router.pushNamed('realms.editor', extra: widget.realm).then((did) {
|
||||||
|
if (did == true) {
|
||||||
|
if (SolianRouter.router.canPop()) SolianRouter.router.pop('refresh');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
return IndentScaffold(
|
||||||
|
title: AppLocalizations.of(context)!.realmManage,
|
||||||
|
hideDrawer: true,
|
||||||
|
noSafeArea: true,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const CircleAvatar(
|
||||||
|
radius: 24,
|
||||||
|
backgroundColor: Colors.teal,
|
||||||
|
child: Icon(Icons.tag, color: Colors.white),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
|
Text(widget.realm.name, style: Theme.of(context).textTheme.bodyLarge),
|
||||||
|
Text(widget.realm.description, style: Theme.of(context).textTheme.bodySmall),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(thickness: 0.3),
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.supervisor_account),
|
||||||
|
title: Text(AppLocalizations.of(context)!.chatMember),
|
||||||
|
onTap: () {
|
||||||
|
SolianRouter.router.pushNamed(
|
||||||
|
'realms.member',
|
||||||
|
extra: widget.realm,
|
||||||
|
pathParameters: {'realm': widget.realm.alias},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
...(_isOwned ? authorizedItems : List.empty()),
|
||||||
|
const Divider(thickness: 0.3),
|
||||||
|
ListTile(
|
||||||
|
leading: _isOwned ? const Icon(Icons.delete) : const Icon(Icons.exit_to_app),
|
||||||
|
title: Text(_isOwned ? AppLocalizations.of(context)!.delete : AppLocalizations.of(context)!.exit),
|
||||||
|
onTap: () => promptLeaveChannel(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -7,20 +7,23 @@ import 'package:solian/models/account.dart';
|
|||||||
import 'package:solian/models/realm.dart';
|
import 'package:solian/models/realm.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/utils/service_url.dart';
|
import 'package:solian/utils/service_url.dart';
|
||||||
|
import 'package:solian/utils/theme.dart';
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
import 'package:solian/widgets/account/friend_picker.dart';
|
import 'package:solian/widgets/account/friend_picker.dart';
|
||||||
import 'package:solian/widgets/exts.dart';
|
import 'package:solian/widgets/exts.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
|
|
||||||
class RealmMemberWidget extends StatefulWidget {
|
class RealmMemberScreen extends StatefulWidget {
|
||||||
final Realm realm;
|
final Realm realm;
|
||||||
|
|
||||||
const RealmMemberWidget({super.key, required this.realm});
|
const RealmMemberScreen({super.key, required this.realm});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RealmMemberWidget> createState() => _RealmMemberWidgetState();
|
State<RealmMemberScreen> createState() => _RealmMemberScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RealmMemberWidgetState extends State<RealmMemberWidget> {
|
class _RealmMemberScreenState extends State<RealmMemberScreen> {
|
||||||
bool _isSubmitting = false;
|
bool _isSubmitting = false;
|
||||||
|
|
||||||
List<RealmMember> _members = List.empty();
|
List<RealmMember> _members = List.empty();
|
||||||
@ -136,12 +139,18 @@ class _RealmMemberWidgetState extends State<RealmMemberWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return IndentScaffold(
|
||||||
floatingActionButton: FloatingActionButton(
|
title: AppLocalizations.of(context)!.realmMember,
|
||||||
child: const Icon(Icons.add),
|
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
||||||
|
noSafeArea: true,
|
||||||
|
hideDrawer: true,
|
||||||
|
appBarActions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
onPressed: () => promptAddMember(),
|
onPressed: () => promptAddMember(),
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
],
|
||||||
|
child: RefreshIndicator(
|
||||||
onRefresh: () => fetchMemberships(),
|
onRefresh: () => fetchMemberships(),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
|
101
lib/widgets/realms/realm_deletion.dart
Normal file
101
lib/widgets/realms/realm_deletion.dart
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:solian/models/realm.dart';
|
||||||
|
import 'package:solian/providers/auth.dart';
|
||||||
|
import 'package:solian/utils/service_url.dart';
|
||||||
|
import 'package:solian/widgets/exts.dart';
|
||||||
|
|
||||||
|
class RealmDeletion extends StatefulWidget {
|
||||||
|
final Realm realm;
|
||||||
|
final bool isOwned;
|
||||||
|
|
||||||
|
const RealmDeletion({
|
||||||
|
super.key,
|
||||||
|
required this.realm,
|
||||||
|
required this.isOwned,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RealmDeletion> createState() => _RealmDeletionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RealmDeletionState extends State<RealmDeletion> {
|
||||||
|
bool _isSubmitting = false;
|
||||||
|
|
||||||
|
Future<void> deleteChannel() async {
|
||||||
|
setState(() => _isSubmitting = true);
|
||||||
|
|
||||||
|
final auth = context.read<AuthProvider>();
|
||||||
|
if (!await auth.isAuthorized()) {
|
||||||
|
setState(() => _isSubmitting = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = await auth.client!.delete(
|
||||||
|
getRequestUri('passport', '/api/realms/${widget.realm.alias}'),
|
||||||
|
);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
var message = utf8.decode(res.bodyBytes);
|
||||||
|
context.showErrorDialog(message);
|
||||||
|
} else if (Navigator.canPop(context)) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() => _isSubmitting = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> leaveChannel() async {
|
||||||
|
setState(() => _isSubmitting = true);
|
||||||
|
|
||||||
|
final auth = context.read<AuthProvider>();
|
||||||
|
if (!await auth.isAuthorized()) {
|
||||||
|
setState(() => _isSubmitting = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = await auth.client!.delete(
|
||||||
|
getRequestUri('passport', '/api/realms/${widget.realm.alias}/members/me'),
|
||||||
|
);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
var message = utf8.decode(res.bodyBytes);
|
||||||
|
context.showErrorDialog(message);
|
||||||
|
} else if (Navigator.canPop(context)) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() => _isSubmitting = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final content = widget.isOwned
|
||||||
|
? AppLocalizations.of(context)!.chatChannelDeleteConfirm
|
||||||
|
: AppLocalizations.of(context)!.chatChannelLeaveConfirm;
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(AppLocalizations.of(context)!.confirmation),
|
||||||
|
content: Text(content),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: _isSubmitting ? null : () => Navigator.pop(context),
|
||||||
|
child: Text(AppLocalizations.of(context)!.confirmCancel),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: _isSubmitting
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (widget.isOwned) {
|
||||||
|
deleteChannel();
|
||||||
|
} else {
|
||||||
|
leaveChannel();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(AppLocalizations.of(context)!.confirmOkay),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user