Optimize mobile - Avoid creating unnecessary widgets (#268)

* Avoid creating unnecessary widgets

* more flexible null handling and runtime errors prevention
This commit is contained in:
xpwmaosldk 2022-07-01 10:08:49 +09:00 committed by GitHub
parent 992f792c0a
commit c4ef523564
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 369 additions and 450 deletions

View File

@ -39,14 +39,10 @@ class ImageViewerService {
entity = await PhotoManager.editor.saveVideo(tempFile, title: fileName);
}
if (entity != null) {
return true;
}
return entity != null;
} catch (e) {
debugPrint("Error saving file $e");
return false;
}
return false;
}
}

View File

@ -15,9 +15,7 @@ class ExifBottomSheet extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
_buildMap() {
return (assetDetail.exifInfo!.latitude != null &&
assetDetail.exifInfo!.longitude != null)
? Padding(
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Container(
height: 150,
@ -57,29 +55,23 @@ class ExifBottomSheet extends ConsumerWidget {
],
),
),
)
: Container();
);
}
_buildLocationText() {
return (assetDetail.exifInfo!.city != null &&
assetDetail.exifInfo!.state != null)
? Text(
return Text(
"${assetDetail.exifInfo!.city}, ${assetDetail.exifInfo!.state}",
style: TextStyle(
fontSize: 12,
color: Colors.grey[200],
fontWeight: FontWeight.bold),
)
: Container();
fontSize: 12, color: Colors.grey[200], fontWeight: FontWeight.bold),
);
}
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8),
child: ListView(
children: [
assetDetail.exifInfo?.dateTimeOriginal != null
? Text(
if (assetDetail.exifInfo?.dateTimeOriginal != null)
Text(
DateFormat('E, LLL d, y • h:mm a').format(
DateTime.parse(assetDetail.exifInfo!.dateTimeOriginal!),
),
@ -88,8 +80,7 @@ class ExifBottomSheet extends ConsumerWidget {
fontWeight: FontWeight.bold,
fontSize: 14,
),
)
: Container(),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Text(
@ -102,8 +93,8 @@ class ExifBottomSheet extends ConsumerWidget {
),
// Location
assetDetail.exifInfo?.latitude != null
? Padding(
if (assetDetail.exifInfo?.latitude != null)
Padding(
padding: const EdgeInsets.only(top: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -116,19 +107,22 @@ class ExifBottomSheet extends ConsumerWidget {
"LOCATION",
style: TextStyle(fontSize: 11, color: Colors.grey[400]),
),
if (assetDetail.exifInfo?.latitude != null &&
assetDetail.exifInfo?.longitude != null)
_buildMap(),
if (assetDetail.exifInfo?.city != null &&
assetDetail.exifInfo?.state != null)
_buildLocationText(),
Text(
"${assetDetail.exifInfo!.latitude!.toStringAsFixed(4)}, ${assetDetail.exifInfo!.longitude!.toStringAsFixed(4)}",
"${assetDetail.exifInfo?.latitude?.toStringAsFixed(4)}, ${assetDetail.exifInfo?.longitude?.toStringAsFixed(4)}",
style: TextStyle(fontSize: 12, color: Colors.grey[400]),
)
],
),
)
: Container(),
),
// Detail
assetDetail.exifInfo != null
? Padding(
if (assetDetail.exifInfo != null)
Padding(
padding: const EdgeInsets.only(top: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -141,8 +135,7 @@ class ExifBottomSheet extends ConsumerWidget {
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
"DETAILS",
style:
TextStyle(fontSize: 11, color: Colors.grey[400]),
style: TextStyle(fontSize: 11, color: Colors.grey[400]),
),
),
ListTile(
@ -158,10 +151,10 @@ class ExifBottomSheet extends ConsumerWidget {
subtitle: assetDetail.exifInfo?.exifImageHeight != null
? Text(
"${assetDetail.exifInfo?.exifImageHeight} x ${assetDetail.exifInfo?.exifImageWidth} ${assetDetail.exifInfo?.fileSizeInByte!}B ")
: Container(),
: null,
),
assetDetail.exifInfo?.make != null
? ListTile(
if (assetDetail.exifInfo?.make != null)
ListTile(
contentPadding: const EdgeInsets.all(0),
dense: true,
textColor: Colors.grey[300],
@ -169,17 +162,14 @@ class ExifBottomSheet extends ConsumerWidget {
leading: const Icon(Icons.camera),
title: Text(
"${assetDetail.exifInfo?.make} ${assetDetail.exifInfo?.model}",
style: const TextStyle(
fontWeight: FontWeight.bold),
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
"ƒ/${assetDetail.exifInfo?.fNumber} 1/${(1 / assetDetail.exifInfo!.exposureTime!).toStringAsFixed(0)} ${assetDetail.exifInfo?.focalLength}mm ISO${assetDetail.exifInfo?.iso} "),
)
: Container()
"ƒ/${assetDetail.exifInfo?.fNumber} 1/${(1 / (assetDetail.exifInfo?.exposureTime ?? 1)).toStringAsFixed(0)} ${assetDetail.exifInfo?.focalLength}mm ISO${assetDetail.exifInfo?.iso} "),
),
],
),
)
: Container()
),
],
),
);

View File

@ -147,8 +147,7 @@ class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
@override
Widget build(BuildContext context) {
return chewieController != null &&
chewieController!.videoPlayerController.value.isInitialized
return chewieController?.videoPlayerController.value.isInitialized == true
? SizedBox(
child: Chewie(
controller: chewieController!,

View File

@ -56,7 +56,7 @@ class AlbumInfoCard extends HookConsumerWidget {
);
}
return Container();
return const SizedBox();
}
_buildImageFilter() {
@ -151,7 +151,11 @@ class AlbumInfoCard extends HookConsumerWidget {
),
child: null,
),
Positioned(bottom: 10, left: 25, child: _buildSelectedTextBox())
Positioned(
bottom: 10,
left: 25,
child: _buildSelectedTextBox(),
)
],
),
Padding(
@ -176,8 +180,7 @@ class AlbumInfoCard extends HookConsumerWidget {
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: Text(
albumInfo.assetCount.toString() +
(albumInfo.isAll ? " (ALL)" : ""),
'${albumInfo.assetCount} ${(albumInfo.isAll ? " (ALL)" : "")}',
style: TextStyle(
fontSize: 12, color: Colors.grey[600]),
),

View File

@ -188,11 +188,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
color: Colors.grey[700]),
),
trailing: Text(
ref
.watch(backupProvider)
.allUniqueAssets
.length
.toString(),
'${ref.watch(backupProvider).allUniqueAssets.length}',
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
@ -203,7 +199,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
ListTile(
title: Text(
"Albums on device (${availableAlbums.length.toString()})",
"Albums on device (${availableAlbums.length})",
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
subtitle: Padding(

View File

@ -96,12 +96,11 @@ class BackupControllerPage extends HookConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
!isAutoBackup
? const Text(
if (!isAutoBackup)
const Text(
"Turn on backup to automatically upload new assets to the server.",
style: TextStyle(fontSize: 14),
)
: Container(),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: OutlinedButton(
@ -189,7 +188,7 @@ class BackupControllerPage extends HookConsumerWidget {
),
);
} else {
return Container();
return const SizedBox();
}
}

View File

@ -34,7 +34,7 @@ class DisableMultiSelectButton extends ConsumerWidget {
},
icon: const Icon(Icons.close_rounded),
label: Text(
selectedItemCount.toString(),
'$selectedItemCount',
style: const TextStyle(
fontWeight: FontWeight.w600, fontSize: 18),
)),

View File

@ -615,7 +615,7 @@ class SlideFadeTransition extends StatelessWidget {
return AnimatedBuilder(
animation: animation,
builder: (context, child) =>
animation.value == 0.0 ? Container() : child!,
animation.value == 0.0 ? const SizedBox() : child!,
child: SlideTransition(
position: Tween(
begin: const Offset(0.3, 0.0),

View File

@ -25,18 +25,14 @@ class ImageGrid extends ConsumerWidget {
child: Stack(
children: [
ThumbnailImage(asset: assetGroup[index]),
assetType == 'IMAGE'
? Container()
: Positioned(
if (assetType != 'IMAGE')
Positioned(
top: 5,
right: 5,
child: Row(
children: [
Text(
assetGroup[index]
.duration
.toString()
.substring(0, 7),
assetGroup[index].duration.toString().substring(0, 7),
style: const TextStyle(
color: Colors.white,
fontSize: 10,
@ -48,7 +44,7 @@ class ImageGrid extends ConsumerWidget {
),
],
),
)
),
],
),
);

View File

@ -49,8 +49,8 @@ class ImmichSliverAppBar extends ConsumerWidget {
},
),
),
serverInfoState.isVersionMismatch
? Positioned(
if (serverInfoState.isVersionMismatch)
Positioned(
bottom: 12,
right: 12,
child: GestureDetector(
@ -71,8 +71,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
),
),
),
)
: Container(),
),
],
);
},
@ -90,8 +89,8 @@ class ImmichSliverAppBar extends ConsumerWidget {
Stack(
alignment: AlignmentDirectional.center,
children: [
backupState.backupProgress == BackUpProgressEnum.inProgress
? Positioned(
if (backupState.backupProgress == BackUpProgressEnum.inProgress)
Positioned(
top: 10,
right: 12,
child: SizedBox(
@ -103,8 +102,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
Theme.of(context).primaryColor),
),
),
)
: Container(),
),
IconButton(
splashRadius: 25,
iconSize: 30,
@ -129,18 +127,15 @@ class ImmichSliverAppBar extends ConsumerWidget {
}
},
),
backupState.backupProgress == BackUpProgressEnum.inProgress
? Positioned(
if (backupState.backupProgress == BackUpProgressEnum.inProgress)
Positioned(
bottom: 5,
child: Text(
(backupState.allUniqueAssets.length -
backupState.selectedAlbumsBackupAssetsIds.length)
.toString(),
style: const TextStyle(
fontSize: 9, fontWeight: FontWeight.bold),
'${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}',
style:
const TextStyle(fontSize: 9, fontWeight: FontWeight.bold),
),
),
)
: Container()
],
),
],

View File

@ -87,7 +87,7 @@ class ProfileDrawer extends HookConsumerWidget {
return const ImmichLoadingIndicator();
}
return Container();
return const SizedBox();
}
_pickUserProfileImage() async {

View File

@ -122,16 +122,13 @@ class ThumbnailImage extends HookConsumerWidget {
},
),
),
Container(
child: isMultiSelectEnable
? Padding(
if (isMultiSelectEnable)
Padding(
padding: const EdgeInsets.all(3.0),
child: Align(
alignment: Alignment.topLeft,
child: _buildSelectionIcon(asset),
),
)
: Container(),
),
Positioned(
right: 10,

View File

@ -38,17 +38,10 @@ class HomePage extends HookConsumerWidget {
}
_buildSelectedItemCountIndicator() {
return isMultiSelectEnable
? DisableMultiSelectButton(
onPressed:
ref.watch(homePageStateProvider.notifier).disableMultiSelect,
return DisableMultiSelectButton(
onPressed: ref.watch(homePageStateProvider.notifier).disableMultiSelect,
selectedItemCount: homePageState.selectedItems.length,
)
: Container();
}
_buildBottomAppBar() {
return isMultiSelectEnable ? const ControlBottomAppBar() : Container();
);
}
Widget _buildBody() {
@ -121,8 +114,10 @@ class HomePage extends HookConsumerWidget {
),
),
),
if (isMultiSelectEnable) ...[
_buildSelectedItemCountIndicator(),
_buildBottomAppBar(),
const ControlBottomAppBar(),
],
],
),
);

View File

@ -107,19 +107,12 @@ class ServerEndpointInput extends StatelessWidget {
: super(key: key);
String? _validateInput(String? url) {
if (url == null) {
if (url?.startsWith(RegExp(r'https?://')) == true) {
return null;
}
if (url.isEmpty) {
return 'Server endpoint is required';
}
if (!url.startsWith(RegExp(r'https?://'))) {
} else {
return 'Please specify http:// or https://';
}
return null;
}
@override

View File

@ -62,11 +62,7 @@ final getCuratedLocationProvider =
final SearchService searchService = ref.watch(searchServiceProvider);
var curatedLocation = await searchService.getCuratedLocation();
if (curatedLocation != null) {
return curatedLocation;
} else {
return [];
}
return curatedLocation ?? [];
});
final getCuratedObjectProvider =
@ -74,9 +70,6 @@ final getCuratedObjectProvider =
final SearchService searchService = ref.watch(searchServiceProvider);
var curatedObject = await searchService.getCuratedObjects();
if (curatedObject != null) {
return curatedObject;
} else {
return [];
}
return curatedObject ?? [];
});

View File

@ -176,9 +176,8 @@ class SearchPage extends HookConsumerWidget {
_buildThings()
],
),
isSearchEnabled
? SearchSuggestionList(onSubmitted: _onSearchSubmitted)
: Container(),
if (isSearchEnabled)
SearchSuggestionList(onSubmitted: _onSearchSubmitted),
],
),
),

View File

@ -166,7 +166,7 @@ class SearchResultPage extends HookConsumerWidget {
}
}
return Container();
return const SizedBox();
}
return Scaffold(
@ -198,9 +198,8 @@ class SearchResultPage extends HookConsumerWidget {
child: Stack(
children: [
_buildSearchResult(),
isNewSearch.value
? SearchSuggestionList(onSubmitted: _onSearchSubmitted)
: Container(),
if (isNewSearch.value)
SearchSuggestionList(onSubmitted: _onSearchSubmitted),
],
),
),

View File

@ -72,10 +72,7 @@ class SharedAlbum {
albumThumbnailAssetId: map['albumThumbnailAssetId'],
sharedUsers:
List<User>.from(map['sharedUsers']?.map((x) => User.fromMap(x))),
assets: map['assets'] != null
? List<ImmichAsset>.from(
map['assets']?.map((x) => ImmichAsset.fromMap(x)))
: null,
assets: map['assets']?.map((x) => ImmichAsset.fromMap(x)).toList(),
);
}

View File

@ -39,11 +39,7 @@ class SharedAlbumService {
"assetIds": assets.map((asset) => asset.id).toList(),
});
if (res == null) {
return false;
}
return true;
return res != null;
} catch (e) {
debugPrint("Error createSharedAlbum ${e.toString()}");
return false;
@ -71,11 +67,7 @@ class SharedAlbumService {
"assetIds": assets.map((asset) => asset.id).toList(),
});
if (res == null) {
return false;
}
return true;
return res != null;
} catch (e) {
debugPrint("Error addAdditionalAssetToAlbum ${e.toString()}");
return false;
@ -90,11 +82,7 @@ class SharedAlbumService {
"sharedUserIds": sharedUserIds,
});
if (res == null) {
return false;
}
return true;
return res != null;
} catch (e) {
debugPrint("Error addAdditionalUserToAlbum ${e.toString()}");
return false;

View File

@ -114,7 +114,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
onTap: () => _onRemoveFromAlbumPressed(albumId),
);
} else {
return Container();
return const SizedBox();
}
} else {
if (_albumInfo.asData?.value.ownerId == userId) {
@ -198,8 +198,8 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
elevation: 0,
leading: _buildLeadingButton(),
title: isMultiSelectionEnable
? Text(selectedAssetsInAlbum.length.toString())
: Container(),
? Text('${selectedAssetsInAlbum.length}')
: null,
centerTitle: false,
actions: [
IconButton(

View File

@ -71,9 +71,6 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
}
_buildVideoLabel() {
if (asset.type == 'IMAGE') {
return Container();
} else {
return Positioned(
top: 5,
right: 5,
@ -94,7 +91,6 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
),
);
}
}
_buildAssetStoreLocationIcon() {
return Positioned(
@ -112,7 +108,7 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
_buildAssetSelectionIcon() {
bool isSelected = selectedAssetsInAlbumViewer.contains(asset);
if (isMultiSelectionEnable) {
return Positioned(
left: 10,
top: 5,
@ -126,9 +122,6 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
color: Colors.white,
),
);
} else {
return Container();
}
}
_buildThumbnailImage() {
@ -183,8 +176,8 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
children: [
_buildThumbnailImage(),
_buildAssetStoreLocationIcon(),
_buildVideoLabel(),
_buildAssetSelectionIcon(),
if (asset.type != 'IMAGE') _buildVideoLabel(),
if (isMultiSelectionEnable) _buildAssetSelectionIcon(),
],
),
),

View File

@ -131,15 +131,14 @@ class SelectionThumbnailImage extends HookConsumerWidget {
child: _buildSelectionIcon(asset),
),
),
asset.type == 'IMAGE'
? Container()
: Positioned(
if (asset.type != 'IMAGE')
Positioned(
bottom: 5,
right: 5,
child: Row(
children: [
Text(
asset.duration.toString().substring(0, 7),
'${asset.duration?.substring(0, 7)}',
style: const TextStyle(
color: Colors.white,
fontSize: 10,
@ -151,7 +150,7 @@ class SelectionThumbnailImage extends HookConsumerWidget {
),
],
),
)
),
],
),
);

View File

@ -14,7 +14,8 @@ class SharingSliverAppBar extends StatelessWidget {
floating: false,
pinned: true,
snap: false,
leading: Container(),
automaticallyImplyLeading: false,
// leading: Container(),
// elevation: 0,
title: Text(
'IMMICH',

View File

@ -37,7 +37,7 @@ class AlbumViewerPage extends HookConsumerWidget {
/// Find out if the assets in album exist on the device
/// If they exist, add to selected asset state to show they are already selected.
void _onAddPhotosPressed(SharedAlbum albumInfo) async {
if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) {
if (albumInfo.assets?.isNotEmpty == true) {
ref
.watch(assetSelectionProvider.notifier)
.addNewAssets(albumInfo.assets!.toList());
@ -109,12 +109,11 @@ class AlbumViewerPage extends HookConsumerWidget {
}
Widget _buildAlbumDateRange(SharedAlbum albumInfo) {
if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) {
String startDate = "";
DateTime parsedStartDate =
DateTime.parse(albumInfo.assets!.first.createdAt);
DateTime parsedEndDate =
DateTime.parse(albumInfo.assets!.last.createdAt);
DateTime parsedEndDate = DateTime.parse(
albumInfo.assets?.last.createdAt ?? '11111111'); //Need default.
if (parsedStartDate.year == parsedEndDate.year) {
startDate = DateFormat('LLL d').format(parsedStartDate);
@ -132,9 +131,6 @@ class AlbumViewerPage extends HookConsumerWidget {
fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey),
),
);
} else {
return Container();
}
}
Widget _buildHeader(SharedAlbum albumInfo) {
@ -143,6 +139,7 @@ class AlbumViewerPage extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTitle(albumInfo),
if (albumInfo.assets?.isNotEmpty == true)
_buildAlbumDateRange(albumInfo),
SizedBox(
height: 60,
@ -175,7 +172,7 @@ class AlbumViewerPage extends HookConsumerWidget {
}
Widget _buildImageGrid(SharedAlbum albumInfo) {
if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) {
if (albumInfo.assets?.isNotEmpty == true) {
return SliverPadding(
padding: const EdgeInsets.only(top: 10.0),
sliver: SliverGrid(
@ -209,13 +206,12 @@ class AlbumViewerPage extends HookConsumerWidget {
onPressed: () => _onAddPhotosPressed(albumInfo),
labelText: "Add photos",
),
userId == albumInfo.ownerId
? AlbumActionOutlinedButton(
if (userId == albumInfo.ownerId)
AlbumActionOutlinedButton(
iconData: Icons.person_add_alt_rounded,
onPressed: () => _onAddUsersPressed(albumInfo),
labelText: "Add users",
)
: Container(),
),
],
),
),

View File

@ -74,9 +74,9 @@ class AssetSelectionPage extends HookConsumerWidget {
),
centerTitle: false,
actions: [
(!isAlbumExist && selectedAssets.isNotEmpty) ||
(isAlbumExist && newAssetsForAlbum.isNotEmpty)
? TextButton(
if ((!isAlbumExist && selectedAssets.isNotEmpty) ||
(isAlbumExist && newAssetsForAlbum.isNotEmpty))
TextButton(
onPressed: () {
var payload = AssetSelectionPageResult(
isAlbumExist: isAlbumExist,
@ -89,8 +89,7 @@ class AssetSelectionPage extends HookConsumerWidget {
"Add",
style: TextStyle(fontWeight: FontWeight.bold),
),
)
: Container()
),
],
),
body: _buildBody(),

View File

@ -113,7 +113,6 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
}
_buildControlButton() {
if (selectedAssets.isNotEmpty) {
return Padding(
padding: const EdgeInsets.only(left: 12.0, top: 16, bottom: 16),
child: SizedBox(
@ -132,9 +131,6 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
);
}
return Container();
}
_buildSelectedImageGrid() {
if (selectedAssets.isNotEmpty) {
return SliverPadding(
@ -196,7 +192,8 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
slivers: [
SliverAppBar(
elevation: 5,
leading: Container(),
automaticallyImplyLeading: false,
// leading: Container(),
pinned: true,
floating: false,
bottom: PreferredSize(
@ -204,7 +201,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
child: Column(
children: [
_buildTitleInputField(),
_buildControlButton(),
if (selectedAssets.isNotEmpty) _buildControlButton(),
],
),
),

View File

@ -104,12 +104,11 @@ class WebsocketNotifier extends StateNotifier<WebscoketState> {
disconnect() {
debugPrint("[WEBSOCKET] Attempting to disconnect");
var socket = state.socket?.disconnect();
if (socket != null) {
if (socket.disconnected) {
if (socket?.disconnected == true) {
state = WebscoketState(isConnected: false, socket: null);
}
}
}
stopListenToEvent(String eventName) {
debugPrint("[Websocket] Stop listening to event $eventName");

View File

@ -34,7 +34,7 @@ class SplashScreenPage extends HookConsumerWidget {
}
useEffect(() {
if (loginInfo != null && loginInfo.isSaveLogin) {
if (loginInfo?.isSaveLogin == true) {
performLoggingIn();
} else {
AutoRouter.of(context).push(const LoginRoute());

View File

@ -121,7 +121,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget {
),
);
} else {
return Container();
return const SizedBox();
}
},
);