This commit is contained in:
@ -1,98 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:encrypt_shared_preferences/provider.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:f0ckapp/controller/media_controller.dart';
|
||||
|
||||
class AuthController extends GetxController {
|
||||
final EncryptedSharedPreferencesAsync storage =
|
||||
EncryptedSharedPreferencesAsync.getInstance();
|
||||
final MediaController mediaController = Get.find<MediaController>();
|
||||
|
||||
RxnString token = RxnString();
|
||||
RxnInt userId = RxnInt();
|
||||
RxnString avatarUrl = RxnString();
|
||||
RxnString username = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
loadToken();
|
||||
}
|
||||
|
||||
Future<void> loadToken() async {
|
||||
token.value = await storage.getString('token');
|
||||
if (token.value != null) {
|
||||
await fetchUserInfo();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveToken(String newToken) async {
|
||||
token.value = newToken;
|
||||
await storage.setString('token', newToken);
|
||||
await fetchUserInfo();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
if (token.value != null) {
|
||||
try {
|
||||
await http.post(
|
||||
Uri.parse('https://api.f0ck.me/logout'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${token.value}',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
await mediaController.loadMediaItems();
|
||||
mediaController.mediaItems.refresh();
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
token.value = null;
|
||||
userId.value = null;
|
||||
avatarUrl.value = null;
|
||||
username.value = null;
|
||||
await storage.remove('token');
|
||||
}
|
||||
|
||||
Future<bool> login(String username, String password) async {
|
||||
final http.Response response = await http.post(
|
||||
Uri.parse('https://api.f0ck.me/login'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({'username': username, 'password': password}),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
final dynamic data = json.decode(response.body);
|
||||
if (data['token'] != null) {
|
||||
await saveToken(data['token']);
|
||||
await mediaController.loadMediaItems();
|
||||
mediaController.mediaItems.refresh();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> fetchUserInfo() async {
|
||||
if (token.value == null) return;
|
||||
final http.Response response = await http.get(
|
||||
Uri.parse('https://api.f0ck.me/login/check'),
|
||||
headers: {'Authorization': 'Bearer ${token.value}'},
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
final dynamic data = json.decode(response.body);
|
||||
userId.value = data['userid'] != null
|
||||
? int.parse(data['userid'].toString())
|
||||
: null;
|
||||
avatarUrl.value = data['avatar'] != null
|
||||
? 'https://f0ck.me/t/${data['avatar']}.webp'
|
||||
: null;
|
||||
username.value = data['user'];
|
||||
} else {
|
||||
await logout();
|
||||
}
|
||||
}
|
||||
}
|
114
lib/controller/authcontroller.dart
Normal file
114
lib/controller/authcontroller.dart
Normal file
@ -0,0 +1,114 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:encrypt_shared_preferences/provider.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class AuthController extends GetxController {
|
||||
final EncryptedSharedPreferencesAsync storage =
|
||||
EncryptedSharedPreferencesAsync.getInstance();
|
||||
|
||||
RxnString token = RxnString();
|
||||
RxnInt userId = RxnInt();
|
||||
RxnString avatarUrl = RxnString();
|
||||
RxnString username = RxnString();
|
||||
RxBool isLoading = false.obs;
|
||||
RxnString error = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
loadToken();
|
||||
}
|
||||
|
||||
Future<void> loadToken() async {
|
||||
token.value = await storage.getString('token');
|
||||
if (token.value != null) {
|
||||
await fetchUserInfo();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveToken(String newToken) async {
|
||||
token.value = newToken;
|
||||
await storage.setString('token', newToken);
|
||||
await fetchUserInfo();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
if (token.value != null) {
|
||||
try {
|
||||
await http.post(
|
||||
Uri.parse('https://api.f0ck.me/logout'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${token.value}',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
} catch (_) {}
|
||||
}
|
||||
token.value = null;
|
||||
userId.value = null;
|
||||
avatarUrl.value = null;
|
||||
username.value = null;
|
||||
await storage.remove('token');
|
||||
}
|
||||
|
||||
Future<bool> login(String username, String password) async {
|
||||
isLoading.value = true;
|
||||
error.value = null;
|
||||
try {
|
||||
final http.Response response = await http.post(
|
||||
Uri.parse('https://api.f0ck.me/login'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({'username': username, 'password': password}),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
final dynamic data = json.decode(response.body);
|
||||
if (data['token'] != null) {
|
||||
await saveToken(data['token']);
|
||||
userId.value = data['userid'];
|
||||
avatarUrl.value = data['avatar'] != null
|
||||
? 'https://f0ck.me/t/${data['avatar']}.webp'
|
||||
: null;
|
||||
this.username.value = data['user'];
|
||||
return true;
|
||||
} else {
|
||||
error.value = 'Kein Token erhalten';
|
||||
}
|
||||
} else {
|
||||
error.value = 'Login fehlgeschlagen';
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = e.toString();
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> fetchUserInfo() async {
|
||||
if (token.value == null) return;
|
||||
try {
|
||||
final http.Response response = await http.get(
|
||||
Uri.parse('https://api.f0ck.me/login/check'),
|
||||
headers: {'Authorization': 'Bearer ${token.value}'},
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
final dynamic data = json.decode(response.body);
|
||||
userId.value = data['userid'] != null
|
||||
? int.tryParse(data['userid'].toString())
|
||||
: null;
|
||||
avatarUrl.value = data['avatar'] != null
|
||||
? 'https://f0ck.me/t/${data['avatar']}.webp'
|
||||
: null;
|
||||
username.value = data['user'];
|
||||
} else {
|
||||
await logout();
|
||||
}
|
||||
} catch (_) {
|
||||
await logout();
|
||||
}
|
||||
}
|
||||
|
||||
bool get isLoggedIn => token.value != null && token.value!.isNotEmpty;
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
import 'package:encrypt_shared_preferences/provider.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:f0ckapp/utils/animatedtransition.dart';
|
||||
import 'package:f0ckapp/service/media_service.dart';
|
||||
import 'package:f0ckapp/models/media_item.dart';
|
||||
|
||||
class MediaController extends GetxController {
|
||||
final EncryptedSharedPreferencesAsync storage =
|
||||
EncryptedSharedPreferencesAsync.getInstance();
|
||||
|
||||
final RxList<MediaItem> mediaItems = <MediaItem>[].obs;
|
||||
final RxBool isLoading = false.obs;
|
||||
final RxString errorMessage = ''.obs;
|
||||
final MediaService _mediaService = MediaService();
|
||||
|
||||
RxnString tag = RxnString();
|
||||
RxInt type = 0.obs;
|
||||
RxInt mode = 0.obs;
|
||||
RxBool random = false.obs;
|
||||
late RxBool muted = false.obs;
|
||||
late RxInt crossAxisCount = 0.obs;
|
||||
late RxBool drawerSwipeEnabled = true.obs;
|
||||
final Rx<PageTransition> transitionType = PageTransition.opacity.obs;
|
||||
|
||||
MediaItem? selectedItem;
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
await loadSettings();
|
||||
}
|
||||
|
||||
Future<void> loadSettings() async {
|
||||
muted.value = await storage.getBoolean('muted') ?? false;
|
||||
crossAxisCount.value = await storage.getInt('crossAxisCount') ?? 0;
|
||||
drawerSwipeEnabled.value =
|
||||
await storage.getBoolean('drawerSwipeEnabled') ?? true;
|
||||
transitionType.value =
|
||||
PageTransition.values[await storage.getInt('transitionType') ?? 0];
|
||||
}
|
||||
|
||||
Future<void> saveSettings() async {
|
||||
await storage.setBoolean('muted', muted.value);
|
||||
await storage.setInt('crossAxisCount', crossAxisCount.value);
|
||||
await storage.setBoolean('drawerSwipeEnabled', drawerSwipeEnabled.value);
|
||||
await storage.setInt('transitionType', transitionType.value.index);
|
||||
}
|
||||
|
||||
Future<void> setTag(String? newTag) async {
|
||||
tag.value = newTag;
|
||||
await loadMediaItems();
|
||||
}
|
||||
|
||||
Future<void> setType(int newType) async {
|
||||
type.value = newType;
|
||||
await loadMediaItems();
|
||||
}
|
||||
|
||||
Future<void> setMode(int newMode) async {
|
||||
mode.value = newMode;
|
||||
await loadMediaItems();
|
||||
}
|
||||
|
||||
Future<void> toggleRandom() async {
|
||||
random.value = !random.value;
|
||||
await loadMediaItems();
|
||||
}
|
||||
|
||||
Future<void> toggleMuted() async {
|
||||
muted.value = !muted.value;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> setCrossAxisCount(int newCrossAxisCount) async {
|
||||
crossAxisCount.value = newCrossAxisCount;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> setDrawerSwipeEnabled(bool newValue) async {
|
||||
drawerSwipeEnabled.value = newValue;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> setTransitionType(PageTransition newType) async {
|
||||
transitionType.value = newType;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> loadMediaItems({int? older, bool append = false}) async {
|
||||
if (isLoading.value) return;
|
||||
try {
|
||||
isLoading.value = true;
|
||||
final List<MediaItem> items = await _mediaService.fetchMediaItems(
|
||||
type: type.value,
|
||||
mode: mode.value,
|
||||
random: random.value ? 1 : 0,
|
||||
tag: tag.value,
|
||||
older: older,
|
||||
);
|
||||
|
||||
append ? mediaItems.addAll(items) : mediaItems.assignAll(items);
|
||||
|
||||
errorMessage.value = '';
|
||||
} catch (e) {
|
||||
errorMessage.value = 'Fehler beim Laden der Daten: ${e.toString()}';
|
||||
Get.snackbar('Error', e.toString());
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
181
lib/controller/mediacontroller.dart
Normal file
181
lib/controller/mediacontroller.dart
Normal file
@ -0,0 +1,181 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:encrypt_shared_preferences/provider.dart';
|
||||
|
||||
import 'package:f0ckapp/models/feed.dart';
|
||||
import 'package:f0ckapp/models/item.dart';
|
||||
import 'package:f0ckapp/services/api.dart';
|
||||
import 'package:f0ckapp/utils/animatedtransition.dart';
|
||||
|
||||
const List<String> mediaTypes = ["alles", "image", "video", "audio"];
|
||||
const List<String> mediaModes = ["sfw", "nsfw", "untagged", "all"];
|
||||
|
||||
class MediaController extends GetxController {
|
||||
final ApiService _api = ApiService();
|
||||
final EncryptedSharedPreferencesAsync storage =
|
||||
EncryptedSharedPreferencesAsync.getInstance();
|
||||
|
||||
RxList<MediaItem> items = <MediaItem>[].obs;
|
||||
RxBool loading = false.obs;
|
||||
RxBool atEnd = false.obs;
|
||||
RxBool atStart = false.obs;
|
||||
|
||||
RxInt typeIndex = 0.obs;
|
||||
RxInt modeIndex = 0.obs;
|
||||
RxInt random = 0.obs;
|
||||
Rxn<String> tag = Rxn<String>();
|
||||
RxBool muted = false.obs;
|
||||
Rx<PageTransition> transitionType = PageTransition.opacity.obs;
|
||||
RxBool drawerSwipeEnabled = true.obs;
|
||||
RxInt crossAxisCount = 0.obs;
|
||||
|
||||
void setTypeIndex(int idx) {
|
||||
typeIndex.value = idx;
|
||||
fetchInitial();
|
||||
}
|
||||
|
||||
void setModeIndex(int idx) {
|
||||
modeIndex.value = idx;
|
||||
fetchInitial();
|
||||
}
|
||||
|
||||
void setTag(String? newTag, {bool reload = true}) {
|
||||
tag.value = newTag;
|
||||
if (reload) {
|
||||
fetchInitial();
|
||||
}
|
||||
}
|
||||
|
||||
List<MediaItem> get filteredItems {
|
||||
final String typeStr = mediaTypes[typeIndex.value];
|
||||
return items.where((item) {
|
||||
final bool typeOk = typeStr == "alles" || item.mime.startsWith(typeStr);
|
||||
return typeOk;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Future<List<Favorite>?> toggleFavorite(
|
||||
MediaItem item,
|
||||
bool isFavorite,
|
||||
) async {
|
||||
try {
|
||||
return await _api.toggleFavorite(item, isFavorite);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchInitial({int? id}) async {
|
||||
loading.value = true;
|
||||
try {
|
||||
final Feed result = await _api.fetchItems(
|
||||
type: typeIndex.value,
|
||||
mode: modeIndex.value,
|
||||
random: random.value,
|
||||
tag: tag.value,
|
||||
older: id,
|
||||
);
|
||||
items.assignAll(result.items);
|
||||
atEnd.value = result.atEnd;
|
||||
atStart.value = result.atStart;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchMore() async {
|
||||
if (items.isEmpty || atEnd.value) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
final Feed result = await _api.fetchItems(
|
||||
older: items.last.id,
|
||||
type: typeIndex.value,
|
||||
mode: modeIndex.value,
|
||||
random: random.value,
|
||||
tag: tag.value,
|
||||
);
|
||||
final List<MediaItem> newItems = result.items
|
||||
.where((item) => !items.any((existing) => existing.id == item.id))
|
||||
.toList();
|
||||
items.addAll(newItems);
|
||||
items.refresh();
|
||||
atEnd.value = result.atEnd;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> fetchNewer() async {
|
||||
if (items.isEmpty || atStart.value) return 0;
|
||||
loading.value = true;
|
||||
try {
|
||||
final Feed result = await _api.fetchItems(
|
||||
newer: items.first.id,
|
||||
type: typeIndex.value,
|
||||
mode: modeIndex.value,
|
||||
random: random.value,
|
||||
tag: tag.value,
|
||||
);
|
||||
int oldLength = filteredItems.length;
|
||||
final List<MediaItem> newItems = result.items
|
||||
.where((item) => !items.any((existing) => existing.id == item.id))
|
||||
.toList();
|
||||
items.insertAll(0, newItems);
|
||||
items.refresh();
|
||||
atStart.value = result.atStart;
|
||||
int newLength = filteredItems.length;
|
||||
return newLength - oldLength;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void toggleMuted() {
|
||||
muted.value = !muted.value;
|
||||
}
|
||||
|
||||
void setMuted(bool value) {
|
||||
muted.value = value;
|
||||
}
|
||||
|
||||
Future<void> setTransitionType(PageTransition type) async {
|
||||
transitionType.value = type;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> setCrossAxisCount(int value) async {
|
||||
crossAxisCount.value = value;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
Future<void> setDrawerSwipeEnabled(bool enabled) async {
|
||||
drawerSwipeEnabled.value = enabled;
|
||||
await saveSettings();
|
||||
}
|
||||
|
||||
void toggleRandom() {
|
||||
random.value = random.value == 1 ? 0 : 1;
|
||||
fetchInitial();
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
await loadSettings();
|
||||
}
|
||||
|
||||
Future<void> loadSettings() async {
|
||||
muted.value = await storage.getBoolean('muted') ?? false;
|
||||
crossAxisCount.value = await storage.getInt('crossAxisCount') ?? 0;
|
||||
drawerSwipeEnabled.value =
|
||||
await storage.getBoolean('drawerSwipeEnabled') ?? true;
|
||||
transitionType.value =
|
||||
PageTransition.values[await storage.getInt('transitionType') ?? 0];
|
||||
}
|
||||
|
||||
Future<void> saveSettings() async {
|
||||
await storage.setBoolean('muted', muted.value);
|
||||
await storage.setInt('crossAxisCount', crossAxisCount.value);
|
||||
await storage.setBoolean('drawerSwipeEnabled', drawerSwipeEnabled.value);
|
||||
await storage.setInt('transitionType', transitionType.value.index);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user