Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0da4497857 | ||
|
|
0b05a21dc7 | ||
|
|
2558473399 | ||
|
|
4dd465fdfa | ||
|
|
1f20ba17f4 | ||
|
|
9ce8059212 | ||
|
|
e69a3adf14 | ||
|
|
8baa350056 |
@@ -13,7 +13,6 @@ import "package:ente_auth/onboarding/view/onboarding_page.dart";
|
||||
import 'package:ente_auth/ui/home_page.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import "package:flutter_localizations/flutter_localizations.dart";
|
||||
|
||||
class App extends StatefulWidget {
|
||||
@@ -62,7 +61,6 @@ class _AppState extends State<App> {
|
||||
theme: lightTheme,
|
||||
darkTheme: dartTheme,
|
||||
debugShowCheckedModeBanner: false,
|
||||
builder: EasyLoading.init(),
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
@@ -80,7 +78,6 @@ class _AppState extends State<App> {
|
||||
theme: lightThemeData,
|
||||
darkTheme: darkThemeData,
|
||||
debugShowCheckedModeBanner: false,
|
||||
builder: EasyLoading.init(),
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
|
||||
@@ -224,6 +224,14 @@ extension CustomColorScheme on ColorScheme {
|
||||
Color get inverseBackgroundColor =>
|
||||
brightness != Brightness.light ? backgroundBaseLight : backgroundBaseDark;
|
||||
|
||||
Color get fabForegroundColor => brightness == Brightness.light
|
||||
? const Color.fromRGBO(255, 255, 255, 1)
|
||||
: const Color.fromRGBO(40, 40, 40, 1);
|
||||
|
||||
Color get fabBackgroundColor => brightness != Brightness.light
|
||||
? const Color.fromRGBO(255, 255, 255, 1)
|
||||
: const Color.fromRGBO(40, 40, 40, 1);
|
||||
|
||||
Color get defaultTextColor =>
|
||||
brightness == Brightness.light ? textBaseLight : textBaseDark;
|
||||
|
||||
@@ -344,6 +352,10 @@ extension CustomColorScheme on ColorScheme {
|
||||
? Colors.black.withOpacity(0.32)
|
||||
: Colors.black.withOpacity(0.64);
|
||||
|
||||
Color get codeCardBackgroundColor => brightness == Brightness.light
|
||||
? const Color.fromRGBO(246, 246, 246, 1)
|
||||
: const Color.fromRGBO(40, 40, 40, 0.6);
|
||||
|
||||
EnteTheme get enteTheme =>
|
||||
brightness == Brightness.light ? lightTheme : darkTheme;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import "package:ente_auth/l10n/l10n.dart";
|
||||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:ente_auth/utils/totp_util.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
class SetupEnterSecretKeyPage extends StatefulWidget {
|
||||
@@ -15,8 +14,7 @@ class SetupEnterSecretKeyPage extends StatefulWidget {
|
||||
|
||||
class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
final _accountController = TextEditingController();
|
||||
final _secretController =
|
||||
TextEditingController(text: kDebugMode ? "JBSWY3DPEHPK3PXP" : "");
|
||||
final _secretController = TextEditingController(text: "");
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:clipboard/clipboard.dart';
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:ente_auth/store/code_store.dart';
|
||||
import 'package:ente_auth/utils/toast_util.dart';
|
||||
import 'package:ente_auth/utils/totp_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animation_progress_bar/flutter_animation_progress_bar.dart';
|
||||
// import 'package:flutter_animation_progress_bar/flutter_animation_progress_bar.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
class CodeWidget extends StatefulWidget {
|
||||
@@ -48,86 +48,107 @@ class _CodeWidgetState extends State<CodeWidget> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Slidable(
|
||||
key: ValueKey(widget.code.hashCode),
|
||||
endActionPane: ActionPane(
|
||||
motion: const ScrollMotion(),
|
||||
children: [
|
||||
SlidableAction(
|
||||
onPressed: _onDeletePressed,
|
||||
backgroundColor: Colors.grey.withOpacity(0.1),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
|
||||
foregroundColor: const Color(0xFFFE4A49),
|
||||
icon: Icons.delete,
|
||||
label: 'Delete',
|
||||
),
|
||||
],
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
FlutterClipboard.copy(_getTotp())
|
||||
.then((value) => showToast(context, "Copied to clipboard"));
|
||||
},
|
||||
child: SizedBox(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FAProgressBar(
|
||||
currentValue: _timeRemaining / widget.code.period * 100,
|
||||
size: 4,
|
||||
animatedDuration: const Duration(milliseconds: 200),
|
||||
progressColor: Colors.orange,
|
||||
changeColorValue: 40,
|
||||
changeProgressColor: Colors.green,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Text(
|
||||
Uri.decodeFull(widget.code.issuer),
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8, top: 8),
|
||||
child: Slidable(
|
||||
key: ValueKey(widget.code.hashCode),
|
||||
endActionPane: ActionPane(
|
||||
motion: const ScrollMotion(),
|
||||
children: [
|
||||
SlidableAction(
|
||||
onPressed: _onDeletePressed,
|
||||
backgroundColor: Colors.grey.withOpacity(0.1),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
|
||||
foregroundColor: const Color(0xFFFE4A49),
|
||||
icon: Icons.delete,
|
||||
label: 'Delete',
|
||||
padding: const EdgeInsets.only(left: 0, right: 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.codeCardBackgroundColor,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
customBorder: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
onTap: () {
|
||||
FlutterClipboard.copy(_getTotp()).then(
|
||||
(value) => showToast(context, "Copied to clipboard"),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FAProgressBar(
|
||||
currentValue:
|
||||
_timeRemaining / widget.code.period * 100,
|
||||
size: 4,
|
||||
animatedDuration: const Duration(milliseconds: 200),
|
||||
progressColor: Colors.orange,
|
||||
changeColorValue: 40,
|
||||
changeProgressColor: Colors.green,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Text(
|
||||
Uri.decodeFull(widget.code.issuer),
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"next",
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_getTotp(),
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
_getNextTotp(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"next",
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_getTotp(),
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
_getNextTotp(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -195,16 +216,4 @@ class _CodeWidgetState extends State<CodeWidget> {
|
||||
return "Error";
|
||||
}
|
||||
}
|
||||
|
||||
Color _getProgressColor() {
|
||||
final progress = _timeRemaining / widget.code.period;
|
||||
if (progress > 0.6) {
|
||||
return Colors.green;
|
||||
} else if (progress > 0.4) {
|
||||
return Colors.yellow;
|
||||
} else if (progress > 2) {
|
||||
return Colors.orange;
|
||||
}
|
||||
return Colors.red;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +152,8 @@ class _HomePageState extends State<HomePage> {
|
||||
childPadding: const EdgeInsets.all(5),
|
||||
spaceBetweenChildren: 4,
|
||||
tooltip: 'Add Code',
|
||||
foregroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: Theme.of(context).colorScheme.inverseBackgroundColor,
|
||||
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.fabBackgroundColor,
|
||||
overlayOpacity: 0.5,
|
||||
overlayColor: Theme.of(context).colorScheme.background,
|
||||
elevation: 8.0,
|
||||
@@ -161,16 +161,16 @@ class _HomePageState extends State<HomePage> {
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: const Icon(Icons.qr_code),
|
||||
foregroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: Theme.of(context).colorScheme.inverseBackgroundColor,
|
||||
label: 'Scan a QR Code',
|
||||
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.fabBackgroundColor,
|
||||
labelWidget: const SpeedDialLabelWidget("Scan a QR Code"),
|
||||
onTap: _redirectToScannerPage,
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: const Icon(Icons.keyboard),
|
||||
foregroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: Theme.of(context).colorScheme.inverseBackgroundColor,
|
||||
label: 'Enter details manually',
|
||||
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.fabBackgroundColor,
|
||||
labelWidget: const SpeedDialLabelWidget("Enter details manually"),
|
||||
onTap: _redirectToManualEntryPage,
|
||||
),
|
||||
],
|
||||
@@ -224,3 +224,30 @@ class _HomePageState extends State<HomePage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SpeedDialLabelWidget extends StatelessWidget {
|
||||
final String label;
|
||||
|
||||
const SpeedDialLabelWidget(
|
||||
this.label, {
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(4),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.fabBackgroundColor,
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.fabForegroundColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
Future showToast(
|
||||
@@ -11,31 +8,16 @@ Future showToast(
|
||||
toastLength = Toast.LENGTH_LONG,
|
||||
iOSDismissOnTap = true,
|
||||
}) async {
|
||||
if (Platform.isAndroid) {
|
||||
await Fluttertoast.cancel();
|
||||
return Fluttertoast.showToast(
|
||||
msg: message,
|
||||
toastLength: toastLength,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
timeInSecForIosWeb: 1,
|
||||
backgroundColor: Theme.of(context).colorScheme.toastBackgroundColor,
|
||||
textColor: Theme.of(context).colorScheme.toastTextColor,
|
||||
fontSize: 16.0,
|
||||
);
|
||||
} else {
|
||||
EasyLoading.instance
|
||||
..backgroundColor = Theme.of(context).colorScheme.toastBackgroundColor
|
||||
..indicatorColor = Theme.of(context).colorScheme.toastBackgroundColor
|
||||
..textColor = Theme.of(context).colorScheme.toastTextColor
|
||||
..userInteractions = true
|
||||
..loadingStyle = EasyLoadingStyle.custom;
|
||||
return EasyLoading.showToast(
|
||||
message,
|
||||
duration: Duration(seconds: (toastLength == Toast.LENGTH_LONG ? 5 : 2)),
|
||||
toastPosition: EasyLoadingToastPosition.bottom,
|
||||
dismissOnTap: iOSDismissOnTap,
|
||||
);
|
||||
}
|
||||
await Fluttertoast.cancel();
|
||||
return Fluttertoast.showToast(
|
||||
msg: message,
|
||||
toastLength: toastLength,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
timeInSecForIosWeb: 1,
|
||||
backgroundColor: Theme.of(context).colorScheme.toastBackgroundColor,
|
||||
textColor: Theme.of(context).colorScheme.toastTextColor,
|
||||
fontSize: 16.0,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showShortToast(context, String message) {
|
||||
|
||||
16
pubspec.lock
16
pubspec.lock
@@ -384,13 +384,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.0.1"
|
||||
flutter_easyloading:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_easyloading
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
flutter_email_sender:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -494,13 +487,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
flutter_spinkit:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_spinkit
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@@ -524,7 +510,7 @@ packages:
|
||||
name: fluttertoast
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.0.9"
|
||||
version: "8.1.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 1.0.7+7
|
||||
version: 1.0.8+8
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
@@ -46,7 +46,7 @@ dependencies:
|
||||
# sentry_flutter:
|
||||
# path: thirdparty/sentry-dart/flutter
|
||||
json_annotation: ^4.5.0
|
||||
fluttertoast: ^8.0.6
|
||||
fluttertoast: ^8.1.1
|
||||
google_nav_bar: ^5.0.5 #supported
|
||||
http: ^0.13.4
|
||||
move_to_background: ^1.0.2
|
||||
@@ -58,7 +58,6 @@ dependencies:
|
||||
share_plus: ^4.4.0
|
||||
package_info_plus: ^1.0.1
|
||||
shared_preferences: ^2.0.5
|
||||
flutter_easyloading: ^3.0.5
|
||||
uuid: ^3.0.4
|
||||
url_launcher: ^6.1.5
|
||||
logging: ^1.0.1
|
||||
|
||||
Reference in New Issue
Block a user