♻️ Refactor the app management to use sheet

This commit is contained in:
2025-11-02 21:12:55 +08:00
parent da2d3f7f17
commit bd2247ce86
3 changed files with 350 additions and 281 deletions

View File

@@ -6,8 +6,11 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/custom_app.dart'; import 'package:island/models/custom_app.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/screens/developers/edit_app.dart';
import 'package:island/screens/developers/new_app.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:island/widgets/extended_refresh_indicator.dart'; import 'package:island/widgets/extended_refresh_indicator.dart';
import 'package:island/widgets/response.dart'; import 'package:island/widgets/response.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
@@ -70,12 +73,18 @@ class CustomAppsScreen extends HookConsumerWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
ElevatedButton.icon( ElevatedButton.icon(
onPressed: () { onPressed: () {
context.pushNamed( showModalBottomSheet(
'developerAppNew', context: context,
pathParameters: { isScrollControlled: true,
'name': publisherName, builder:
'projectId': projectId, (context) => SheetScaffold(
}, titleText: 'createCustomApp'.tr(),
child: NewCustomAppScreen(
publisherName: publisherName,
projectId: projectId,
isModal: true,
),
),
); );
}, },
icon: const Icon(Symbols.add), icon: const Icon(Symbols.add),
@@ -98,12 +107,18 @@ class CustomAppsScreen extends HookConsumerWidget {
title: Text('customApps').tr().padding(horizontal: 8), title: Text('customApps').tr().padding(horizontal: 8),
trailing: IconButton( trailing: IconButton(
onPressed: () { onPressed: () {
context.pushNamed( showModalBottomSheet(
'developerAppNew', context: context,
pathParameters: { isScrollControlled: true,
'name': publisherName, builder:
'projectId': projectId, (context) => SheetScaffold(
}, titleText: 'createCustomApp'.tr(),
child: NewCustomAppScreen(
publisherName: publisherName,
projectId: projectId,
isModal: true,
),
),
); );
}, },
icon: const Icon(Symbols.add), icon: const Icon(Symbols.add),
@@ -198,13 +213,19 @@ class CustomAppsScreen extends HookConsumerWidget {
], ],
onSelected: (value) { onSelected: (value) {
if (value == 'edit') { if (value == 'edit') {
context.pushNamed( showModalBottomSheet(
'developerAppEdit', context: context,
pathParameters: { isScrollControlled: true,
'name': publisherName, builder:
'projectId': projectId, (context) => SheetScaffold(
'id': app.id, titleText: 'editCustomApp'.tr(),
}, child: EditAppScreen(
publisherName: publisherName,
projectId: projectId,
id: app.id,
isModal: true,
),
),
); );
} else if (value == 'delete') { } else if (value == 'delete') {
showConfirmAlert( showConfirmAlert(

View File

@@ -39,11 +39,13 @@ class EditAppScreen extends HookConsumerWidget {
final String publisherName; final String publisherName;
final String projectId; final String projectId;
final String? id; final String? id;
final bool isModal;
const EditAppScreen({ const EditAppScreen({
super.key, super.key,
required this.publisherName, required this.publisherName,
required this.projectId, required this.projectId,
this.id, this.id,
this.isModal = false,
}); });
@override @override
@@ -177,7 +179,12 @@ class EditAppScreen extends HookConsumerWidget {
children: [ children: [
TextFormField( TextFormField(
controller: scopeController, controller: scopeController,
decoration: InputDecoration(labelText: 'scopeName'.tr()), decoration: InputDecoration(
labelText: 'scopeName'.tr(),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
FilledButton.tonalIcon( FilledButton.tonalIcon(
@@ -220,6 +227,9 @@ class EditAppScreen extends HookConsumerWidget {
hintText: 'https://example.com/auth/callback', hintText: 'https://example.com/auth/callback',
helperText: 'redirectUriHint'.tr(), helperText: 'redirectUriHint'.tr(),
helperMaxLines: 3, helperMaxLines: 3,
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
), ),
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
validator: (value) { validator: (value) {
@@ -316,12 +326,7 @@ class EditAppScreen extends HookConsumerWidget {
} }
} }
return AppScaffold( final bodyContent =
isNoBackground: false,
appBar: AppBar(
title: Text(isNew ? 'createCustomApp'.tr() : 'editCustomApp'.tr()),
),
body:
app == null && !isNew app == null && !isNew
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: app?.hasError == true && !isNew : app?.hasError == true && !isNew
@@ -382,11 +387,17 @@ class EditAppScreen extends HookConsumerWidget {
children: [ children: [
TextFormField( TextFormField(
controller: nameController, controller: nameController,
decoration: InputDecoration(labelText: 'name'.tr()), decoration: InputDecoration(
labelText: 'name'.tr(),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
),
onTapOutside: onTapOutside:
(_) => (_) =>
FocusManager.instance.primaryFocus FocusManager.instance.primaryFocus?.unfocus(),
?.unfocus(),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( TextFormField(
@@ -394,11 +405,15 @@ class EditAppScreen extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'slug'.tr(), labelText: 'slug'.tr(),
helperText: 'slugHint'.tr(), helperText: 'slugHint'.tr(),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
), ),
onTapOutside: onTapOutside:
(_) => (_) =>
FocusManager.instance.primaryFocus FocusManager.instance.primaryFocus?.unfocus(),
?.unfocus(),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( TextFormField(
@@ -406,12 +421,16 @@ class EditAppScreen extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'description'.tr(), labelText: 'description'.tr(),
alignLabelWithHint: true, alignLabelWithHint: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
), ),
maxLines: 3, maxLines: 3,
onTapOutside: onTapOutside:
(_) => (_) =>
FocusManager.instance.primaryFocus FocusManager.instance.primaryFocus?.unfocus(),
?.unfocus(),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ExpansionPanelList( ExpansionPanelList(
@@ -438,6 +457,11 @@ class EditAppScreen extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'homePageUrl'.tr(), labelText: 'homePageUrl'.tr(),
hintText: 'https://example.com', hintText: 'https://example.com',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
), ),
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
), ),
@@ -446,6 +470,11 @@ class EditAppScreen extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'privacyPolicyUrl'.tr(), labelText: 'privacyPolicyUrl'.tr(),
hintText: 'https://example.com/privacy', hintText: 'https://example.com/privacy',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
), ),
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
), ),
@@ -454,6 +483,11 @@ class EditAppScreen extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'termsOfServiceUrl'.tr(), labelText: 'termsOfServiceUrl'.tr(),
hintText: 'https://example.com/terms', hintText: 'https://example.com/terms',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
), ),
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
), ),
@@ -463,9 +497,8 @@ class EditAppScreen extends HookConsumerWidget {
), ),
ExpansionPanel( ExpansionPanel(
headerBuilder: headerBuilder:
(context, isExpanded) => ListTile( (context, isExpanded) =>
title: Text('oauthConfig').tr(), ListTile(title: Text('oauthConfig').tr()),
),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -480,15 +513,11 @@ class EditAppScreen extends HookConsumerWidget {
(uri) => ListTile( (uri) => ListTile(
title: Text(uri), title: Text(uri),
trailing: IconButton( trailing: IconButton(
icon: const Icon( icon: const Icon(Symbols.delete),
Symbols.delete,
),
onPressed: () { onPressed: () {
redirectUris.value = redirectUris.value =
redirectUris.value redirectUris.value
.where( .where((u) => u != uri)
(u) => u != uri,
)
.toList(); .toList();
}, },
), ),
@@ -501,8 +530,9 @@ class EditAppScreen extends HookConsumerWidget {
title: Text('addRedirectUri'.tr()), title: Text('addRedirectUri'.tr()),
onTap: showAddRedirectUriDialog, onTap: showAddRedirectUriDialog,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: borderRadius: BorderRadius.circular(
BorderRadius.circular(8), 8,
),
), ),
), ),
], ],
@@ -520,9 +550,7 @@ class EditAppScreen extends HookConsumerWidget {
(scope) => ListTile( (scope) => ListTile(
title: Text(scope), title: Text(scope),
trailing: IconButton( trailing: IconButton(
icon: const Icon( icon: const Icon(Symbols.delete),
Symbols.delete,
),
onPressed: () { onPressed: () {
allowedScopes.value = allowedScopes.value =
allowedScopes.value allowedScopes.value
@@ -568,8 +596,7 @@ class EditAppScreen extends HookConsumerWidget {
Align( Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: TextButton.icon( child: TextButton.icon(
onPressed: onPressed: submitting.value ? null : performAction,
submitting.value ? null : performAction,
label: Text('saveChanges'.tr()), label: Text('saveChanges'.tr()),
icon: const Icon(Symbols.save), icon: const Icon(Symbols.save),
), ),
@@ -579,7 +606,18 @@ class EditAppScreen extends HookConsumerWidget {
), ),
], ],
), ),
);
if (isModal) {
return bodyContent;
}
return AppScaffold(
isNoBackground: false,
appBar: AppBar(
title: Text(isNew ? 'createCustomApp'.tr() : 'editCustomApp'.tr()),
), ),
body: bodyContent,
); );
} }
} }

View File

@@ -4,10 +4,20 @@ import 'package:island/screens/developers/edit_app.dart';
class NewCustomAppScreen extends StatelessWidget { class NewCustomAppScreen extends StatelessWidget {
final String publisherName; final String publisherName;
final String projectId; final String projectId;
const NewCustomAppScreen({super.key, required this.publisherName, required this.projectId}); final bool isModal;
const NewCustomAppScreen({
super.key,
required this.publisherName,
required this.projectId,
this.isModal = false,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return EditAppScreen(publisherName: publisherName, projectId: projectId); return EditAppScreen(
publisherName: publisherName,
projectId: projectId,
isModal: isModal,
);
} }
} }