This commit is contained in:
		@@ -29,11 +29,27 @@ class _MediaGrid extends State<MediaGrid> {
 | 
			
		||||
 | 
			
		||||
  late final _MediaGridAppBar _appBar;
 | 
			
		||||
  late final _MediaGridBody _body;
 | 
			
		||||
  Worker? _filterWorker;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    _mediaController.fetchInitial();
 | 
			
		||||
 | 
			
		||||
    _filterWorker = everAll(
 | 
			
		||||
      [
 | 
			
		||||
        _mediaController.typeIndex,
 | 
			
		||||
        _mediaController.modeIndex,
 | 
			
		||||
        _mediaController.tag,
 | 
			
		||||
        _mediaController.random,
 | 
			
		||||
      ],
 | 
			
		||||
      (_) {
 | 
			
		||||
        WidgetsBinding.instance.addPostFrameCallback((_) {
 | 
			
		||||
          _refreshController.requestRefresh();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    _appBar = _MediaGridAppBar(mediaController: _mediaController);
 | 
			
		||||
    _body = _MediaGridBody(
 | 
			
		||||
      refreshController: _refreshController,
 | 
			
		||||
@@ -45,6 +61,7 @@ class _MediaGrid extends State<MediaGrid> {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    _filterWorker?.dispose();
 | 
			
		||||
    _scrollController.dispose();
 | 
			
		||||
    _refreshController.dispose();
 | 
			
		||||
    super.dispose();
 | 
			
		||||
@@ -52,19 +69,55 @@ class _MediaGrid extends State<MediaGrid> {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Obx(
 | 
			
		||||
      () => Scaffold(
 | 
			
		||||
    return Obx(() {
 | 
			
		||||
      if (_mediaController.loading.value && _mediaController.items.isEmpty) {
 | 
			
		||||
        return Scaffold(
 | 
			
		||||
          appBar: _appBar,
 | 
			
		||||
          body: const Center(child: CircularProgressIndicator()),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (_mediaController.errorMessage.value != null &&
 | 
			
		||||
          _mediaController.items.isEmpty) {
 | 
			
		||||
        return Scaffold(
 | 
			
		||||
          appBar: _appBar,
 | 
			
		||||
          body: Center(
 | 
			
		||||
            child: Padding(
 | 
			
		||||
              padding: const EdgeInsets.all(16.0),
 | 
			
		||||
              child: Column(
 | 
			
		||||
                mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
                children: [
 | 
			
		||||
                  const Icon(Icons.error_outline, color: Colors.red, size: 60),
 | 
			
		||||
                  const SizedBox(height: 16),
 | 
			
		||||
                  Text(
 | 
			
		||||
                    '${_mediaController.errorMessage.value}',
 | 
			
		||||
                    textAlign: TextAlign.center,
 | 
			
		||||
                    style: Theme.of(context).textTheme.titleMedium,
 | 
			
		||||
                  ),
 | 
			
		||||
                  const SizedBox(height: 16),
 | 
			
		||||
                  ElevatedButton(
 | 
			
		||||
                    onPressed: () => _mediaController.fetchInitial(),
 | 
			
		||||
                    child: const Text('Erneut versuchen'),
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return Scaffold(
 | 
			
		||||
        endDrawer: const EndDrawer(),
 | 
			
		||||
        endDrawerEnableOpenDragGesture:
 | 
			
		||||
            _settingsController.drawerSwipeEnabled.value,
 | 
			
		||||
        bottomNavigationBar: FilterBar(scrollController: _scrollController),
 | 
			
		||||
        bottomNavigationBar: FilterBar(),
 | 
			
		||||
        appBar: _appBar,
 | 
			
		||||
        body: _body,
 | 
			
		||||
        persistentFooterButtons: _mediaController.tag.value != null
 | 
			
		||||
            ? [TagFooter()]
 | 
			
		||||
            : null,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -78,7 +131,9 @@ class _MediaGridAppBar extends StatelessWidget implements PreferredSizeWidget {
 | 
			
		||||
    return AppBar(
 | 
			
		||||
      title: InkWell(
 | 
			
		||||
        onTap: () {
 | 
			
		||||
          mediaController.setTag(null);
 | 
			
		||||
          if (mediaController.tag.value != null) {
 | 
			
		||||
            mediaController.setTag(null);
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        child: Row(
 | 
			
		||||
          mainAxisSize: MainAxisSize.min,
 | 
			
		||||
@@ -106,7 +161,9 @@ class _MediaGridAppBar extends StatelessWidget implements PreferredSizeWidget {
 | 
			
		||||
                  ? Icons.shuffle_on_outlined
 | 
			
		||||
                  : Icons.shuffle,
 | 
			
		||||
            ),
 | 
			
		||||
            onPressed: mediaController.toggleRandom,
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              mediaController.toggleRandom();
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        IconButton(
 | 
			
		||||
@@ -134,63 +191,72 @@ class _MediaGridBody extends StatelessWidget {
 | 
			
		||||
  final SettingsController settingsController;
 | 
			
		||||
  final ScrollController scrollController;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return PullexRefresh(
 | 
			
		||||
      controller: refreshController,
 | 
			
		||||
      enablePullDown: true,
 | 
			
		||||
      enablePullUp: true,
 | 
			
		||||
      header: const WaterDropHeader(),
 | 
			
		||||
      onRefresh: () async {
 | 
			
		||||
        try {
 | 
			
		||||
          await mediaController.handleRefresh();
 | 
			
		||||
        } finally {
 | 
			
		||||
          refreshController.refreshCompleted();
 | 
			
		||||
    if (mediaController.items.isEmpty && !mediaController.loading.value) {
 | 
			
		||||
      return const Center(
 | 
			
		||||
        child: Text(
 | 
			
		||||
          'Keine f0cks gefunden.\n\nVersuch mal andere Filter.',
 | 
			
		||||
          textAlign: TextAlign.center,
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return NotificationListener<ScrollNotification>(
 | 
			
		||||
      onNotification: (scrollInfo) {
 | 
			
		||||
        if (!mediaController.loading.value &&
 | 
			
		||||
            !mediaController.atEnd.value &&
 | 
			
		||||
            scrollInfo.metrics.pixels >=
 | 
			
		||||
                scrollInfo.metrics.maxScrollExtent - 600) {
 | 
			
		||||
          mediaController.handleLoading();
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
      },
 | 
			
		||||
      onLoading: () async {
 | 
			
		||||
        try {
 | 
			
		||||
          await mediaController.handleLoading();
 | 
			
		||||
        } finally {
 | 
			
		||||
          refreshController.loadComplete();
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      child: Obx(
 | 
			
		||||
        () => GridView.builder(
 | 
			
		||||
          addAutomaticKeepAlives: false,
 | 
			
		||||
          controller: scrollController,
 | 
			
		||||
          physics: const NeverScrollableScrollPhysics(),
 | 
			
		||||
          shrinkWrap: true,
 | 
			
		||||
          padding: const EdgeInsets.all(4),
 | 
			
		||||
          itemCount: mediaController.items.length,
 | 
			
		||||
          gridDelegate: settingsController.crossAxisCount.value == 0
 | 
			
		||||
              ? const SliverGridDelegateWithMaxCrossAxisExtent(
 | 
			
		||||
                  maxCrossAxisExtent: 150,
 | 
			
		||||
                  crossAxisSpacing: 5,
 | 
			
		||||
                  mainAxisSpacing: 5,
 | 
			
		||||
                  childAspectRatio: 1,
 | 
			
		||||
                )
 | 
			
		||||
              : SliverGridDelegateWithFixedCrossAxisCount(
 | 
			
		||||
                  crossAxisCount: settingsController.crossAxisCount.value,
 | 
			
		||||
                  crossAxisSpacing: 5,
 | 
			
		||||
                  mainAxisSpacing: 5,
 | 
			
		||||
                  childAspectRatio: 1,
 | 
			
		||||
      child: PullexRefresh(
 | 
			
		||||
        controller: refreshController,
 | 
			
		||||
        onRefresh: () async {
 | 
			
		||||
          try {
 | 
			
		||||
            await mediaController.handleRefresh();
 | 
			
		||||
          } finally {
 | 
			
		||||
            refreshController.refreshCompleted();
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        header: const WaterDropHeader(),
 | 
			
		||||
        child: Obx(
 | 
			
		||||
          () => GridView.builder(
 | 
			
		||||
            addAutomaticKeepAlives: false,
 | 
			
		||||
            controller: scrollController,
 | 
			
		||||
            shrinkWrap: true,
 | 
			
		||||
            physics: const NeverScrollableScrollPhysics(),
 | 
			
		||||
            padding: const EdgeInsets.all(4),
 | 
			
		||||
            itemCount: mediaController.items.length,
 | 
			
		||||
            gridDelegate: settingsController.crossAxisCount.value == 0
 | 
			
		||||
                ? const SliverGridDelegateWithMaxCrossAxisExtent(
 | 
			
		||||
                    maxCrossAxisExtent: 150,
 | 
			
		||||
                    crossAxisSpacing: 5,
 | 
			
		||||
                    mainAxisSpacing: 5,
 | 
			
		||||
                    childAspectRatio: 1,
 | 
			
		||||
                  )
 | 
			
		||||
                : SliverGridDelegateWithFixedCrossAxisCount(
 | 
			
		||||
                    crossAxisCount: settingsController.crossAxisCount.value,
 | 
			
		||||
                    crossAxisSpacing: 5,
 | 
			
		||||
                    mainAxisSpacing: 5,
 | 
			
		||||
                    childAspectRatio: 1,
 | 
			
		||||
                  ),
 | 
			
		||||
            itemBuilder: (context, index) {
 | 
			
		||||
              final MediaItem item = mediaController.items[index];
 | 
			
		||||
              return Hero(
 | 
			
		||||
                tag: 'media_${item.id}',
 | 
			
		||||
                child: Material(
 | 
			
		||||
                  type: MaterialType.transparency,
 | 
			
		||||
                  child: GestureDetector(
 | 
			
		||||
                    key: ValueKey(item.id),
 | 
			
		||||
                    onTap: () => Get.toNamed('/${item.id}'),
 | 
			
		||||
                    child: MediaTile(item: item),
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
          itemBuilder: (context, index) {
 | 
			
		||||
            final MediaItem item = mediaController.items[index];
 | 
			
		||||
            return Hero(
 | 
			
		||||
              tag: 'media_${item.id}',
 | 
			
		||||
              child: Material(
 | 
			
		||||
                type: MaterialType.transparency,
 | 
			
		||||
                child: GestureDetector(
 | 
			
		||||
                  key: ValueKey(item.id),
 | 
			
		||||
                  onTap: () => Get.toNamed('/${item.id}'),
 | 
			
		||||
                  child: MediaTile(item: item),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            );
 | 
			
		||||
          },
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user