v1.3.3+59
All checks were successful
Flutter Schmutter / build (push) Successful in 3m47s

This commit is contained in:
2025-06-17 19:03:40 +02:00
parent 089fe1f8df
commit ee2db04a36
19 changed files with 667 additions and 136 deletions

View File

@ -3,11 +3,11 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:get/get.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:share_plus/share_plus.dart';
import 'package:f0ckapp/service/media_service.dart';
import 'package:f0ckapp/utils/animatedtransition.dart';
import 'package:f0ckapp/utils/smartrefreshindicator.dart';
import 'package:f0ckapp/controller/media_controller.dart';
@ -15,7 +15,7 @@ import 'package:f0ckapp/models/media_item.dart';
import 'package:f0ckapp/screens/media_grid.dart';
import 'package:f0ckapp/screens/fullscreen_screen.dart';
import 'package:f0ckapp/widgets/end_drawer.dart';
import 'package:f0ckapp/widgets/video_widget.dart';
import 'package:f0ckapp/widgets/detailmediacontent.dart';
class DetailView extends StatefulWidget {
final int initialId;
@ -42,6 +42,12 @@ class _DetailViewState extends State<DetailView> {
});
}
@override
void dispose() {
_pageController?.dispose();
super.dispose();
}
Future<void> _setupInitialView() async {
bool itemExists = controller.mediaItems.any(
(media) => media.id == widget.initialId,
@ -54,15 +60,16 @@ class _DetailViewState extends State<DetailView> {
}
void _initializePageController() {
_currentPage = controller.mediaItems.indexWhere(
final page = controller.mediaItems.indexWhere(
(media) => media.id == widget.initialId,
);
if (_currentPage < 0) _currentPage = 0;
_pageController = PageController(initialPage: _currentPage)
..addListener(() {
setState(() => _currentPage = _pageController!.page!.round());
});
setState(() {});
setState(() {
_currentPage = page < 0 ? 0 : page;
_pageController = PageController(initialPage: _currentPage)
..addListener(() {
setState(() => _currentPage = _pageController!.page!.round());
});
});
}
Future<void> _downloadMedia(MediaItem item) async {
@ -106,7 +113,9 @@ class _DetailViewState extends State<DetailView> {
@override
Widget build(BuildContext context) {
if (isLoading) {
final MediaService mediaService = Get.find<MediaService>();
if (isLoading || controller.mediaItems.isEmpty || _pageController == null) {
return Scaffold(
appBar: AppBar(
title: const Text("f0ck"),
@ -135,7 +144,7 @@ class _DetailViewState extends State<DetailView> {
label: Text(controller.tag.value!),
onDeleted: () {
controller.setTag(null);
Get.offAllNamed('/');
Get.offAll(() => const MediaGrid());
},
),
),
@ -152,10 +161,11 @@ class _DetailViewState extends State<DetailView> {
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.canPop(context)
? Get.back()
: Get.offAllNamed('/');
}
Navigator.popUntil(
context,
(route) => route.settings.name == '/' || route.isFirst,
);
},
),
actions: [
IconButton(
@ -254,57 +264,22 @@ class _DetailViewState extends State<DetailView> {
},
child: SmartRefreshIndicator(
onRefresh: () async {
_showMsg('not hehe');
final MediaItem? refreshed = await mediaService.fetchItem(
pageItem.id,
);
if (refreshed != null) {
controller.mediaItems[index] = refreshed;
controller.mediaItems.refresh();
}
},
child: SafeArea(
top: false,
child: SingleChildScrollView(
child: Column(
children: [
if (pageItem.mime.startsWith('image'))
CachedNetworkImage(
imageUrl: pageItem.mediaUrl,
fit: BoxFit.contain,
placeholder: (context, url) => const Center(
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
const Center(child: Icon(Icons.error)),
)
else
VideoWidget(
details: pageItem,
isActive: index == _currentPage,
),
const SizedBox(height: 10, width: double.infinity),
Wrap(
alignment: WrapAlignment.center,
spacing: 5.0,
children: pageItem.tags.map((tag) {
return ActionChip(
onPressed: () {
if (tag.tag == 'sfw' || tag.tag == 'nsfw') {
return;
}
controller.setTag(tag.tag);
Get.offAllNamed('/');
},
label: Text(tag.tag),
backgroundColor: switch (tag.id) {
1 => Colors.green,
2 => Colors.red,
_ => const Color(0xFF090909),
},
labelStyle: const TextStyle(
color: Colors.white,
),
);
}).toList(),
),
const SizedBox(height: 20),
],
),
),
child: DetailMediaContent(
currentPage: _currentPage,
index: index,
onTagTap: (tag) {
if (tag == 'sfw' || tag == 'nsfw') return;
controller.setTag(tag);
Get.offAllNamed('/');
},
),
),
);

View File

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:f0ckapp/controller/auth_controller.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<StatefulWidget> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final AuthController authController = Get.find();
final TextEditingController usernameController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
void _showMsg(String message, {String title = ''}) {
Get
..closeAllSnackbars()
..snackbar(message, title, snackPosition: SnackPosition.BOTTOM);
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(floating: false, pinned: true, title: Text('Login')),
SliverList(
delegate: SliverChildListDelegate([
ListTile(
title: Text('Benutzername'),
subtitle: TextField(controller: usernameController),
),
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'),
),
]),
),
],
),
);
}
}