mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-06 10:07:45 +08:00
feat: use cookie to store jwt token, better performance
This commit is contained in:
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:ui/activity.dart';
|
||||
import 'package:ui/login_page.dart';
|
||||
import 'package:ui/movie_watchlist.dart';
|
||||
@@ -177,41 +176,30 @@ class _MainSkeletonState extends State<MainSkeleton> {
|
||||
(BuildContext context, SearchController controller) {
|
||||
return [Text("dadada")];
|
||||
}),
|
||||
FutureBuilder(
|
||||
future: APIs.isLoggedIn(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data == true) {
|
||||
return MenuAnchor(
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.exit_to_app),
|
||||
child: const Text("登出"),
|
||||
onPressed: () async {
|
||||
final SharedPreferences prefs =
|
||||
await SharedPreferences.getInstance();
|
||||
await prefs.remove('token');
|
||||
if (context.mounted) {
|
||||
context.go(LoginScreen.route);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
builder: (context, controller, child) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
if (controller.isOpen) {
|
||||
controller.close();
|
||||
} else {
|
||||
controller.open();
|
||||
}
|
||||
},
|
||||
child: const Icon(Icons.account_circle),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
})
|
||||
MenuAnchor(
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.exit_to_app),
|
||||
child: const Text("登出"),
|
||||
onPressed: () async {
|
||||
await APIs.logout();
|
||||
},
|
||||
),
|
||||
],
|
||||
builder: (context, controller, child) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
if (controller.isOpen) {
|
||||
controller.close();
|
||||
} else {
|
||||
controller.open();
|
||||
}
|
||||
},
|
||||
child: const Icon(Icons.account_circle),
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
useDrawer: false,
|
||||
|
||||
@@ -45,8 +45,8 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
fit: BoxFit.fitWidth,
|
||||
opacity: 0.5,
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg",
|
||||
headers: APIs.authHeaders))),
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg",
|
||||
))),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
@@ -58,7 +58,6 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain,
|
||||
headers: APIs.authHeaders,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,8 +2,6 @@ import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:quiver/strings.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:ui/providers/server_response.dart';
|
||||
|
||||
class APIs {
|
||||
@@ -26,6 +24,7 @@ class APIs {
|
||||
static final delDownloadClientUrl = "$_baseUrl/api/v1/downloader/del/";
|
||||
static final storageUrl = "$_baseUrl/api/v1/storage/";
|
||||
static final loginUrl = "$_baseUrl/api/login";
|
||||
static final logoutUrl = "$_baseUrl/api/v1/setting/logout";
|
||||
static final loginSettingUrl = "$_baseUrl/api/v1/setting/auth";
|
||||
static final activityUrl = "$_baseUrl/api/v1/activity/";
|
||||
static final activityMediaUrl = "$_baseUrl/api/v1/activity/media/";
|
||||
@@ -49,53 +48,20 @@ class APIs {
|
||||
return "http://127.0.0.1:8080";
|
||||
}
|
||||
|
||||
static Dio? gDio;
|
||||
static Map<String, String> authHeaders = {};
|
||||
|
||||
static Future<bool> isLoggedIn() async {
|
||||
return isNotBlank(await getToken());
|
||||
}
|
||||
|
||||
static Future<String> getToken() async {
|
||||
var token = authHeaders["Authorization"];
|
||||
if (isBlank(token)) {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var t = prefs.getString("token");
|
||||
if (isNotBlank(t)) {
|
||||
authHeaders["Authorization"] = t!;
|
||||
token = t;
|
||||
}
|
||||
}
|
||||
return token ?? "";
|
||||
}
|
||||
|
||||
static Future<Dio> getDio() async {
|
||||
if (gDio != null) {
|
||||
return gDio!;
|
||||
}
|
||||
var token = await getToken();
|
||||
|
||||
static Dio getDio() {
|
||||
var dio = Dio();
|
||||
dio.interceptors.add(InterceptorsWrapper(
|
||||
onRequest: (options, handler) {
|
||||
options.headers['Authorization'] = 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');
|
||||
gDio = null;
|
||||
}
|
||||
}
|
||||
return handler.next(error);
|
||||
},
|
||||
));
|
||||
if (isNotBlank(token)) {
|
||||
gDio = dio;
|
||||
}
|
||||
return dio;
|
||||
}
|
||||
|
||||
@@ -108,9 +74,19 @@ class APIs {
|
||||
if (sp.code != 0) {
|
||||
throw sp.message;
|
||||
}
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var t = sp.data["token"];
|
||||
authHeaders["Authorization"] = "Bearer $t";
|
||||
prefs.setString("token", "Bearer $t");
|
||||
}
|
||||
|
||||
static Future<void> logout() async {
|
||||
var resp = await getDio().get(APIs.logoutUrl);
|
||||
|
||||
var sp = ServerResponse.fromJson(resp.data);
|
||||
|
||||
if (sp.code != 0) {
|
||||
throw sp.message;
|
||||
}
|
||||
final context = navigatorKey.currentContext;
|
||||
if (context != null) {
|
||||
context.go('/login');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ class _SearchPageState extends ConsumerState<SearchPage> {
|
||||
child: Image.network(
|
||||
"${APIs.tmdbImgBaseUrl}${item.posterPath}",
|
||||
fit: BoxFit.contain,
|
||||
headers: APIs.authHeaders,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -49,9 +49,7 @@ class _SystemPageState extends ConsumerState<SystemPage> {
|
||||
DataCell(Text((item.size ?? 0).readableFileSize())),
|
||||
DataCell(InkWell(
|
||||
child: const Icon(Icons.download),
|
||||
onTap: () => launchUrl(uri,
|
||||
webViewConfiguration: WebViewConfiguration(
|
||||
headers: APIs.authHeaders)),
|
||||
onTap: () => launchUrl(uri),
|
||||
))
|
||||
]);
|
||||
}));
|
||||
|
||||
@@ -155,8 +155,7 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
fit: BoxFit.fitWidth,
|
||||
opacity: 0.5,
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg",
|
||||
headers: APIs.authHeaders))),
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg"))),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
@@ -167,8 +166,7 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain,
|
||||
headers: APIs.authHeaders,
|
||||
fit: BoxFit.contain
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -34,7 +34,10 @@ class WelcomePage extends ConsumerWidget {
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height * 0.6,
|
||||
alignment: Alignment.center,
|
||||
child: const Text("啥都没有...", style: TextStyle(fontSize: 16),))
|
||||
child: const Text(
|
||||
"啥都没有...",
|
||||
style: TextStyle(fontSize: 16),
|
||||
))
|
||||
]
|
||||
: List.generate(value.length, (i) {
|
||||
var item = value[i];
|
||||
@@ -56,10 +59,8 @@ class WelcomePage extends ConsumerWidget {
|
||||
width: 140,
|
||||
height: 210,
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${item.id}/poster.jpg",
|
||||
fit: BoxFit.fill,
|
||||
headers: APIs.authHeaders,
|
||||
),
|
||||
"${APIs.imagesUrl}/${item.id}/poster.jpg",
|
||||
fit: BoxFit.fill),
|
||||
),
|
||||
SizedBox(
|
||||
width: 140,
|
||||
|
||||
Reference in New Issue
Block a user