Compare commits
15 Commits
v1.1.1+32
...
v1.1.12+42
Author | SHA1 | Date | |
---|---|---|---|
5876c809a5 | |||
c35308fbc1 | |||
e945844151 | |||
74eb6e3d26 | |||
9755066d1e | |||
671b3cfbe0 | |||
93fb3536ee | |||
346e447d5e | |||
f7777821fd | |||
ffbde73300 | |||
836a0886e2 | |||
1cd10b3809 | |||
43c42ac0d5 | |||
bf4e0fa493 | |||
27476fbc1d |
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 f0ck
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
52
README.md
@ -1,16 +1,48 @@
|
|||||||
# f0ckapp
|
# fApp
|
||||||
|

|
||||||
|
## Overview
|
||||||
|
|
||||||
A new Flutter project.
|
fApp is the mobile application for the website [f0ck.me](https://f0ck.me). This app provides a user-friendly interface to access the content of the website and utilize its features conveniently from your mobile device.
|
||||||
|
|
||||||
## Getting Started
|
## Installation
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
fApp is available in its own F-Droid repository.
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
### Installation Steps
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
1. Add the F-Droid repository to your F-Droid app:
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
- Go to the settings in the F-Droid app.
|
||||||
|
- Select "Repositories" and add the URL `https://fdroid.flumm.io/fdroid/repo/`.
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
2. Search for "f0ckapp" in the F-Droid app and install the app.
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
|
||||||
samples, guidance on mobile development, and a full API reference.
|
## Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Flutter SDK
|
||||||
|
- Dart SDK
|
||||||
|
- Android Studio or Visual Studio Code
|
||||||
|
|
||||||
|
### Setting Up the Project
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone https://git.lat/f0ck/fApp.git
|
||||||
|
cd fApp
|
||||||
|
2. Install dependencies:
|
||||||
|
```flutter pub get```
|
||||||
|
3. Run the app:
|
||||||
|
```flutter run```
|
||||||
|
|
||||||
|
### Contributing
|
||||||
|
|
||||||
|
don't.
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License. See the LICENSE file for more information.
|
||||||
|
|
||||||
|
### Contact
|
||||||
|
|
||||||
|
For questions or feedback, you can reach us at [contact@f0ck.me](mailto:contact@f0ck.me).
|
||||||
|
@ -11,12 +11,12 @@ android {
|
|||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="f0ckapp"
|
android:label="f0ckapp"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:enableOnBackInvokedCallback="true">
|
android:enableOnBackInvokedCallback="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@ -29,12 +30,26 @@
|
|||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<meta-data android:name="flutter_deeplinking_enabled" android:value="false"/>
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
<data android:scheme="https" android:host="f0ck.me"/>
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
<data android:scheme="f0ck" android:host="com.f0ck.f0ckapp"/>
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||||
|
</adaptive-icon>
|
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 3.5 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 839 B |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 4.5 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 446 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.4 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.2 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 6.4 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 133 KiB |
After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 17 KiB |
BIN
android/app/src/main/res/play_store_512.png
Normal file
After Width: | Height: | Size: 345 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 447 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 192 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.7 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 7.0 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png
Normal file
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 2.2 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png
Normal file
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png
Normal file
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 43 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png
Normal file
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 36 KiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png
Normal file
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 1.1 MiB |
BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -1,42 +1,89 @@
|
|||||||
|
import 'package:f0ckapp/providers/media_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:f0ckapp/providers/MediaProvider.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:f0ckapp/providers/ThemeProvider.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:f0ckapp/screens/MediaGrid.dart';
|
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||||
import 'package:f0ckapp/utils/AppVersion.dart';
|
|
||||||
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:f0ckapp/screens/mediagrid_screen.dart';
|
||||||
|
import 'package:f0ckapp/screens/detailview_screen.dart';
|
||||||
|
import 'package:f0ckapp/utils/appversion_util.dart';
|
||||||
|
import 'package:f0ckapp/providers/theme_provider.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||||
|
await FlutterDownloader.initialize();
|
||||||
await AppVersion.init();
|
await AppVersion.init();
|
||||||
|
|
||||||
runApp(
|
runApp(ProviderScope(child: F0ckApp()));
|
||||||
MultiProvider(
|
|
||||||
providers: [
|
|
||||||
ChangeNotifierProvider(create: (context) => ThemeProvider()),
|
|
||||||
ChangeNotifierProvider(create: (context) => MediaProvider())
|
|
||||||
],
|
|
||||||
child: F0ckApp()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class F0ckApp extends StatelessWidget {
|
class F0ckApp extends ConsumerWidget {
|
||||||
const F0ckApp({super.key});
|
F0ckApp({super.key});
|
||||||
|
|
||||||
|
final GoRouter _router = GoRouter(
|
||||||
|
initialLocation: '/',
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: '/',
|
||||||
|
builder: (BuildContext context, GoRouterState state) {
|
||||||
|
return const MediaGrid();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/:rest(.*)',
|
||||||
|
builder: (context, state) {
|
||||||
|
final bool isInternalLink = (state.extra is bool && state.extra == true);
|
||||||
|
final String fullPath = state.matchedLocation;
|
||||||
|
|
||||||
|
final regExp = RegExp(
|
||||||
|
r'^(?:/tag/(?<tag>.+?))?(?:/(?<mime>image|audio|video))?(?:/(?<itemid>\d+))?$',
|
||||||
|
);
|
||||||
|
final RegExpMatch? match = regExp.firstMatch(fullPath);
|
||||||
|
|
||||||
|
if (match == null) {
|
||||||
|
return const Scaffold(body: Center(child: Text('Ungültiger Link')));
|
||||||
|
}
|
||||||
|
|
||||||
|
final String? tag = match.namedGroup('tag');
|
||||||
|
final String? mime = match.namedGroup('mime');
|
||||||
|
final String? idStr = match.namedGroup('itemid');
|
||||||
|
final int? itemId = idStr != null ? int.tryParse(idStr) : null;
|
||||||
|
const int preloadOffset = 50;
|
||||||
|
|
||||||
|
return Consumer(
|
||||||
|
builder: (BuildContext context, WidgetRef ref, Widget? child) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
final MediaNotifier mediaNotifier = ref.read(mediaProvider.notifier);
|
||||||
|
if (!isInternalLink) {
|
||||||
|
mediaNotifier.setType(mime ?? "alles");
|
||||||
|
mediaNotifier.setTag(tag);
|
||||||
|
}
|
||||||
|
if (itemId != null) {
|
||||||
|
await mediaNotifier.loadMedia(id: itemId + preloadOffset);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (itemId != null) {
|
||||||
|
return DetailView(initialItemId: itemId);
|
||||||
|
} else {
|
||||||
|
return MediaGrid();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final themeProvider = Provider.of<ThemeProvider>(context);
|
final ThemeData theme = ref.watch(themeNotifierProvider);
|
||||||
|
return MaterialApp.router(
|
||||||
return MaterialApp(
|
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: themeProvider.themeData,
|
routerConfig: _router,
|
||||||
home: Scaffold(
|
theme: theme,
|
||||||
body: MediaGrid(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
lib/models/suggestion_model.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class Suggestion {
|
||||||
|
final String tag;
|
||||||
|
final int tagged;
|
||||||
|
final double score;
|
||||||
|
|
||||||
|
Suggestion({
|
||||||
|
required this.tag,
|
||||||
|
required this.tagged,
|
||||||
|
required this.score,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Suggestion.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Suggestion(
|
||||||
|
tag: json['tag'].toString(),
|
||||||
|
tagged: json['tagged'],
|
||||||
|
score: (json['score'] as num).toDouble(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,95 +0,0 @@
|
|||||||
import 'package:f0ckapp/services/Api.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:f0ckapp/models/MediaItem.dart';
|
|
||||||
|
|
||||||
class MediaProvider extends ChangeNotifier {
|
|
||||||
int _typeid = 0;
|
|
||||||
int _mode = 0;
|
|
||||||
bool _random = false;
|
|
||||||
String? _tag;
|
|
||||||
int _crossAxisCount = 0;
|
|
||||||
List<MediaItem> _mediaItems = [];
|
|
||||||
bool _isLoading = false;
|
|
||||||
|
|
||||||
List<String> types = ["alles", "image", "video", "audio"];
|
|
||||||
List<String> modes = ["sfw", "nsfw", "untagged", "all"];
|
|
||||||
|
|
||||||
String get type => types[_typeid];
|
|
||||||
int get typeid => _typeid;
|
|
||||||
int get mode => _mode;
|
|
||||||
bool get random => _random;
|
|
||||||
String? get tag => _tag;
|
|
||||||
int get crossAxisCount => _crossAxisCount;
|
|
||||||
List<MediaItem> get mediaItems => _mediaItems;
|
|
||||||
bool get isLoading => _isLoading;
|
|
||||||
Function get resetMedia => _resetMedia;
|
|
||||||
|
|
||||||
void setType(String type) {
|
|
||||||
_typeid = types.indexOf(type);
|
|
||||||
_resetMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMode(int mode) {
|
|
||||||
_mode = mode;
|
|
||||||
_resetMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
void toggleRandom() {
|
|
||||||
_random = !_random;
|
|
||||||
_resetMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTag(String? tag) {
|
|
||||||
_tag = tag;
|
|
||||||
_resetMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCrossAxisCount(int crossAxisCount) {
|
|
||||||
_crossAxisCount = crossAxisCount;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMediaItems(List<MediaItem> mediaItems) {
|
|
||||||
if (_mediaItems != mediaItems) {
|
|
||||||
_mediaItems.clear();
|
|
||||||
_mediaItems.addAll(mediaItems);
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMediaItems(List<MediaItem> newItems) {
|
|
||||||
_mediaItems.addAll(newItems);
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _resetMedia() {
|
|
||||||
_mediaItems.clear();
|
|
||||||
notifyListeners();
|
|
||||||
loadMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> loadMedia({bool notify = true}) async {
|
|
||||||
if (_isLoading) return;
|
|
||||||
_isLoading = true;
|
|
||||||
if (notify) notifyListeners();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final newMedia = await fetchMedia(
|
|
||||||
older: _mediaItems.isNotEmpty ? _mediaItems.last.id : null,
|
|
||||||
type: type,
|
|
||||||
mode: mode,
|
|
||||||
random: random,
|
|
||||||
tag: tag,
|
|
||||||
);
|
|
||||||
|
|
||||||
if(_mediaItems != newMedia) {
|
|
||||||
addMediaItems(newMedia);
|
|
||||||
if (notify) notifyListeners();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('Fehler beim Laden der Medien: $e');
|
|
||||||
} finally {
|
|
||||||
_isLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|