v1.4.1+62
All checks were successful
Flutter Schmutter / build (push) Successful in 3m48s

This commit is contained in:
2025-06-21 13:40:44 +02:00
parent 2b5aaad331
commit 73a44bb269
15 changed files with 608 additions and 515 deletions

View File

@@ -1,42 +0,0 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
class FavoriteAvatars extends StatelessWidget {
final List favorites;
final Brightness brightness;
const FavoriteAvatars({
super.key,
required this.favorites,
required this.brightness,
});
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
...favorites.map((favorite) {
return Container(
height: 32,
width: 32,
margin: const EdgeInsets.only(right: 5.0),
decoration: BoxDecoration(
border: Border.all(
color: brightness == Brightness.dark
? Colors.white
: Colors.black,
width: 1.0,
),
),
child: CachedNetworkImage(
imageUrl: favorite.avatarUrl,
fit: BoxFit.cover,
),
);
}),
],
);
}
}

View File

@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:get/get.dart';
import 'package:f0ckapp/controller/authcontroller.dart';
import 'package:f0ckapp/controller/mediacontroller.dart';
import 'package:f0ckapp/models/item.dart';
class FavoriteSection extends StatelessWidget {
final MediaItem item;
final int index;
final MediaController mediaController = Get.find<MediaController>();
final AuthController authController = Get.find<AuthController>();
FavoriteSection({super.key, required this.item, required this.index});
@override
Widget build(BuildContext context) {
final bool isFavorite =
item.favorites?.any((f) => f.userId == authController.userId.value) ??
false;
return Row(
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
...(item.favorites ?? []).map((favorite) {
return Container(
height: 32,
width: 32,
margin: const EdgeInsets.only(right: 5.0),
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).brightness == Brightness.dark
? Colors.white
: Colors.black,
width: 1.0,
),
),
child: CachedNetworkImage(
imageUrl: favorite.avatarUrl,
fit: BoxFit.cover,
),
);
}),
],
),
),
),
IconButton(
icon: isFavorite
? const Icon(Icons.favorite)
: const Icon(Icons.favorite_outline),
color: Colors.red,
onPressed: () async {
final List<Favorite>? newFavorites = await mediaController
.toggleFavorite(item, isFavorite);
if (newFavorites != null) {
mediaController.items[index] = item.copyWith(
favorites: newFavorites,
);
mediaController.items.refresh();
}
},
),
],
);
}
}

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:get/get.dart';
import 'package:f0ckapp/models/item.dart';
@@ -13,9 +12,6 @@ class MediaTile extends StatelessWidget {
Widget build(BuildContext context) {
return RepaintBoundary(
child: InkWell(
onTap: () {
Get.toNamed('/${item.id}');
},
child: Stack(
fit: StackFit.expand,
children: [

View File

@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:f0ckapp/controller/mediacontroller.dart';
class TagFooter extends StatelessWidget {
final MediaController mediaController = Get.find<MediaController>();
TagFooter({super.key});
@override
Widget build(BuildContext context) {
return Obx(() {
if (mediaController.tag.value != null) {
return Center(
child: InputChip(
label: Text(mediaController.tag.value!),
onDeleted: () {
mediaController.setTag(null);
Get.offAllNamed('/');
},
),
);
} else {
return const SizedBox.shrink();
}
});
}
}

View File

@@ -14,12 +14,14 @@ class VideoWidget extends StatefulWidget {
final MediaItem details;
final bool isActive;
final bool fullScreen;
final VoidCallback? onInitialized;
const VideoWidget({
super.key,
required this.details,
required this.isActive,
this.fullScreen = false,
this.onInitialized,
});
@override
@@ -29,6 +31,7 @@ class VideoWidget extends StatefulWidget {
class _VideoWidgetState extends State<VideoWidget> {
final MediaController controller = Get.find<MediaController>();
late CachedVideoPlayerPlusController _controller;
late Worker _muteWorker;
bool _showControls = false;
Timer? _hideControlsTimer;
@@ -36,6 +39,11 @@ class _VideoWidgetState extends State<VideoWidget> {
void initState() {
super.initState();
_initController();
_muteWorker = ever(controller.muted, (bool muted) {
if (_controller.value.isInitialized) {
_controller.setVolume(muted ? 0.0 : 1.0);
}
});
}
Future<void> _initController() async {
@@ -43,6 +51,8 @@ class _VideoWidgetState extends State<VideoWidget> {
Uri.parse(widget.details.mediaUrl),
);
await _controller.initialize();
widget.onInitialized?.call();
if (!mounted) return;
setState(() {});
_controller.addListener(() => setState(() {}));
_controller.setLooping(true);
@@ -67,6 +77,7 @@ class _VideoWidgetState extends State<VideoWidget> {
@override
void dispose() {
_muteWorker.dispose();
_controller.dispose();
_hideControlsTimer?.cancel();
super.dispose();
@@ -87,11 +98,6 @@ class _VideoWidgetState extends State<VideoWidget> {
@override
Widget build(BuildContext context) {
final bool muted = controller.muted.value;
if (_controller.value.isInitialized &&
_controller.value.volume != (muted ? 0.0 : 1.0)) {
_controller.setVolume(muted ? 0.0 : 1.0);
}
bool isAudio = widget.details.mime.startsWith('audio');
Widget mediaContent;
@@ -131,7 +137,6 @@ class _VideoWidgetState extends State<VideoWidget> {
muted: muted,
onMuteToggle: () {
controller.toggleMuted();
setState(() {});
},
),
),