This commit is contained in:
		@@ -15,6 +15,8 @@ class _LoginPageState extends State<LoginPage> {
 | 
				
			|||||||
  final TextEditingController usernameController = TextEditingController();
 | 
					  final TextEditingController usernameController = TextEditingController();
 | 
				
			||||||
  final TextEditingController passwordController = TextEditingController();
 | 
					  final TextEditingController passwordController = TextEditingController();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool _isLoading = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _showMsg(String message, {String title = ''}) {
 | 
					  void _showMsg(String message, {String title = ''}) {
 | 
				
			||||||
    Get
 | 
					    Get
 | 
				
			||||||
      ..closeAllSnackbars()
 | 
					      ..closeAllSnackbars()
 | 
				
			||||||
@@ -31,37 +33,88 @@ class _LoginPageState extends State<LoginPage> {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      body: CustomScrollView(
 | 
					      body: Center(
 | 
				
			||||||
        slivers: [
 | 
					        child: SingleChildScrollView(
 | 
				
			||||||
          SliverAppBar(floating: false, pinned: true, title: Text('Login')),
 | 
					          padding: const EdgeInsets.all(24),
 | 
				
			||||||
          SliverList(
 | 
					          child: Card(
 | 
				
			||||||
            delegate: SliverChildListDelegate([
 | 
					            elevation: 8,
 | 
				
			||||||
              ListTile(
 | 
					            shape: RoundedRectangleBorder(
 | 
				
			||||||
                title: Text('Benutzername'),
 | 
					              borderRadius: BorderRadius.circular(16),
 | 
				
			||||||
                subtitle: TextField(controller: usernameController),
 | 
					            ),
 | 
				
			||||||
 | 
					            child: Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(24),
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  Row(
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      IconButton(
 | 
				
			||||||
 | 
					                        icon: const Icon(Icons.arrow_back),
 | 
				
			||||||
 | 
					                        tooltip: 'Zurück',
 | 
				
			||||||
 | 
					                        onPressed: () => Get.back(),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      const SizedBox(width: 8),
 | 
				
			||||||
 | 
					                      Text(
 | 
				
			||||||
 | 
					                        'Login',
 | 
				
			||||||
 | 
					                        style: Theme.of(context).textTheme.headlineMedium,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  const SizedBox(height: 24),
 | 
				
			||||||
 | 
					                  TextField(
 | 
				
			||||||
 | 
					                    controller: usernameController,
 | 
				
			||||||
 | 
					                    decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                      labelText: 'Benutzername',
 | 
				
			||||||
 | 
					                      prefixIcon: Icon(Icons.person),
 | 
				
			||||||
 | 
					                      border: OutlineInputBorder(),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                  TextField(
 | 
				
			||||||
 | 
					                    controller: passwordController,
 | 
				
			||||||
 | 
					                    obscureText: true,
 | 
				
			||||||
 | 
					                    decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                      labelText: 'Passwort',
 | 
				
			||||||
 | 
					                      prefixIcon: Icon(Icons.lock),
 | 
				
			||||||
 | 
					                      border: OutlineInputBorder(),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  const SizedBox(height: 24),
 | 
				
			||||||
 | 
					                  SizedBox(
 | 
				
			||||||
 | 
					                    width: double.infinity,
 | 
				
			||||||
 | 
					                    child: ElevatedButton(
 | 
				
			||||||
 | 
					                      onPressed: _isLoading
 | 
				
			||||||
 | 
					                          ? null
 | 
				
			||||||
 | 
					                          : () async {
 | 
				
			||||||
 | 
					                              setState(() => _isLoading = true);
 | 
				
			||||||
 | 
					                              final success = await authController.login(
 | 
				
			||||||
 | 
					                                usernameController.text,
 | 
				
			||||||
 | 
					                                passwordController.text,
 | 
				
			||||||
 | 
					                              );
 | 
				
			||||||
 | 
					                              setState(() => _isLoading = false);
 | 
				
			||||||
 | 
					                              if (!success) {
 | 
				
			||||||
 | 
					                                return _showMsg('Login fehlgeschlagen!');
 | 
				
			||||||
 | 
					                              }
 | 
				
			||||||
 | 
					                              _showMsg('Erfolgreich eingeloggt.');
 | 
				
			||||||
 | 
					                              Get.back();
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                      child: _isLoading
 | 
				
			||||||
 | 
					                          ? const SizedBox(
 | 
				
			||||||
 | 
					                              width: 24,
 | 
				
			||||||
 | 
					                              height: 24,
 | 
				
			||||||
 | 
					                              child: CircularProgressIndicator(
 | 
				
			||||||
 | 
					                                strokeWidth: 2,
 | 
				
			||||||
 | 
					                                color: Colors.white,
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                          : const Text('Login'),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              ListTile(
 | 
					            ),
 | 
				
			||||||
                title: Text('Passwort'),
 | 
					 | 
				
			||||||
                subtitle: TextField(
 | 
					 | 
				
			||||||
                  controller: passwordController,
 | 
					 | 
				
			||||||
                  obscureText: true,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              ElevatedButton(
 | 
					 | 
				
			||||||
                onPressed: () async {
 | 
					 | 
				
			||||||
                  final success = await authController.login(
 | 
					 | 
				
			||||||
                    usernameController.text,
 | 
					 | 
				
			||||||
                    passwordController.text,
 | 
					 | 
				
			||||||
                  );
 | 
					 | 
				
			||||||
                  if (!success) {
 | 
					 | 
				
			||||||
                    _showMsg('Login fehlgeschlagen!');
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                child: Text('Login'),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:get/get.dart';
 | 
					import 'package:get/get.dart';
 | 
				
			||||||
@@ -18,6 +20,7 @@ class MediaGrid extends StatefulWidget {
 | 
				
			|||||||
class _MediaGridState extends State<MediaGrid> {
 | 
					class _MediaGridState extends State<MediaGrid> {
 | 
				
			||||||
  final MediaController controller = Get.find<MediaController>();
 | 
					  final MediaController controller = Get.find<MediaController>();
 | 
				
			||||||
  final ScrollController _scrollController = ScrollController();
 | 
					  final ScrollController _scrollController = ScrollController();
 | 
				
			||||||
 | 
					  Timer? _debounce;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
@@ -31,12 +34,15 @@ class _MediaGridState extends State<MediaGrid> {
 | 
				
			|||||||
    _scrollController.addListener(() {
 | 
					    _scrollController.addListener(() {
 | 
				
			||||||
      if (_scrollController.position.extentAfter < 200 &&
 | 
					      if (_scrollController.position.extentAfter < 200 &&
 | 
				
			||||||
          !controller.isLoading.value) {
 | 
					          !controller.isLoading.value) {
 | 
				
			||||||
        controller.loadMediaItems(
 | 
					        if (_debounce?.isActive ?? false) _debounce!.cancel();
 | 
				
			||||||
          older: controller.mediaItems.isNotEmpty
 | 
					        _debounce = Timer(const Duration(milliseconds: 300), () {
 | 
				
			||||||
              ? controller.mediaItems.last.id
 | 
					          controller.loadMediaItems(
 | 
				
			||||||
              : null,
 | 
					            older: controller.mediaItems.isNotEmpty
 | 
				
			||||||
          append: true,
 | 
					                ? controller.mediaItems.last.id
 | 
				
			||||||
        );
 | 
					                : null,
 | 
				
			||||||
 | 
					            append: true,
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ class EndDrawer extends StatelessWidget {
 | 
				
			|||||||
                    ElevatedButton(
 | 
					                    ElevatedButton(
 | 
				
			||||||
                      onPressed: () {
 | 
					                      onPressed: () {
 | 
				
			||||||
                        Navigator.pop(context);
 | 
					                        Navigator.pop(context);
 | 
				
			||||||
                        Get.bottomSheet(LoginPage(), isDismissible: false);
 | 
					                        Get.to(() => LoginPage());
 | 
				
			||||||
                      },
 | 
					                      },
 | 
				
			||||||
                      child: const Text('Login'),
 | 
					                      child: const Text('Login'),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,34 +12,37 @@ class MediaTile extends StatelessWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return InkWell(
 | 
					    return RepaintBoundary(
 | 
				
			||||||
      onTap: () {
 | 
					      child: InkWell(
 | 
				
			||||||
        Get.toNamed('/${item.id}');
 | 
					        onTap: () {
 | 
				
			||||||
      },
 | 
					          Get.toNamed('/${item.id}');
 | 
				
			||||||
      child: Stack(
 | 
					        },
 | 
				
			||||||
        fit: StackFit.expand,
 | 
					        child: Stack(
 | 
				
			||||||
        children: [
 | 
					          fit: StackFit.expand,
 | 
				
			||||||
          Hero(
 | 
					          children: [
 | 
				
			||||||
            tag: 'media-${item.id}',
 | 
					            Hero(
 | 
				
			||||||
            child: CachedNetworkImage(
 | 
					              tag: 'media-${item.id}',
 | 
				
			||||||
              imageUrl: item.thumbnailUrl,
 | 
					              child: CachedNetworkImage(
 | 
				
			||||||
              fit: BoxFit.cover,
 | 
					                imageUrl: item.thumbnailUrl,
 | 
				
			||||||
              errorWidget: (context, url, error) => const Icon(Icons.error),
 | 
					                fit: BoxFit.cover,
 | 
				
			||||||
 | 
					                placeholder: (content, url) => Container(color: Colors.grey[900]),
 | 
				
			||||||
 | 
					                errorWidget: (context, url, error) => const Icon(Icons.error),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					            Align(
 | 
				
			||||||
          Align(
 | 
					              alignment: Alignment.bottomRight,
 | 
				
			||||||
            alignment: Alignment.bottomRight,
 | 
					              child: Icon(
 | 
				
			||||||
            child: Icon(
 | 
					                Icons.square,
 | 
				
			||||||
              Icons.square,
 | 
					                color: switch (item.mode) {
 | 
				
			||||||
              color: switch (item.mode) {
 | 
					                  1 => Colors.green,
 | 
				
			||||||
                1 => Colors.green,
 | 
					                  2 => Colors.red,
 | 
				
			||||||
                2 => Colors.red,
 | 
					                  _ => Colors.yellow,
 | 
				
			||||||
                _ => Colors.yellow,
 | 
					                },
 | 
				
			||||||
              },
 | 
					                size: 15.0,
 | 
				
			||||||
              size: 15.0,
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ],
 | 
				
			||||||
        ],
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
				
			|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
					# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
				
			||||||
# In Windows, build-name is used as the major, minor, and patch parts
 | 
					# In Windows, build-name is used as the major, minor, and patch parts
 | 
				
			||||||
# of the product and file versions while build-number is used as the build suffix.
 | 
					# of the product and file versions while build-number is used as the build suffix.
 | 
				
			||||||
version: 1.3.3+59
 | 
					version: 1.3.4+60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ^3.9.0-100.2.beta
 | 
					  sdk: ^3.9.0-100.2.beta
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user