diff --git a/assets/i18n/en.json b/assets/i18n/en.json index e62390db..88fe3fb7 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -66,11 +66,13 @@ "widgetSubtitle": "We are online!" }, "appSelectorView": { + "viewTitle": "Select application", "searchBarHint": "Search applications", "storageButton": "Storage", "errorMessage": "Unable to use selected application." }, "patchesSelectorView": { + "viewTitle": "Select patches", "searchBarHint": "Search patches", "doneButton": "Done", "noPatchesFound": "No patches found for the selected app." diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index 44cb9150..f26f24ec 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -31,53 +31,62 @@ class _AppSelectorViewState extends State { Navigator.of(context).pop(); }, ), - body: SafeArea( - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: Column( - children: [ - SearchBar( - showSelectIcon: false, - hintText: FlutterI18n.translate( - context, - 'appSelectorView.searchBarHint', + body: CustomScrollView( + slivers: [ + SliverAppBar( + pinned: true, + floating: true, + snap: false, + title: I18nText('appSelectorView.viewTitle'), + bottom: PreferredSize( + preferredSize: const Size.fromHeight(64.0), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 12.0), + child: SearchBar( + showSelectIcon: false, + hintText: FlutterI18n.translate( + context, + 'appSelectorView.searchBarHint', + ), + onQueryChanged: (searchQuery) { + setState(() { + _query = searchQuery; + }); + }, ), - onQueryChanged: (searchQuery) { - setState(() { - _query = searchQuery; - }); - }, ), - const SizedBox(height: 12), - Expanded( - child: model.noApps - ? Center( - child: I18nText('appSelectorCard.noAppsLabel'), - ) - : model.apps.isEmpty - ? const AppSkeletonLoader() - : ListView( - padding: const EdgeInsets.only(bottom: 80), - children: model - .getFilteredApps(_query) - .map((app) => InkWell( - onTap: () { - model.selectApp(app); - Navigator.of(context).pop(); - }, - child: InstalledAppItem( - name: app.appName, - pkgName: app.packageName, - icon: app.icon, - ), - )) - .toList(), - ), - ), - ], + ), ), - ), + SliverToBoxAdapter( + child: model.noApps + ? Center( + child: I18nText('appSelectorCard.noAppsLabel'), + ) + : model.apps.isEmpty + ? const AppSkeletonLoader() + : Padding( + padding: const EdgeInsets.only(bottom: 80).add( + const EdgeInsets.symmetric(horizontal: 12.0)), + child: Column( + children: model + .getFilteredApps(_query) + .map((app) => InkWell( + onTap: () { + model.selectApp(app); + Navigator.of(context).pop(); + }, + child: InstalledAppItem( + name: app.appName, + pkgName: app.packageName, + icon: app.icon, + ), + )) + .toList(), + ), + ), + ), + ], ), ), ); diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index 95b8e10e..7f246c57 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -33,144 +33,153 @@ class _PatchesSelectorViewState extends State { }, ), ), - body: SafeArea( - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: Column( - children: [ - SearchBar( - showSelectIcon: true, - hintText: FlutterI18n.translate( - context, - 'patchesSelectorView.searchBarHint', + body: CustomScrollView( + slivers: [ + SliverAppBar( + pinned: true, + floating: true, + snap: false, + title: I18nText('patchesSelectorView.viewTitle'), + bottom: PreferredSize( + preferredSize: const Size.fromHeight(64.0), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 12.0), + child: SearchBar( + showSelectIcon: true, + hintText: FlutterI18n.translate( + context, + 'patchesSelectorView.searchBarHint', + ), + onQueryChanged: (searchQuery) { + setState(() { + _query = searchQuery; + }); + }, + onSelectAll: (value) => model.selectAllPatches(value), ), - onQueryChanged: (searchQuery) { - setState(() { - _query = searchQuery; - }); - }, - onSelectAll: (value) => model.selectAllPatches(value), ), - const SizedBox(height: 12), - Expanded( - child: model.patches.isEmpty - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: I18nText( - 'patchesSelectorView.noPatchesFound', - child: Text( - '', - style: Theme.of(context).textTheme.bodyMedium, - ), - ), + ), + ), + SliverToBoxAdapter( + child: model.patches.isEmpty + ? Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: I18nText( + 'patchesSelectorView.noPatchesFound', + child: Text( + '', + style: Theme.of(context).textTheme.bodyMedium, ), - ) - : ListView( - padding: const EdgeInsets.only(bottom: 80), - children: model - .getQueriedPatches(_query) - .map( - (patch) => PatchItem( - name: patch.name, - simpleName: patch.getSimpleName(), - version: patch.version, - description: patch.description, - packageVersion: model.getAppVersion(), - supportedPackageVersions: - model.getSupportedVersions(patch), - isUnsupported: !model.isPatchSupported(patch), - isSelected: model.isSelected(patch), - onChanged: (value) => - model.selectPatch(patch, value), - ), - /* TODO: Enable this and make use of new Patch Options implementation - patch.hasOptions ? ExpandablePanel( - controller: expController, - theme: const ExpandableThemeData( - hasIcon: false, - tapBodyToExpand: true, - tapBodyToCollapse: true, - tapHeaderToExpand: true, - ), - header: Column( - children: [ - GestureDetector( - onLongPress: () => - expController.toggle(), - child: PatchItem( - name: patch.name, - simpleName: patch.getSimpleName(), - description: patch.description, - version: patch.version, - packageVersion: - model.getAppVersion(), - supportedPackageVersions: model - .getSupportedVersions(patch), - isUnsupported: !model - .isPatchSupported(patch), - isSelected: - model.isSelected(patch), - onChanged: (value) => model - .selectPatch(patch, value), - child: const Padding( - padding: EdgeInsets.symmetric( - vertical: 8.0, - ), - child: Text( - 'Long press for additional options.', - ), + ), + ), + ) + : Padding( + padding: const EdgeInsets.only(bottom: 80) + .add(const EdgeInsets.symmetric(horizontal: 12.0)), + child: Column( + children: model + .getQueriedPatches(_query) + .map( + (patch) => PatchItem( + name: patch.name, + simpleName: patch.getSimpleName(), + version: patch.version, + description: patch.description, + packageVersion: model.getAppVersion(), + supportedPackageVersions: + model.getSupportedVersions(patch), + isUnsupported: !model.isPatchSupported(patch), + isSelected: model.isSelected(patch), + onChanged: (value) => + model.selectPatch(patch, value), + ), + /* TODO: Enable this and make use of new Patch Options implementation + patch.hasOptions ? ExpandablePanel( + controller: expController, + theme: const ExpandableThemeData( + hasIcon: false, + tapBodyToExpand: true, + tapBodyToCollapse: true, + tapHeaderToExpand: true, + ), + header: Column( + children: [ + GestureDetector( + onLongPress: () => + expController.toggle(), + child: PatchItem( + name: patch.name, + simpleName: patch.getSimpleName(), + description: patch.description, + version: patch.version, + packageVersion: + model.getAppVersion(), + supportedPackageVersions: model + .getSupportedVersions(patch), + isUnsupported: !model + .isPatchSupported(patch), + isSelected: + model.isSelected(patch), + onChanged: (value) => model + .selectPatch(patch, value), + child: const Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, + ), + child: Text( + 'Long press for additional options.', ), ), ), - ], + ), + ], + ), + expanded: Padding( + padding: const EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 10, ), - expanded: Padding( + child: Container( padding: const EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 10, + vertical: 8, + horizontal: 8, ), - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, - ), - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .tertiary - .withOpacity(0.1), - borderRadius: - BorderRadius.circular(12), - ), - child: Column( - children: [ - Text( - 'Patch options', - style: GoogleFonts.inter( - fontSize: 18, - fontWeight: FontWeight.w600, - ), + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .tertiary + .withOpacity(0.1), + borderRadius: + BorderRadius.circular(12), + ), + child: Column( + children: [ + Text( + 'Patch options', + style: GoogleFonts.inter( + fontSize: 18, + fontWeight: FontWeight.w600, ), - const OptionsTextField( - hint: 'App name'), - const OptionsFilePicker( - optionName: 'Choose a logo', - ), - ], - ), + ), + const OptionsTextField( + hint: 'App name'), + const OptionsFilePicker( + optionName: 'Choose a logo', + ), + ], ), ), - collapsed: Container(), - ) */ - ) - .toList(), - ), - ), - ], + ), + collapsed: Container(), + ) */ + ) + .toList(), + ), + ), ), - ), + ], ), ), ); diff --git a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart index 540bdfa8..89699c09 100644 --- a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart +++ b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart @@ -10,6 +10,7 @@ class AppSkeletonLoader extends StatelessWidget { return Skeleton( isLoading: true, skeleton: ListView.builder( + shrinkWrap: true, itemCount: 7, itemBuilder: (context, index) => Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8.0),