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

View File

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