login feature

This commit is contained in:
Simon Ding
2024-07-12 10:06:26 +08:00
parent a172ca0361
commit 60c3c8822e
16 changed files with 751 additions and 16 deletions

View File

@@ -1,4 +1,8 @@
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
class APIs {
static final _baseUrl = baseUrl();
@@ -14,16 +18,50 @@ class APIs {
static final addDownloadClientUrl = "$_baseUrl/api/v1/downloader/add";
static final delDownloadClientUrl = "$_baseUrl/api/v1/downloader/del/";
static final storageUrl = "$_baseUrl/api/v1/storage/";
static final loginUrl = "$_baseUrl/api/login";
static final loginSettingUrl = "$_baseUrl/api/v1/setting/auth";
static const tmdbImgBaseUrl = "https://image.tmdb.org/t/p/w500/";
static const tmdbApiKey = "tmdb_api_key";
static const downloadDirKey = "download_dir";
static final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
static String baseUrl() {
if (kReleaseMode) {
return "";
}
return "http://127.0.0.1:8080";
}
static Dio? dio1;
static Future<Dio> getDio() async {
if (dio1 != null) {
return dio1!;
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString("token");
var dio = Dio();
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
options.headers['Authorization'] = "Bearer $token";
return handler.next(options);
},
onError: (error, handler) {
if (error.response?.statusCode != null &&
error.response?.statusCode! == 403) {
final context = navigatorKey.currentContext;
if (context != null) {
context.go('/login');
}
}
return handler.next(error);
},
));
dio1 = dio;
return dio;
}
}

View File

@@ -0,0 +1,61 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:ui/providers/APIs.dart';
import 'package:ui/providers/server_response.dart';
var authSettingProvider =
AsyncNotifierProvider.autoDispose<AuthSettingData, AuthSetting>(
AuthSettingData.new);
class AuthSettingData extends AutoDisposeAsyncNotifier<AuthSetting> {
@override
FutureOr<AuthSetting> build() async {
final dio = await APIs.getDio();
var resp = await dio.get(APIs.loginSettingUrl);
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
throw sp.message;
}
var as = AuthSetting.fromJson(sp.data);
return as;
}
Future<void> updateAuthSetting(
bool enable, String user, String password) async {
final dio = await APIs.getDio();
var resp = await dio.post(APIs.loginSettingUrl,
data: {"enable": enable, "user": user, "password": password});
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
throw sp.message;
}
ref.invalidateSelf();
}
Future<void> login(String user, String password) async {
var resp = await Dio()
.post(APIs.loginUrl, data: {"user": user, "password": password});
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
throw sp.message;
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("token", sp.data["token"]);
}
}
class AuthSetting {
bool enable;
String user;
AuthSetting({required this.enable, required this.user});
factory AuthSetting.fromJson(Map<String, dynamic> json) {
return AuthSetting(enable: json["enable"], user: json["user"]);
}
}

View File

@@ -12,7 +12,8 @@ class SeriesDetailData
extends AutoDisposeFamilyAsyncNotifier<SeriesDetails, String> {
@override
FutureOr<SeriesDetails> build(String arg) async {
var resp = await Dio().get("${APIs.seriesDetailUrl}$arg");
final dio = await APIs.getDio();
var resp = await dio.get("${APIs.seriesDetailUrl}$arg");
var rsp = ServerResponse.fromJson(resp.data);
if (rsp.code != 0) {
throw rsp.message;
@@ -22,7 +23,8 @@ class SeriesDetailData
Future<String> searchAndDownload(
String seriesId, int seasonNum, int episodeNum) async {
var resp = await Dio().post(APIs.searchAndDownloadUrl, data: {
final dio = await APIs.getDio();
var resp = await dio.post(APIs.searchAndDownloadUrl, data: {
"id": int.parse(seriesId),
"season": seasonNum,
"episode": episodeNum,

View File

@@ -22,11 +22,11 @@ var storageSettingProvider =
StorageSettingData.new);
class EditSettingData extends FamilyAsyncNotifier<String, String> {
final dio = Dio();
String? key;
@override
FutureOr<String> build(String arg) async {
final dio = await APIs.getDio();
key = arg;
var resp = await dio.get(APIs.settingsUrl, queryParameters: {"key": arg});
var rrr = ServerResponse.fromJson(resp.data);
@@ -40,6 +40,7 @@ class EditSettingData extends FamilyAsyncNotifier<String, String> {
}
Future<void> updateSettings(String v) async {
final dio = await APIs.getDio();
var resp = await dio.post(APIs.settingsUrl, data: {
"key": key,
"value": v,
@@ -53,10 +54,9 @@ class EditSettingData extends FamilyAsyncNotifier<String, String> {
}
class IndexerSetting extends AsyncNotifier<List<Indexer>> {
final dio = Dio();
@override
FutureOr<List<Indexer>> build() async {
final dio = await APIs.getDio();
var resp = await dio.get(APIs.allIndexersUrl);
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -75,6 +75,7 @@ class IndexerSetting extends AsyncNotifier<List<Indexer>> {
isBlank(indexer.apiKey)) {
return;
}
final dio = await APIs.getDio();
var resp = await dio.post(APIs.addIndexerUrl, data: indexer.toJson());
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -84,6 +85,7 @@ class IndexerSetting extends AsyncNotifier<List<Indexer>> {
}
Future<void> deleteIndexer(int id) async {
final dio = await APIs.getDio();
var resp = await dio.delete("${APIs.delIndexerUrl}$id");
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -117,10 +119,9 @@ class Indexer {
}
class DownloadClientSetting extends AsyncNotifier<List<DownloadClient>> {
final dio = Dio();
@override
FutureOr<List<DownloadClient>> build() async {
final dio = await APIs.getDio();
var resp = await dio.get(APIs.allDownloadClientsUrl);
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -137,7 +138,7 @@ class DownloadClientSetting extends AsyncNotifier<List<DownloadClient>> {
if (name.isEmpty || url.isEmpty) {
return;
}
var dio = Dio();
final dio = await APIs.getDio();
var resp = await dio.post(APIs.addDownloadClientUrl, data: {
"name": name,
"url": url,
@@ -150,7 +151,7 @@ class DownloadClientSetting extends AsyncNotifier<List<DownloadClient>> {
}
Future<void> deleteDownloadClients(int id) async {
var dio = Dio();
final dio = await APIs.getDio();
var resp = await dio.delete("${APIs.delDownloadClientUrl}$id");
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -202,9 +203,10 @@ class DownloadClient {
}
class StorageSettingData extends AsyncNotifier<List<Storage>> {
final dio = Dio();
@override
FutureOr<List<Storage>> build() async {
final dio = await APIs.getDio();
var resp = await dio.get(APIs.storageUrl);
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -219,6 +221,7 @@ class StorageSettingData extends AsyncNotifier<List<Storage>> {
}
Future<void> deleteStorage(int id) async {
final dio = await APIs.getDio();
var resp = await dio.delete("${APIs.storageUrl}$id");
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
@@ -228,6 +231,7 @@ class StorageSettingData extends AsyncNotifier<List<Storage>> {
}
Future<void> addStorage(Storage s) async {
final dio = await APIs.getDio();
var resp = await dio.post(APIs.storageUrl, data: s.toJson());
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {

View File

@@ -6,7 +6,8 @@ import 'package:ui/providers/APIs.dart';
import 'package:ui/providers/server_response.dart';
final welcomePageDataProvider = FutureProvider((ref) async {
var resp = await Dio().get(APIs.watchlistUrl);
final dio = await APIs.getDio();
var resp = await dio.get(APIs.watchlistUrl);
var sp = ServerResponse.fromJson(resp.data);
List<TvSeries> favList = List.empty(growable: true);
for (var item in sp.data as List) {
@@ -39,7 +40,7 @@ class SearchPageData extends AutoDisposeAsyncNotifier<List<SearchResult>> {
}
void queryResults(String q) async {
final dio = Dio();
final dio = await APIs.getDio();
var resp = await dio.get(APIs.searchUrl, queryParameters: {"query": q});
//var dy = jsonDecode(resp.data.toString());