mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-01-15 06:39:32 +00:00
chore: run dart format
Some checks are pending
Flutter CI & Release / Test (push) Waiting to run
Flutter CI & Release / Build Android APKs (push) Blocked by required conditions
Flutter CI & Release / build_linux (push) Blocked by required conditions
Flutter CI & Release / Create GitHub Release (push) Blocked by required conditions
Some checks are pending
Flutter CI & Release / Test (push) Waiting to run
Flutter CI & Release / Build Android APKs (push) Blocked by required conditions
Flutter CI & Release / build_linux (push) Blocked by required conditions
Flutter CI & Release / Create GitHub Release (push) Blocked by required conditions
This commit is contained in:
parent
a520136e01
commit
e23c0b6c5f
84 changed files with 1565 additions and 1945 deletions
|
|
@ -53,8 +53,10 @@ class OauthFlows extends _$OauthFlows {
|
|||
}
|
||||
state = {
|
||||
...state,
|
||||
oauthState: state[oauthState]!
|
||||
.copyWith(isFlowComplete: true, authToken: authToken),
|
||||
oauthState: state[oauthState]!.copyWith(
|
||||
isFlowComplete: true,
|
||||
authToken: authToken,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ class CallbackPage extends HookConsumerWidget {
|
|||
|
||||
// check if the state is in the flows
|
||||
if (!flows.containsKey(state)) {
|
||||
return const _SomethingWentWrong(
|
||||
message: 'State not found',
|
||||
);
|
||||
return const _SomethingWentWrong(message: 'State not found');
|
||||
}
|
||||
|
||||
// get the token
|
||||
|
|
@ -45,26 +43,21 @@ class CallbackPage extends HookConsumerWidget {
|
|||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Contacting server...\nPlease wait\n\nGot:'
|
||||
'\nState: $state\nCode: $code'),
|
||||
Text(
|
||||
'Contacting server...\nPlease wait\n\nGot:'
|
||||
'\nState: $state\nCode: $code',
|
||||
),
|
||||
loginAuthToken.when(
|
||||
data: (authenticationToken) {
|
||||
if (authenticationToken == null) {
|
||||
handleServerError(
|
||||
context,
|
||||
serverErrorResponse,
|
||||
);
|
||||
handleServerError(context, serverErrorResponse);
|
||||
return const BackToLoginButton();
|
||||
}
|
||||
return Text('Token: $authenticationToken');
|
||||
},
|
||||
loading: () => const CircularProgressIndicator(),
|
||||
error: (error, _) {
|
||||
handleServerError(
|
||||
context,
|
||||
serverErrorResponse,
|
||||
e: error,
|
||||
);
|
||||
handleServerError(context, serverErrorResponse, e: error);
|
||||
return Column(
|
||||
children: [
|
||||
Text('Error with OAuth flow: $error'),
|
||||
|
|
@ -81,9 +74,7 @@ class CallbackPage extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
class BackToLoginButton extends StatelessWidget {
|
||||
const BackToLoginButton({
|
||||
super.key,
|
||||
});
|
||||
const BackToLoginButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -97,9 +88,7 @@ class BackToLoginButton extends StatelessWidget {
|
|||
}
|
||||
|
||||
class _SomethingWentWrong extends StatelessWidget {
|
||||
const _SomethingWentWrong({
|
||||
this.message = 'Error with OAuth flow',
|
||||
});
|
||||
const _SomethingWentWrong({this.message = 'Error with OAuth flow'});
|
||||
|
||||
final String message;
|
||||
|
||||
|
|
@ -109,10 +98,7 @@ class _SomethingWentWrong extends StatelessWidget {
|
|||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(message),
|
||||
const BackToLoginButton(),
|
||||
],
|
||||
children: [Text(message), const BackToLoginButton()],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ import 'package:vaani/shared/utils.dart';
|
|||
import 'package:vaani/shared/widgets/add_new_server.dart';
|
||||
|
||||
class OnboardingSinglePage extends HookConsumerWidget {
|
||||
const OnboardingSinglePage({
|
||||
super.key,
|
||||
});
|
||||
const OnboardingSinglePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
|
@ -23,8 +21,9 @@ class OnboardingSinglePage extends HookConsumerWidget {
|
|||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 600,
|
||||
minWidth:
|
||||
constraints.maxWidth < 600 ? constraints.maxWidth : 0,
|
||||
minWidth: constraints.maxWidth < 600
|
||||
? constraints.maxWidth
|
||||
: 0,
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 20.0),
|
||||
|
|
@ -39,10 +38,7 @@ class OnboardingSinglePage extends HookConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
Widget fadeSlideTransitionBuilder(
|
||||
Widget child,
|
||||
Animation<double> animation,
|
||||
) {
|
||||
Widget fadeSlideTransitionBuilder(Widget child, Animation<double> animation) {
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: SlideTransition(
|
||||
|
|
@ -56,9 +52,7 @@ Widget fadeSlideTransitionBuilder(
|
|||
}
|
||||
|
||||
class OnboardingBody extends HookConsumerWidget {
|
||||
const OnboardingBody({
|
||||
super.key,
|
||||
});
|
||||
const OnboardingBody({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
|
@ -81,9 +75,7 @@ class OnboardingBody extends HookConsumerWidget {
|
|||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
const SizedBox.square(
|
||||
dimension: 16.0,
|
||||
),
|
||||
const SizedBox.square(dimension: 16.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: AnimatedSwitcher(
|
||||
|
|
@ -112,21 +104,17 @@ class OnboardingBody extends HookConsumerWidget {
|
|||
},
|
||||
),
|
||||
),
|
||||
const SizedBox.square(
|
||||
dimension: 16.0,
|
||||
),
|
||||
const SizedBox.square(dimension: 16.0),
|
||||
AnimatedSwitcher(
|
||||
duration: 500.ms,
|
||||
transitionBuilder: fadeSlideTransitionBuilder,
|
||||
child: canUserLogin.value
|
||||
? UserLoginWidget(
|
||||
server: audiobookshelfUri,
|
||||
)
|
||||
? UserLoginWidget(server: audiobookshelfUri)
|
||||
// ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0)
|
||||
: const RedirectToABS().animate().fadeIn().slideY(
|
||||
curve: Curves.easeInOut,
|
||||
duration: 500.ms,
|
||||
),
|
||||
curve: Curves.easeInOut,
|
||||
duration: 500.ms,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -134,9 +122,7 @@ class OnboardingBody extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
class RedirectToABS extends StatelessWidget {
|
||||
const RedirectToABS({
|
||||
super.key,
|
||||
});
|
||||
const RedirectToABS({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -152,18 +138,14 @@ class RedirectToABS extends StatelessWidget {
|
|||
isSemanticButton: false,
|
||||
style: ButtonStyle(
|
||||
elevation: WidgetStateProperty.all(0),
|
||||
padding: WidgetStateProperty.all(
|
||||
const EdgeInsets.all(0),
|
||||
),
|
||||
padding: WidgetStateProperty.all(const EdgeInsets.all(0)),
|
||||
),
|
||||
onPressed: () async {
|
||||
// open the github page
|
||||
// ignore: avoid_print
|
||||
print('Opening the github page');
|
||||
await handleLaunchUrl(
|
||||
Uri.parse(
|
||||
'https://www.audiobookshelf.org',
|
||||
),
|
||||
Uri.parse('https://www.audiobookshelf.org'),
|
||||
);
|
||||
},
|
||||
child: const Text('Click here'),
|
||||
|
|
|
|||
|
|
@ -22,11 +22,7 @@ import 'package:vaani/settings/api_settings_provider.dart'
|
|||
import 'package:vaani/settings/models/models.dart' as model;
|
||||
|
||||
class UserLoginWidget extends HookConsumerWidget {
|
||||
const UserLoginWidget({
|
||||
super.key,
|
||||
required this.server,
|
||||
this.onSuccess,
|
||||
});
|
||||
const UserLoginWidget({super.key, required this.server, this.onSuccess});
|
||||
|
||||
final Uri server;
|
||||
final Function(model.AuthenticatedUser)? onSuccess;
|
||||
|
|
@ -34,8 +30,9 @@ class UserLoginWidget extends HookConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final serverStatusError = useMemoized(() => ErrorResponseHandler(), []);
|
||||
final serverStatus =
|
||||
ref.watch(serverStatusProvider(server, serverStatusError.storeError));
|
||||
final serverStatus = ref.watch(
|
||||
serverStatusProvider(server, serverStatusError.storeError),
|
||||
);
|
||||
|
||||
return serverStatus.when(
|
||||
data: (value) {
|
||||
|
|
@ -55,9 +52,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
|||
);
|
||||
},
|
||||
loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
},
|
||||
error: (error, _) {
|
||||
return Center(
|
||||
|
|
@ -68,10 +63,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
|||
ElevatedButton(
|
||||
onPressed: () {
|
||||
ref.invalidate(
|
||||
serverStatusProvider(
|
||||
server,
|
||||
serverStatusError.storeError,
|
||||
),
|
||||
serverStatusProvider(server, serverStatusError.storeError),
|
||||
);
|
||||
},
|
||||
child: const Text('Try again'),
|
||||
|
|
@ -84,11 +76,7 @@ class UserLoginWidget extends HookConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
enum AuthMethodChoice {
|
||||
local,
|
||||
openid,
|
||||
authToken,
|
||||
}
|
||||
enum AuthMethodChoice { local, openid, authToken }
|
||||
|
||||
class UserLoginMultipleAuth extends HookConsumerWidget {
|
||||
const UserLoginMultipleAuth({
|
||||
|
|
@ -117,21 +105,17 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
|||
);
|
||||
|
||||
model.AudiobookShelfServer addServer() {
|
||||
var newServer = model.AudiobookShelfServer(
|
||||
serverUrl: server,
|
||||
);
|
||||
var newServer = model.AudiobookShelfServer(serverUrl: server);
|
||||
try {
|
||||
// add the server to the list of servers
|
||||
ref.read(audiobookShelfServerProvider.notifier).addServer(
|
||||
newServer,
|
||||
);
|
||||
ref.read(audiobookShelfServerProvider.notifier).addServer(newServer);
|
||||
} on ServerAlreadyExistsException catch (e) {
|
||||
newServer = e.server;
|
||||
} finally {
|
||||
ref.read(apiSettingsProvider.notifier).updateState(
|
||||
ref.read(apiSettingsProvider).copyWith(
|
||||
activeServer: newServer,
|
||||
),
|
||||
ref
|
||||
.read(apiSettingsProvider.notifier)
|
||||
.updateState(
|
||||
ref.read(apiSettingsProvider).copyWith(activeServer: newServer),
|
||||
);
|
||||
}
|
||||
return newServer;
|
||||
|
|
@ -150,42 +134,49 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
|||
runAlignment: WrapAlignment.center,
|
||||
runSpacing: 10,
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
// a small label to show the user what to do
|
||||
if (localAvailable)
|
||||
ChoiceChip(
|
||||
label: const Text('Local'),
|
||||
selected: methodChoice.value == AuthMethodChoice.local,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value = AuthMethodChoice.local;
|
||||
}
|
||||
},
|
||||
),
|
||||
if (openIDAvailable)
|
||||
ChoiceChip(
|
||||
label: const Text('OpenID'),
|
||||
selected: methodChoice.value == AuthMethodChoice.openid,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value = AuthMethodChoice.openid;
|
||||
}
|
||||
},
|
||||
),
|
||||
ChoiceChip(
|
||||
label: const Text('Token'),
|
||||
selected:
|
||||
methodChoice.value == AuthMethodChoice.authToken,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value = AuthMethodChoice.authToken;
|
||||
}
|
||||
},
|
||||
),
|
||||
].animate(interval: 100.ms).fadeIn(
|
||||
duration: 150.ms,
|
||||
curve: Curves.easeIn,
|
||||
),
|
||||
children:
|
||||
[
|
||||
// a small label to show the user what to do
|
||||
if (localAvailable)
|
||||
ChoiceChip(
|
||||
label: const Text('Local'),
|
||||
selected:
|
||||
methodChoice.value ==
|
||||
AuthMethodChoice.local,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value = AuthMethodChoice.local;
|
||||
}
|
||||
},
|
||||
),
|
||||
if (openIDAvailable)
|
||||
ChoiceChip(
|
||||
label: const Text('OpenID'),
|
||||
selected:
|
||||
methodChoice.value ==
|
||||
AuthMethodChoice.openid,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value =
|
||||
AuthMethodChoice.openid;
|
||||
}
|
||||
},
|
||||
),
|
||||
ChoiceChip(
|
||||
label: const Text('Token'),
|
||||
selected:
|
||||
methodChoice.value ==
|
||||
AuthMethodChoice.authToken,
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
methodChoice.value =
|
||||
AuthMethodChoice.authToken;
|
||||
}
|
||||
},
|
||||
),
|
||||
]
|
||||
.animate(interval: 100.ms)
|
||||
.fadeIn(duration: 150.ms, curve: Curves.easeIn),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
@ -195,21 +186,21 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
|
|||
transitionBuilder: fadeSlideTransitionBuilder,
|
||||
child: switch (methodChoice.value) {
|
||||
AuthMethodChoice.authToken => UserLoginWithToken(
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
AuthMethodChoice.local => UserLoginWithPassword(
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
AuthMethodChoice.openid => UserLoginWithOpenID(
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
openIDButtonText: openIDButtonText,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
server: server,
|
||||
addServer: addServer,
|
||||
openIDButtonText: openIDButtonText,
|
||||
onSuccess: onSuccess,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ class UserLoginWithOpenID extends HookConsumerWidget {
|
|||
|
||||
if (openIDLoginEndpoint == null) {
|
||||
if (responseErrorHandler.response.statusCode == 400 &&
|
||||
responseErrorHandler.response.body
|
||||
.toLowerCase()
|
||||
.contains(RegExp(r'invalid.*redirect.*uri'))) {
|
||||
responseErrorHandler.response.body.toLowerCase().contains(
|
||||
RegExp(r'invalid.*redirect.*uri'),
|
||||
)) {
|
||||
// show error
|
||||
handleServerError(
|
||||
context,
|
||||
|
|
@ -97,16 +97,16 @@ class UserLoginWithOpenID extends HookConsumerWidget {
|
|||
);
|
||||
|
||||
// add the flow to the provider
|
||||
ref.read(oauthFlowsProvider.notifier).addFlow(
|
||||
ref
|
||||
.read(oauthFlowsProvider.notifier)
|
||||
.addFlow(
|
||||
oauthState,
|
||||
verifier: verifier,
|
||||
serverUri: server,
|
||||
cookie: Cookie.fromSetCookieValue(authCookie!),
|
||||
);
|
||||
|
||||
await handleLaunchUrl(
|
||||
openIDLoginEndpoint,
|
||||
);
|
||||
await handleLaunchUrl(openIDLoginEndpoint);
|
||||
}
|
||||
|
||||
return Column(
|
||||
|
|
|
|||
|
|
@ -39,17 +39,14 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
|||
final api = ref.watch(audiobookshelfApiProvider(server));
|
||||
|
||||
// forward animation when the password visibility changes
|
||||
useEffect(
|
||||
() {
|
||||
if (isPasswordVisible.value) {
|
||||
isPasswordVisibleAnimationController.forward();
|
||||
} else {
|
||||
isPasswordVisibleAnimationController.reverse();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
[isPasswordVisible.value],
|
||||
);
|
||||
useEffect(() {
|
||||
if (isPasswordVisible.value) {
|
||||
isPasswordVisibleAnimationController.forward();
|
||||
} else {
|
||||
isPasswordVisibleAnimationController.reverse();
|
||||
}
|
||||
return null;
|
||||
}, [isPasswordVisible.value]);
|
||||
|
||||
/// Login to the server and save the user
|
||||
Future<void> loginAndSave() async {
|
||||
|
|
@ -109,10 +106,9 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
|||
decoration: InputDecoration(
|
||||
labelText: 'Username',
|
||||
labelStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.8),
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||
),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
|
|
@ -129,18 +125,16 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
|||
decoration: InputDecoration(
|
||||
labelText: 'Password',
|
||||
labelStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.8),
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||
),
|
||||
border: const OutlineInputBorder(),
|
||||
suffixIcon: ColorFiltered(
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withValues(alpha: 0.8),
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withValues(alpha: 0.8),
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
child: InkWell(
|
||||
|
|
@ -157,9 +151,7 @@ class UserLoginWithPassword extends HookConsumerWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
suffixIconConstraints: const BoxConstraints(
|
||||
maxHeight: 45,
|
||||
),
|
||||
suffixIconConstraints: const BoxConstraints(maxHeight: 45),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
|
|
@ -197,10 +189,12 @@ Future<void> handleServerError(
|
|||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: SelectableText('$title\n'
|
||||
'Got response: ${responseErrorHandler.response.body} (${responseErrorHandler.response.statusCode})\n'
|
||||
'Stacktrace: $e\n\n'
|
||||
'$body\n\n'),
|
||||
content: SelectableText(
|
||||
'$title\n'
|
||||
'Got response: ${responseErrorHandler.response.body} (${responseErrorHandler.response.statusCode})\n'
|
||||
'Stacktrace: $e\n\n'
|
||||
'$body\n\n',
|
||||
),
|
||||
actions: [
|
||||
if (outLink != null)
|
||||
TextButton(
|
||||
|
|
@ -214,8 +208,8 @@ Future<void> handleServerError(
|
|||
// open an issue on the github page
|
||||
handleLaunchUrl(
|
||||
AppMetadata.githubRepo
|
||||
// append the issue url
|
||||
.replace(
|
||||
// append the issue url
|
||||
.replace(
|
||||
path: '${AppMetadata.githubRepo.path}/issues/new',
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -89,10 +89,9 @@ class UserLoginWithToken extends HookConsumerWidget {
|
|||
decoration: InputDecoration(
|
||||
labelText: 'API Token',
|
||||
labelStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.8),
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withValues(alpha: 0.8),
|
||||
),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
|
|
@ -107,10 +106,7 @@ class UserLoginWithToken extends HookConsumerWidget {
|
|||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
ElevatedButton(
|
||||
onPressed: loginAndSave,
|
||||
child: const Text('Login'),
|
||||
),
|
||||
ElevatedButton(onPressed: loginAndSave, child: const Text('Login')),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue