Compare commits
3 commits
f9a2bb0df7
...
a65c7d9253
Author | SHA1 | Date | |
---|---|---|---|
a65c7d9253 | |||
bac39aebdf | |||
b55e932204 |
47 changed files with 322 additions and 256 deletions
|
@ -1,7 +1,7 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 1.5.2+18
|
||||
* ...
|
||||
* Added proper linting to project
|
||||
|
||||
## 1.5.1+17
|
||||
* Fixed white background button in AppBar when light theme enabled
|
||||
|
|
30
analysis_options.yaml
Normal file
30
analysis_options.yaml
Normal file
|
@ -0,0 +1,30 @@
|
|||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at
|
||||
# https://dart-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
library_private_types_in_public_api: false
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
|
@ -21,7 +21,7 @@ class MyApp extends StatelessWidget {
|
|||
static final _defaultLightColorScheme = ColorScheme.fromSwatch(primarySwatch: myColor, brightness: Brightness.light);
|
||||
static final _defaultDarkColorScheme = ColorScheme.fromSwatch(primarySwatch: myColor, brightness: Brightness.dark);
|
||||
|
||||
MyApp() {
|
||||
MyApp({super.key}) {
|
||||
initializeDateFormatting('en');
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class MyApp extends StatelessWidget {
|
|||
darkTheme: ThemeData(useMaterial3: true, colorScheme: darkColorScheme ?? _defaultDarkColorScheme),
|
||||
onGenerateRoute: AppRouter.generateRoute,
|
||||
navigatorKey: locator<NavigationService>().navigationKey,
|
||||
home: StartUpView(),
|
||||
home: const StartUpView(),
|
||||
supportedLocales: localizationDelegate.supportedLocales,
|
||||
locale: localizationDelegate.currentLocale,
|
||||
);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/// Enums for error codes
|
||||
enum ErrorCode {
|
||||
/// A generic error
|
||||
GENERAL_ERROR,
|
||||
generalError,
|
||||
|
||||
/// Errors related to connections
|
||||
SOCKET_ERROR,
|
||||
SOCKET_TIMEOUT,
|
||||
socketError,
|
||||
socketTimeout,
|
||||
|
||||
/// A REST error (response code wasn't 200 or 204)
|
||||
REST_ERROR,
|
||||
restError,
|
||||
|
||||
/// Custom errors
|
||||
INVALID_API_KEY
|
||||
invalidApiKey
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
enum RefreshEvent { RefreshHistory }
|
||||
enum RefreshEvent { refreshHistory }
|
||||
|
|
|
@ -1 +1 @@
|
|||
enum ViewState { Idle, Busy }
|
||||
enum ViewState { idle, busy }
|
||||
|
|
|
@ -6,8 +6,9 @@ class RestServiceException extends ServiceException {
|
|||
final dynamic responseBody;
|
||||
|
||||
RestServiceException(this.statusCode, {this.responseBody, String? message})
|
||||
: super(code: ErrorCode.REST_ERROR, message: message);
|
||||
: super(code: ErrorCode.restError, message: message);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$code $statusCode $message";
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ class ServiceException implements Exception {
|
|||
final ErrorCode code;
|
||||
final String? message;
|
||||
|
||||
ServiceException({this.code = ErrorCode.GENERAL_ERROR, this.message = ''});
|
||||
ServiceException({this.code = ErrorCode.generalError, this.message = ''});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$code: $message";
|
||||
}
|
||||
|
|
|
@ -8,13 +8,14 @@ import '../services/dialog_service.dart';
|
|||
class DialogManager extends StatefulWidget {
|
||||
final Widget? child;
|
||||
|
||||
DialogManager({Key? key, this.child}) : super(key: key);
|
||||
const DialogManager({Key? key, this.child}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DialogManagerState createState() => _DialogManagerState();
|
||||
}
|
||||
|
||||
class _DialogManagerState extends State<DialogManager> {
|
||||
DialogService _dialogService = locator<DialogService>();
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
|
@ -11,8 +11,9 @@ import '../util/logger.dart';
|
|||
class LifeCycleManager extends StatefulWidget {
|
||||
final Widget? child;
|
||||
|
||||
LifeCycleManager({Key? key, this.child}) : super(key: key);
|
||||
const LifeCycleManager({Key? key, this.child}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LifeCycleManagerState createState() => _LifeCycleManagerState();
|
||||
}
|
||||
|
||||
|
@ -43,12 +44,12 @@ class _LifeCycleManagerState extends State<LifeCycleManager> with WidgetsBinding
|
|||
logger.d('LifeCycle event ${state.toString()}');
|
||||
super.didChangeAppLifecycleState(state);
|
||||
|
||||
servicesToManage.forEach((service) {
|
||||
for (var service in servicesToManage) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
service.start();
|
||||
} else {
|
||||
service.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import '../models/rest/uploaded_response.dart';
|
|||
import '../services/api.dart';
|
||||
|
||||
class FileRepository {
|
||||
Api _api = locator<Api>();
|
||||
final Api _api = locator<Api>();
|
||||
|
||||
Future<History> getHistory() async {
|
||||
var response = await _api.post('/file/history');
|
||||
|
@ -39,11 +39,11 @@ class FileRepository {
|
|||
}
|
||||
|
||||
Future<UploadedMultiResponse> postCreateMultiPaste(List<String> ids) async {
|
||||
Map<String, String> multiPasteIds = Map();
|
||||
Map<String, String> multiPasteIds = {};
|
||||
|
||||
ids.forEach((element) {
|
||||
for (var element in ids) {
|
||||
multiPasteIds.putIfAbsent("ids[${ids.indexOf(element) + 1}]", () => element);
|
||||
});
|
||||
}
|
||||
|
||||
var response = await _api.post('/file/create_multipaste', fields: multiPasteIds);
|
||||
return UploadedMultiResponse.fromJson(json.decode(response.body));
|
||||
|
|
|
@ -6,7 +6,7 @@ import '../models/rest/create_apikey_response.dart';
|
|||
import '../services/api.dart';
|
||||
|
||||
class UserRepository {
|
||||
Api _api = locator<Api>();
|
||||
final Api _api = locator<Api>();
|
||||
|
||||
Future<CreateApiKeyResponse> postApiKey(
|
||||
String url, String username, String password, String accessLevel, String comment) async {
|
||||
|
|
|
@ -24,8 +24,8 @@ class Api implements ApiErrorConverter {
|
|||
String _url = "";
|
||||
String _apiKey = "";
|
||||
|
||||
Map<String, String> _headers = {"Content-Type": _applicationJson, "Accept": _applicationJson};
|
||||
Duration _timeout = Duration(seconds: Constants.apiRequestTimeoutLimit);
|
||||
final Map<String, String> _headers = {"Content-Type": _applicationJson, "Accept": _applicationJson};
|
||||
Duration _timeout = const Duration(seconds: Constants.apiRequestTimeoutLimit);
|
||||
|
||||
Future<http.Response> fetch<T>(String route) async {
|
||||
try {
|
||||
|
@ -35,9 +35,9 @@ class Api implements ApiErrorConverter {
|
|||
handleRestErrors(response);
|
||||
return response;
|
||||
} on TimeoutException {
|
||||
throw ServiceException(code: ErrorCode.SOCKET_TIMEOUT, message: _errorTimeout);
|
||||
throw ServiceException(code: ErrorCode.socketTimeout, message: _errorTimeout);
|
||||
} on SocketException {
|
||||
throw ServiceException(code: ErrorCode.SOCKET_ERROR, message: _errorNoConnection);
|
||||
throw ServiceException(code: ErrorCode.socketError, message: _errorNoConnection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,12 +58,12 @@ class Api implements ApiErrorConverter {
|
|||
}
|
||||
|
||||
if (files != null && files.isNotEmpty) {
|
||||
files.forEach((element) async {
|
||||
for (var element in files) {
|
||||
request.files.add(await http.MultipartFile.fromPath('file[${files.indexOf(element) + 1}]', element.path));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalFiles != null && additionalFiles.length > 0) {
|
||||
if (additionalFiles != null && additionalFiles.isNotEmpty) {
|
||||
List<String> keys = additionalFiles.keys.toList();
|
||||
additionalFiles.forEach((key, value) {
|
||||
var index = files != null ? files.length + keys.indexOf(key) + 1 : keys.indexOf(key) + 1;
|
||||
|
@ -77,9 +77,9 @@ class Api implements ApiErrorConverter {
|
|||
handleRestErrors(response);
|
||||
return response;
|
||||
} on TimeoutException {
|
||||
throw ServiceException(code: ErrorCode.SOCKET_TIMEOUT, message: _errorTimeout);
|
||||
throw ServiceException(code: ErrorCode.socketTimeout, message: _errorTimeout);
|
||||
} on SocketException {
|
||||
throw ServiceException(code: ErrorCode.SOCKET_ERROR, message: _errorNoConnection);
|
||||
throw ServiceException(code: ErrorCode.socketError, message: _errorNoConnection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,11 +114,11 @@ class Api implements ApiErrorConverter {
|
|||
if (ContentType.json.primaryType == responseContentType.primaryType &&
|
||||
ContentType.json.subType == responseContentType.subType) {
|
||||
var parsedBody = convert(response);
|
||||
throw new RestServiceException(response.statusCode, responseBody: parsedBody);
|
||||
throw RestServiceException(response.statusCode, responseBody: parsedBody);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RestServiceException(response.statusCode);
|
||||
throw RestServiceException(response.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import '../datamodels/dialog_request.dart';
|
|||
import '../datamodels/dialog_response.dart';
|
||||
|
||||
class DialogService {
|
||||
GlobalKey<NavigatorState> _dialogNavigationKey = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> _dialogNavigationKey = GlobalKey<NavigatorState>();
|
||||
late Function(DialogRequest) _showDialogListener;
|
||||
Completer<DialogResponse>? _dialogCompleter;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:logger/logger.dart';
|
|||
import '../util/logger.dart';
|
||||
|
||||
class NavigationService {
|
||||
GlobalKey<NavigatorState> _navigationKey = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> _navigationKey = GlobalKey<NavigatorState>();
|
||||
|
||||
GlobalKey<NavigatorState> get navigationKey => _navigationKey;
|
||||
|
||||
|
|
|
@ -105,11 +105,11 @@ class PermissionService extends StoppableService {
|
|||
await checkEnabledAndPermission();
|
||||
|
||||
_serviceCheckTimer =
|
||||
Timer.periodic(Duration(milliseconds: Constants.mediaPermissionCheckInterval), (_serviceTimer) async {
|
||||
Timer.periodic(const Duration(milliseconds: Constants.mediaPermissionCheckInterval), (serviceTimer) async {
|
||||
if (!super.serviceStopped) {
|
||||
await checkEnabledAndPermission();
|
||||
} else {
|
||||
_serviceTimer.cancel();
|
||||
serviceTimer.cancel();
|
||||
}
|
||||
});
|
||||
_logger.d('PermissionService started');
|
||||
|
|
|
@ -31,7 +31,7 @@ class SessionService extends StoppableService {
|
|||
Future<bool> login(String url, String apiKey) async {
|
||||
setApiConfig(url, apiKey);
|
||||
|
||||
var session = new Session(url: url, apiKey: apiKey);
|
||||
var session = Session(url: url, apiKey: apiKey);
|
||||
sessionController.add(session);
|
||||
await _storageService.storeSession(session);
|
||||
_logger.d('Session created');
|
||||
|
|
|
@ -5,45 +5,45 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
import '../models/session.dart';
|
||||
|
||||
class StorageService {
|
||||
static const _SESSION_KEY = 'session';
|
||||
static const _LAST_URL_KEY = 'last_url';
|
||||
static const _STORAGE_PERMISSION_DIALOG_IGNORED = 'storage_permission_ignored';
|
||||
static const _sessionKey = 'session';
|
||||
static const _lastUrlKey = 'last_url';
|
||||
static const _storagePermissionDialogIgnoredKey = 'storage_permission_ignored';
|
||||
|
||||
Future<bool> storeLastUrl(String url) {
|
||||
return _store(_LAST_URL_KEY, url);
|
||||
return _store(_lastUrlKey, url);
|
||||
}
|
||||
|
||||
Future<String?> retrieveLastUrl() async {
|
||||
return await _retrieve(_LAST_URL_KEY);
|
||||
return await _retrieve(_lastUrlKey);
|
||||
}
|
||||
|
||||
Future<bool> hasLastUrl() async {
|
||||
return await _exists(_LAST_URL_KEY);
|
||||
return await _exists(_lastUrlKey);
|
||||
}
|
||||
|
||||
Future<bool> storeSession(Session session) {
|
||||
return _store(_SESSION_KEY, json.encode(session));
|
||||
return _store(_sessionKey, json.encode(session));
|
||||
}
|
||||
|
||||
Future<Session> retrieveSession() async {
|
||||
var retrieve = await _retrieve(_SESSION_KEY);
|
||||
var retrieve = await _retrieve(_sessionKey);
|
||||
return Session.fromJson(json.decode(retrieve!));
|
||||
}
|
||||
|
||||
Future<bool> hasSession() {
|
||||
return _exists(_SESSION_KEY);
|
||||
return _exists(_sessionKey);
|
||||
}
|
||||
|
||||
Future<bool> removeSession() {
|
||||
return _remove(_SESSION_KEY);
|
||||
return _remove(_sessionKey);
|
||||
}
|
||||
|
||||
Future<bool> storeStoragePermissionDialogIgnored() {
|
||||
return _store(_STORAGE_PERMISSION_DIALOG_IGNORED, true.toString());
|
||||
return _store(_storagePermissionDialogIgnoredKey, true.toString());
|
||||
}
|
||||
|
||||
Future<bool> hasStoragePermissionDialogIgnored() {
|
||||
return _exists(_STORAGE_PERMISSION_DIALOG_IGNORED);
|
||||
return _exists(_storagePermissionDialogIgnoredKey);
|
||||
}
|
||||
|
||||
Future<bool> _exists(String key) async {
|
||||
|
|
|
@ -26,7 +26,7 @@ class UserService {
|
|||
try {
|
||||
await _fileService.getHistory();
|
||||
} on ServiceException catch (e) {
|
||||
throw new ServiceException(code: ErrorCode.INVALID_API_KEY, message: e.message);
|
||||
throw ServiceException(code: ErrorCode.invalidApiKey, message: e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,6 @@ class FormatterUtil {
|
|||
if (bytes <= 0) return "0 B";
|
||||
const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||
var i = (log(bytes) / log(1024)).floor();
|
||||
return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + ' ' + suffixes[i];
|
||||
return '${(bytes / pow(1024, i)).toStringAsFixed(decimals)} ${suffixes[i]}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ class AboutModel extends BaseModel {
|
|||
}
|
||||
|
||||
Future<void> _initPackageInfo() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
final PackageInfo info = await PackageInfo.fromPlatform();
|
||||
packageInfo = info;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
void openLink(String link) {
|
||||
|
|
|
@ -5,18 +5,18 @@ import '../../core/util/logger.dart';
|
|||
import '../enums/viewstate.dart';
|
||||
|
||||
class BaseModel extends ChangeNotifier {
|
||||
static const String STATE_VIEW = 'viewState';
|
||||
static const String STATE_MESSAGE = 'viewMessage';
|
||||
static const String stateViewKey = 'viewState';
|
||||
static const String stateMessageKey = 'viewMessage';
|
||||
|
||||
final Logger _logger = getLogger();
|
||||
|
||||
bool _isDisposed = false;
|
||||
|
||||
Map<String, Object?> _stateMap = {STATE_VIEW: ViewState.Idle, STATE_MESSAGE: null};
|
||||
final Map<String, Object?> _stateMap = {stateViewKey: ViewState.idle, stateMessageKey: null};
|
||||
|
||||
ViewState? get state => _stateMap[STATE_VIEW] as ViewState?;
|
||||
ViewState? get state => _stateMap[stateViewKey] as ViewState?;
|
||||
|
||||
String? get stateMessage => _stateMap[STATE_MESSAGE] as String?;
|
||||
String? get stateMessage => _stateMap[stateMessageKey] as String?;
|
||||
|
||||
bool getStateValueAsBoolean(String key) {
|
||||
if (_stateMap.containsKey(key) && _stateMap[key] is bool) {
|
||||
|
@ -71,11 +71,11 @@ class BaseModel extends ChangeNotifier {
|
|||
}
|
||||
|
||||
void setStateView(ViewState stateView) {
|
||||
_setStateValue(STATE_VIEW, stateView);
|
||||
_setStateValue(stateViewKey, stateView);
|
||||
}
|
||||
|
||||
void setStateMessage(String? stateMessage) {
|
||||
_setStateValue(STATE_MESSAGE, stateMessage);
|
||||
_setStateValue(stateMessageKey, stateMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -35,7 +35,7 @@ class HistoryModel extends BaseModel {
|
|||
|
||||
void init() {
|
||||
_refreshTriggerSubscription = _refreshService.refreshEventController.stream.listen((event) {
|
||||
if (event == RefreshEvent.RefreshHistory) {
|
||||
if (event == RefreshEvent.refreshHistory) {
|
||||
_logger.d('History needs a refresh');
|
||||
getHistory();
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ class HistoryModel extends BaseModel {
|
|||
}
|
||||
|
||||
Future getHistory() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
|
||||
try {
|
||||
pastes.clear();
|
||||
History _history = await _fileService.getHistory();
|
||||
if (_history.items.isNotEmpty) {
|
||||
_history.items.forEach((key, value) {
|
||||
History history = await _fileService.getHistory();
|
||||
if (history.items.isNotEmpty) {
|
||||
history.items.forEach((key, value) {
|
||||
var millisecondsSinceEpoch = int.parse(value.date) * 1000;
|
||||
pastes.add(
|
||||
UploadedPaste(
|
||||
|
@ -66,8 +66,8 @@ class HistoryModel extends BaseModel {
|
|||
});
|
||||
}
|
||||
|
||||
if (_history.multipasteItems.isNotEmpty) {
|
||||
_history.multipasteItems.forEach((key, multiPaste) {
|
||||
if (history.multipasteItems.isNotEmpty) {
|
||||
history.multipasteItems.forEach((key, multiPaste) {
|
||||
var millisecondsSinceEpoch = int.parse(multiPaste.date) * 1000;
|
||||
pastes.add(UploadedPaste(
|
||||
id: key,
|
||||
|
@ -97,19 +97,19 @@ class HistoryModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('api.general_rest_error');
|
||||
}
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_ERROR) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketError) {
|
||||
errorMessage = translate('api.socket_error');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_TIMEOUT) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketTimeout) {
|
||||
errorMessage = translate('api.socket_timeout');
|
||||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
throw e;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
Future deletePaste(String id) async {
|
||||
|
@ -123,7 +123,7 @@ class HistoryModel extends BaseModel {
|
|||
return;
|
||||
}
|
||||
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
|
||||
try {
|
||||
await _fileService.deletePaste(id);
|
||||
|
@ -143,19 +143,19 @@ class HistoryModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('api.general_rest_error');
|
||||
}
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_ERROR) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketError) {
|
||||
errorMessage = translate('api.socket_error');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_TIMEOUT) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketTimeout) {
|
||||
errorMessage = translate('api.socket_timeout');
|
||||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
throw e;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
void openLink(String link) {
|
||||
|
|
|
@ -20,12 +20,12 @@ import '../util/logger.dart';
|
|||
import 'base_model.dart';
|
||||
|
||||
class LoginModel extends BaseModel {
|
||||
TextEditingController _uriController = new TextEditingController();
|
||||
TextEditingController _uriController = TextEditingController();
|
||||
|
||||
final TextEditingController _userNameController = new TextEditingController();
|
||||
final TextEditingController _passwordController = new TextEditingController();
|
||||
final TextEditingController _userNameController = TextEditingController();
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
|
||||
final TextEditingController _apiKeyController = new TextEditingController();
|
||||
final TextEditingController _apiKeyController = TextEditingController();
|
||||
|
||||
TextEditingController get uriController => _uriController;
|
||||
|
||||
|
@ -44,23 +44,23 @@ class LoginModel extends BaseModel {
|
|||
String? errorMessage;
|
||||
|
||||
void toggleLoginMethod() {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
useCredentialsLogin = !useCredentialsLogin;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
void init() async {
|
||||
bool hasLastUrl = await _storageService.hasLastUrl();
|
||||
|
||||
if (hasLastUrl) {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
var s = await (_storageService.retrieveLastUrl() as FutureOr<String>);
|
||||
|
||||
if (s.isNotEmpty) {
|
||||
_uriController = new TextEditingController(text: s);
|
||||
_uriController = TextEditingController(text: s);
|
||||
}
|
||||
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,45 +70,45 @@ class LoginModel extends BaseModel {
|
|||
var password = passwordController.text;
|
||||
var apiKey = apiKeyController.text;
|
||||
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
url = trim(url);
|
||||
username = trim(username);
|
||||
|
||||
if (url.isEmpty) {
|
||||
errorMessage = translate('login.errors.empty_url');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!url.contains("https://") && !url.contains("http://")) {
|
||||
errorMessage = translate('login.errors.no_protocol');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool validUri = Uri.parse(url).isAbsolute;
|
||||
if (!validUri || !isURL(url)) {
|
||||
errorMessage = translate('login.errors.invalid_url');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (useCredentialsLogin) {
|
||||
if (username.isEmpty) {
|
||||
errorMessage = translate('login.errors.empty_username');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password.isEmpty) {
|
||||
errorMessage = translate('login.errors.empty_password');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (apiKey.isEmpty) {
|
||||
errorMessage = translate('login.errors.empty_apikey');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -117,14 +117,13 @@ class LoginModel extends BaseModel {
|
|||
try {
|
||||
if (useCredentialsLogin) {
|
||||
CreateApiKeyResponse apiKeyResponse = await _userService.createApiKey(
|
||||
url, username, password, 'apikey', 'fbmobile-${new DateTime.now().millisecondsSinceEpoch}');
|
||||
url, username, password, 'apikey', 'fbmobile-${DateTime.now().millisecondsSinceEpoch}');
|
||||
|
||||
var newKey = apiKeyResponse.data['new_key'];
|
||||
if (newKey != null) {
|
||||
success = await _sessionService.login(url, newKey);
|
||||
} else {
|
||||
throw new ServiceException(
|
||||
code: ErrorCode.INVALID_API_KEY, message: translate('login.errors.invalid_api_key'));
|
||||
throw ServiceException(code: ErrorCode.invalidApiKey, message: translate('login.errors.invalid_api_key'));
|
||||
}
|
||||
} else {
|
||||
_sessionService.setApiConfig(url, apiKey);
|
||||
|
@ -146,25 +145,25 @@ class LoginModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('api.general_rest_error');
|
||||
}
|
||||
} else if (e is ServiceException && e.code == ErrorCode.INVALID_API_KEY) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.invalidApiKey) {
|
||||
errorMessage = translate('login.errors.invalid_api_key');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_ERROR) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketError) {
|
||||
errorMessage = translate('api.socket_error');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_TIMEOUT) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketTimeout) {
|
||||
errorMessage = translate('api.socket_timeout');
|
||||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
_sessionService.logout();
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
throw e;
|
||||
rethrow;
|
||||
}
|
||||
|
||||
if (errorMessage!.isNotEmpty) {
|
||||
_sessionService.logout();
|
||||
}
|
||||
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,9 +64,9 @@ class ProfileModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('api.general_rest_error');
|
||||
}
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_ERROR) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketError) {
|
||||
errorMessage = translate('api.socket_error');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_TIMEOUT) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketTimeout) {
|
||||
errorMessage = translate('api.socket_timeout');
|
||||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
|
@ -74,7 +74,7 @@ class ProfileModel extends BaseModel {
|
|||
_sessionService.logout();
|
||||
setStateBoolValue(_configurationButtonLoading, false);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
throw e;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,16 +12,16 @@ class StartUpViewModel extends BaseModel {
|
|||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
|
||||
Future handleStartUpLogic() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
setStateMessage(translate('startup.init'));
|
||||
await Future.delayed(Duration(milliseconds: 150));
|
||||
await Future.delayed(const Duration(milliseconds: 150));
|
||||
|
||||
setStateMessage(translate('startup.start_services'));
|
||||
await _sessionService.start();
|
||||
await Future.delayed(Duration(milliseconds: 150));
|
||||
await Future.delayed(const Duration(milliseconds: 150));
|
||||
|
||||
_navigationService.navigateAndReplaceTo(HomeView.routeName);
|
||||
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class UploadModel extends BaseModel {
|
|||
final LinkService _linkService = locator<LinkService>();
|
||||
final RefreshService _refreshService = locator<RefreshService>();
|
||||
|
||||
TextEditingController _pasteTextController = TextEditingController();
|
||||
final TextEditingController _pasteTextController = TextEditingController();
|
||||
bool pasteTextTouched = false;
|
||||
|
||||
late StreamSubscription _intentDataStreamSubscription;
|
||||
|
@ -53,8 +53,8 @@ class UploadModel extends BaseModel {
|
|||
|
||||
// For sharing images coming from outside the app while the app is in the memory
|
||||
_intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream().listen((List<SharedMediaFile> value) {
|
||||
if (value.length > 0) {
|
||||
setStateView(ViewState.Busy);
|
||||
if (value.isNotEmpty) {
|
||||
setStateView(ViewState.busy);
|
||||
paths = value.map((sharedFile) {
|
||||
return PlatformFile.fromMap({
|
||||
'path': sharedFile.path,
|
||||
|
@ -63,7 +63,7 @@ class UploadModel extends BaseModel {
|
|||
'bytes': null
|
||||
});
|
||||
}).toList();
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}, onError: (err) {
|
||||
_errorIntentHandle(err);
|
||||
|
@ -71,8 +71,8 @@ class UploadModel extends BaseModel {
|
|||
|
||||
// For sharing images coming from outside the app while the app is closed
|
||||
ReceiveSharingIntent.getInitialMedia().then((List<SharedMediaFile> value) {
|
||||
if (value.length > 0) {
|
||||
setStateView(ViewState.Busy);
|
||||
if (value.isNotEmpty) {
|
||||
setStateView(ViewState.busy);
|
||||
paths = value.map((sharedFile) {
|
||||
return PlatformFile.fromMap({
|
||||
'path': sharedFile.path,
|
||||
|
@ -81,7 +81,7 @@ class UploadModel extends BaseModel {
|
|||
'bytes': null
|
||||
});
|
||||
}).toList();
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}, onError: (err) {
|
||||
_errorIntentHandle(err);
|
||||
|
@ -90,9 +90,9 @@ class UploadModel extends BaseModel {
|
|||
// For sharing or opening urls/text coming from outside the app while the app is in the memory
|
||||
_intentDataStreamSubscription = ReceiveSharingIntent.getTextStream().listen((String value) {
|
||||
if (value.isNotEmpty) {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
pasteTextController.text = value;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}, onError: (err) {
|
||||
_errorIntentHandle(err);
|
||||
|
@ -101,9 +101,9 @@ class UploadModel extends BaseModel {
|
|||
// For sharing or opening urls/text coming from outside the app while the app is closed
|
||||
ReceiveSharingIntent.getInitialText().then((String? value) {
|
||||
if (value != null && value.isNotEmpty) {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
pasteTextController.text = value;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
}, onError: (err) {
|
||||
_errorIntentHandle(err);
|
||||
|
@ -111,14 +111,14 @@ class UploadModel extends BaseModel {
|
|||
}
|
||||
|
||||
void _errorIntentHandle(err) {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
errorMessage = translate('upload.retrieval_intent');
|
||||
_logger.e('Error while retrieving shared data: $err');
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
String? generatePasteLinks(Map<String, bool>? uploads, String url) {
|
||||
if (uploads != null && uploads.length > 0) {
|
||||
if (uploads != null && uploads.isNotEmpty) {
|
||||
var links = '';
|
||||
|
||||
uploads.forEach((id, isMulti) {
|
||||
|
@ -134,13 +134,13 @@ class UploadModel extends BaseModel {
|
|||
}
|
||||
|
||||
void toggleCreateMulti() {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
createMulti = !createMulti;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
void openFileExplorer() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
setStateMessage(translate('upload.file_explorer_open'));
|
||||
loadingPath = true;
|
||||
|
||||
|
@ -163,40 +163,40 @@ class UploadModel extends BaseModel {
|
|||
fileName = paths != null ? paths!.map((e) => e.name).toString() : '...';
|
||||
|
||||
setStateMessage(null);
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
void clearCachedFiles() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
await FilePicker.platform.clearTemporaryFiles();
|
||||
paths = null;
|
||||
fileName = null;
|
||||
errorMessage = null;
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
}
|
||||
|
||||
Future<Map<String, bool>?> upload() async {
|
||||
setStateView(ViewState.Busy);
|
||||
setStateView(ViewState.busy);
|
||||
setStateMessage(translate('upload.uploading_now'));
|
||||
|
||||
Map<String, bool> uploadedPasteIds = new Map();
|
||||
Map<String, bool> uploadedPasteIds = {};
|
||||
try {
|
||||
List<File>? files;
|
||||
Map<String, String>? additionalFiles;
|
||||
|
||||
if (pasteTextController.text.isNotEmpty) {
|
||||
additionalFiles = Map.from(
|
||||
{'paste-${(new DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt': pasteTextController.text});
|
||||
additionalFiles =
|
||||
Map.from({'paste-${(DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt': pasteTextController.text});
|
||||
}
|
||||
|
||||
if (paths != null && paths!.length > 0) {
|
||||
files = paths!.map((e) => new File(e.path!)).toList();
|
||||
if (paths != null && paths!.isNotEmpty) {
|
||||
files = paths!.map((e) => File(e.path!)).toList();
|
||||
}
|
||||
|
||||
UploadedResponse response = await _fileService.uploadPaste(files, additionalFiles);
|
||||
response.data.ids.forEach((element) {
|
||||
for (var element in response.data.ids) {
|
||||
uploadedPasteIds.putIfAbsent(element, () => false);
|
||||
});
|
||||
}
|
||||
|
||||
if (createMulti && response.data.ids.length > 1) {
|
||||
UploadedMultiResponse multiResponse = await _fileService.uploadMultiPaste(response.data.ids);
|
||||
|
@ -205,7 +205,7 @@ class UploadModel extends BaseModel {
|
|||
|
||||
clearCachedFiles();
|
||||
_pasteTextController.clear();
|
||||
_refreshService.addEvent(RefreshEvent.RefreshHistory);
|
||||
_refreshService.addEvent(RefreshEvent.refreshHistory);
|
||||
errorMessage = null;
|
||||
return uploadedPasteIds;
|
||||
} catch (e) {
|
||||
|
@ -226,21 +226,21 @@ class UploadModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('api.general_rest_error');
|
||||
}
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_ERROR) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketError) {
|
||||
errorMessage = translate('api.socket_error');
|
||||
} else if (e is ServiceException && e.code == ErrorCode.SOCKET_TIMEOUT) {
|
||||
} else if (e is ServiceException && e.code == ErrorCode.socketTimeout) {
|
||||
errorMessage = translate('api.socket_timeout');
|
||||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
setStateMessage(null);
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
throw e;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
setStateMessage(null);
|
||||
setStateView(ViewState.Idle);
|
||||
setStateView(ViewState.idle);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,15 @@ class AppRouter {
|
|||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case StartUpView.routeName:
|
||||
return MaterialPageRoute(builder: (_) => StartUpView());
|
||||
return MaterialPageRoute(builder: (_) => const StartUpView());
|
||||
case AboutView.routeName:
|
||||
return MaterialPageRoute(builder: (_) => AboutView());
|
||||
return MaterialPageRoute(builder: (_) => const AboutView());
|
||||
case HomeView.routeName:
|
||||
return MaterialPageRoute(builder: (_) => TabBarContainerView());
|
||||
return MaterialPageRoute(builder: (_) => const TabBarContainerView());
|
||||
case LoginView.routeName:
|
||||
return MaterialPageRoute(builder: (_) => LoginView());
|
||||
case ProfileView.routeName:
|
||||
return MaterialPageRoute(builder: (_) => ProfileView());
|
||||
return MaterialPageRoute(builder: (_) => const ProfileView());
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => Scaffold(
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class UIHelper {
|
||||
static const double _VerticalSpaceSmall = 10.0;
|
||||
static const double _VerticalSpaceMedium = 20.0;
|
||||
static const double _VerticalSpaceLarge = 60.0;
|
||||
static const double _verticalSpaceSmall = 10.0;
|
||||
static const double _verticalSpaceMedium = 20.0;
|
||||
static const double _verticalSpaceLarge = 60.0;
|
||||
|
||||
static const double _HorizontalSpaceSmall = 10.0;
|
||||
static const double _HorizontalSpaceMedium = 20.0;
|
||||
static const double HorizontalSpaceLarge = 60.0;
|
||||
static const double _horizontalSpaceSmall = 10.0;
|
||||
static const double _horizontalSpaceMedium = 20.0;
|
||||
static const double _horizontalSpaceLarge = 60.0;
|
||||
|
||||
/// Returns a vertical space with height set to [_VerticalSpaceSmall]
|
||||
/// Returns a vertical space with height set to [_verticalSpaceSmall]
|
||||
static Widget verticalSpaceSmall() {
|
||||
return verticalSpace(_VerticalSpaceSmall);
|
||||
return verticalSpace(_verticalSpaceSmall);
|
||||
}
|
||||
|
||||
/// Returns a vertical space with height set to [_VerticalSpaceMedium]
|
||||
/// Returns a vertical space with height set to [_verticalSpaceMedium]
|
||||
static Widget verticalSpaceMedium() {
|
||||
return verticalSpace(_VerticalSpaceMedium);
|
||||
return verticalSpace(_verticalSpaceMedium);
|
||||
}
|
||||
|
||||
/// Returns a vertical space with height set to [_VerticalSpaceLarge]
|
||||
/// Returns a vertical space with height set to [_verticalSpaceLarge]
|
||||
static Widget verticalSpaceLarge() {
|
||||
return verticalSpace(_VerticalSpaceLarge);
|
||||
return verticalSpace(_verticalSpaceLarge);
|
||||
}
|
||||
|
||||
/// Returns a vertical space equal to the [height] supplied
|
||||
|
@ -29,19 +29,19 @@ class UIHelper {
|
|||
return Container(height: height);
|
||||
}
|
||||
|
||||
/// Returns a vertical space with height set to [_HorizontalSpaceSmall]
|
||||
/// Returns a vertical space with height set to [_horizontalSpaceSmall]
|
||||
static Widget horizontalSpaceSmall() {
|
||||
return horizontalSpace(_HorizontalSpaceSmall);
|
||||
return horizontalSpace(_horizontalSpaceSmall);
|
||||
}
|
||||
|
||||
/// Returns a vertical space with height set to [_HorizontalSpaceMedium]
|
||||
/// Returns a vertical space with height set to [_horizontalSpaceMedium]
|
||||
static Widget horizontalSpaceMedium() {
|
||||
return horizontalSpace(_HorizontalSpaceMedium);
|
||||
return horizontalSpace(_horizontalSpaceMedium);
|
||||
}
|
||||
|
||||
/// Returns a vertical space with height set to [HorizontalSpaceLarge]
|
||||
/// Returns a vertical space with height set to [_horizontalSpaceLarge]
|
||||
static Widget horizontalSpaceLarge() {
|
||||
return horizontalSpace(HorizontalSpaceLarge);
|
||||
return horizontalSpace(_horizontalSpaceLarge);
|
||||
}
|
||||
|
||||
/// Returns a vertical space equal to the [width] supplied
|
||||
|
|
|
@ -12,6 +12,8 @@ import 'base_view.dart';
|
|||
class AboutView extends StatelessWidget {
|
||||
static const routeName = '/about';
|
||||
|
||||
const AboutView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final logo = Hero(
|
||||
|
@ -30,13 +32,13 @@ class AboutView extends StatelessWidget {
|
|||
title: Text(translate('titles.about')),
|
||||
enableAbout: false,
|
||||
),
|
||||
body: model.state == ViewState.Busy
|
||||
? Center(child: CircularProgressIndicator())
|
||||
body: model.state == ViewState.busy
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Container(
|
||||
padding: EdgeInsets.all(0),
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10, top: 10),
|
||||
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10, top: 10),
|
||||
children: <Widget>[
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
Center(child: logo),
|
||||
|
@ -75,7 +77,7 @@ class AboutView extends StatelessWidget {
|
|||
Center(
|
||||
child: Linkify(
|
||||
text: translate('about.website'),
|
||||
options: LinkifyOptions(humanize: false),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
onOpen: (link) => model.openLink(link.url),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ class BaseView<T extends BaseModel> extends StatefulWidget {
|
|||
final Widget Function(BuildContext context, T model, Widget? child)? builder;
|
||||
final Function(T)? onModelReady;
|
||||
|
||||
BaseView({this.builder, this.onModelReady});
|
||||
const BaseView({super.key, this.builder, this.onModelReady});
|
||||
|
||||
@override
|
||||
_BaseViewState<T> createState() => _BaseViewState<T>();
|
||||
|
|
|
@ -18,6 +18,8 @@ import 'base_view.dart';
|
|||
class HistoryView extends StatelessWidget {
|
||||
static const routeName = '/history';
|
||||
|
||||
const HistoryView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseView<HistoryModel>(
|
||||
|
@ -33,15 +35,15 @@ class HistoryView extends StatelessWidget {
|
|||
Widget _render(HistoryModel model, BuildContext context) {
|
||||
var url = Provider.of<Session>(context).url;
|
||||
|
||||
return model.state == ViewState.Busy
|
||||
? Center(child: CircularProgressIndicator())
|
||||
return model.state == ViewState.busy
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: (model.errorMessage == null
|
||||
? Container(
|
||||
padding: EdgeInsets.all(0),
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async => await model.getHistory(), child: _renderItems(model, url, context)))
|
||||
: Container(
|
||||
padding: EdgeInsets.all(25),
|
||||
padding: const EdgeInsets.all(25),
|
||||
child: CenteredErrorRow(
|
||||
model.errorMessage,
|
||||
retryCallback: () => model.getHistory(),
|
||||
|
@ -51,8 +53,8 @@ class HistoryView extends StatelessWidget {
|
|||
Widget _renderItems(HistoryModel model, String url, BuildContext context) {
|
||||
List<Widget> cards = [];
|
||||
|
||||
if (model.pastes.length > 0) {
|
||||
model.pastes.reversed.forEach((paste) {
|
||||
if (model.pastes.isNotEmpty) {
|
||||
for (var paste in model.pastes.reversed) {
|
||||
List<Widget> widgets = [];
|
||||
|
||||
var fullPasteUrl = PasteUtil.generateLink(url, paste.id);
|
||||
|
@ -71,7 +73,7 @@ class HistoryView extends StatelessWidget {
|
|||
var copyWidget = ListTile(
|
||||
title: Text(translate('history.copy_link.description')),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.copy, color: blueColor, textDirection: TextDirection.ltr),
|
||||
icon: const Icon(Icons.copy, color: blueColor, textDirection: TextDirection.ltr),
|
||||
onPressed: () {
|
||||
FlutterClipboard.copy(fullPasteUrl).then((value) {
|
||||
final snackBar = SnackBar(
|
||||
|
@ -83,7 +85,7 @@ class HistoryView extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
content: Text(translate('history.copy_link.copied')),
|
||||
duration: Duration(seconds: 10),
|
||||
duration: const Duration(seconds: 10),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
});
|
||||
|
@ -92,7 +94,7 @@ class HistoryView extends StatelessWidget {
|
|||
var deleteWidget = ListTile(
|
||||
title: Text(translate('history.delete')),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.delete, color: redColor),
|
||||
icon: const Icon(Icons.delete, color: redColor),
|
||||
onPressed: () {
|
||||
model.deletePaste(paste.id);
|
||||
}));
|
||||
|
@ -120,13 +122,13 @@ class HistoryView extends StatelessWidget {
|
|||
widgets.add(fileSizeWidget);
|
||||
widgets.add(mimeTypeWidget);
|
||||
} else {
|
||||
paste.items!.forEach((element) {
|
||||
for (var element in paste.items!) {
|
||||
widgets.add(ListTile(
|
||||
title: Text(element!),
|
||||
subtitle: Text(translate('history.multipaste_element')),
|
||||
trailing: _renderOpenInBrowser(model, '$url/$element'),
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
widgets.add(dateWidget);
|
||||
|
@ -135,7 +137,7 @@ class HistoryView extends StatelessWidget {
|
|||
widgets.add(deleteWidget);
|
||||
|
||||
var expandable = ExpandableTheme(
|
||||
data: ExpandableThemeData(
|
||||
data: const ExpandableThemeData(
|
||||
iconPlacement: ExpandablePanelIconPlacement.right,
|
||||
headerAlignment: ExpandablePanelHeaderAlignment.center,
|
||||
hasIcon: true,
|
||||
|
@ -146,7 +148,7 @@ class HistoryView extends StatelessWidget {
|
|||
header: InkWell(
|
||||
child: Text(
|
||||
paste.id,
|
||||
style: TextStyle(color: blueColor),
|
||||
style: const TextStyle(color: blueColor),
|
||||
textAlign: TextAlign.left,
|
||||
)),
|
||||
expanded: Column(
|
||||
|
@ -162,15 +164,15 @@ class HistoryView extends StatelessWidget {
|
|||
trailing: Wrap(children: [
|
||||
openInBrowserButton,
|
||||
IconButton(
|
||||
icon: Icon(Icons.share, color: blueColor, textDirection: TextDirection.ltr),
|
||||
icon: const Icon(Icons.share, color: blueColor, textDirection: TextDirection.ltr),
|
||||
onPressed: () async {
|
||||
await Share.share(fullPasteUrl);
|
||||
})
|
||||
]),
|
||||
subtitle: Text(!paste.isMulti! ? paste.filename! : '', style: TextStyle(fontStyle: FontStyle.italic)),
|
||||
subtitle: Text(!paste.isMulti! ? paste.filename! : '', style: const TextStyle(fontStyle: FontStyle.italic)),
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
cards.add(Card(
|
||||
child: ListTile(
|
||||
|
@ -181,14 +183,14 @@ class HistoryView extends StatelessWidget {
|
|||
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(8),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
children: cards,
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderOpenInBrowser(HistoryModel model, String url) {
|
||||
return IconButton(
|
||||
icon: Icon(Icons.open_in_new, color: blueColor, textDirection: TextDirection.ltr),
|
||||
icon: const Icon(Icons.open_in_new, color: blueColor, textDirection: TextDirection.ltr),
|
||||
onPressed: () {
|
||||
return model.openLink(url);
|
||||
});
|
||||
|
|
|
@ -9,12 +9,14 @@ import 'base_view.dart';
|
|||
class HomeView extends StatelessWidget {
|
||||
static const routeName = '/home';
|
||||
|
||||
const HomeView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseView<HomeModel>(
|
||||
builder: (context, model, child) => Scaffold(
|
||||
appBar: MyAppBar(title: Text(translate('app.title'))),
|
||||
body: model.state == ViewState.Busy ? Center(child: CircularProgressIndicator()) : Container()),
|
||||
body: model.state == ViewState.busy ? const Center(child: CircularProgressIndicator()) : Container()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ class LoginView extends StatelessWidget {
|
|||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
|
||||
LoginView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final logo = Hero(
|
||||
|
@ -35,11 +37,11 @@ class LoginView extends StatelessWidget {
|
|||
onModelReady: (model) => model.init(),
|
||||
builder: (context, model, child) => Scaffold(
|
||||
appBar: MyAppBar(title: Text(translate('titles.login'))),
|
||||
body: model.state == ViewState.Busy
|
||||
? Center(child: CircularProgressIndicator())
|
||||
body: model.state == ViewState.busy
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 10.0, right: 10.0),
|
||||
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
|
||||
children: <Widget>[
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
Center(child: logo),
|
||||
|
@ -50,7 +52,7 @@ class LoginView extends StatelessWidget {
|
|||
alignment: WrapAlignment.center,
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
child: Icon(Icons.help),
|
||||
child: const Icon(Icons.help),
|
||||
onTap: () {
|
||||
_dialogService.showDialog(
|
||||
title: translate('login.compatibility_dialog.title'),
|
||||
|
@ -79,7 +81,7 @@ class LoginView extends StatelessWidget {
|
|||
apiKeyController: model.apiKeyController),
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.login, color: blueColor),
|
||||
icon: const Icon(Icons.login, color: blueColor),
|
||||
label: Text(translate('login.button')),
|
||||
onPressed: () async {
|
||||
var loginSuccess = await model.login();
|
||||
|
|
|
@ -8,6 +8,8 @@ import '../shared/app_colors.dart';
|
|||
import 'history_view.dart';
|
||||
|
||||
class AuthenticatedNavBarView extends StatefulWidget {
|
||||
const AuthenticatedNavBarView({super.key});
|
||||
|
||||
@override
|
||||
AuthenticatedNavBarState createState() => AuthenticatedNavBarState();
|
||||
}
|
||||
|
@ -52,17 +54,17 @@ class AuthenticatedNavBarState extends State<AuthenticatedNavBarView> with Singl
|
|||
Container(
|
||||
color: myColor,
|
||||
alignment: Alignment.center,
|
||||
child: UploadView(),
|
||||
child: const UploadView(),
|
||||
),
|
||||
Container(
|
||||
color: myColor,
|
||||
alignment: Alignment.center,
|
||||
child: HistoryView(),
|
||||
child: const HistoryView(),
|
||||
),
|
||||
Container(
|
||||
color: myColor,
|
||||
alignment: Alignment.center,
|
||||
child: ProfileView(),
|
||||
child: const ProfileView(),
|
||||
),
|
||||
][_currentTabIndex],
|
||||
);
|
||||
|
|
|
@ -15,6 +15,8 @@ import 'base_view.dart';
|
|||
class ProfileView extends StatelessWidget {
|
||||
static const routeName = '/profile';
|
||||
|
||||
const ProfileView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseView<ProfileModel>(
|
||||
|
@ -26,8 +28,8 @@ class ProfileView extends StatelessWidget {
|
|||
var url = Provider.of<Session>(context).url;
|
||||
var apiKey = Provider.of<Session>(context).apiKey;
|
||||
|
||||
return model.state == ViewState.Busy
|
||||
? Center(child: CircularProgressIndicator())
|
||||
return model.state == ViewState.busy
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: ListView(
|
||||
children: <Widget>[
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
|
@ -45,7 +47,7 @@ class ProfileView extends StatelessWidget {
|
|||
child: Linkify(
|
||||
onOpen: (link) => model.openLink(link.url),
|
||||
text: translate('profile.connection', args: {'url': url}),
|
||||
options: LinkifyOptions(humanize: false),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
))),
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
Padding(
|
||||
|
@ -56,12 +58,12 @@ class ProfileView extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
const CircularProgressIndicator(),
|
||||
Text(translate('profile.show_config_loading')),
|
||||
],
|
||||
))
|
||||
: ElevatedButton.icon(
|
||||
icon: Icon(Icons.settings, color: blueColor),
|
||||
icon: const Icon(Icons.settings, color: blueColor),
|
||||
label: Text(
|
||||
translate('profile.show_config'),
|
||||
),
|
||||
|
@ -72,7 +74,7 @@ class ProfileView extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
child: ElevatedButton.icon(
|
||||
icon: Icon(Icons.lock, color: orangeColor),
|
||||
icon: const Icon(Icons.lock, color: orangeColor),
|
||||
label: Text(
|
||||
translate('profile.reveal_api_key'),
|
||||
),
|
||||
|
@ -83,7 +85,7 @@ class ProfileView extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
child: ElevatedButton.icon(
|
||||
icon: Icon(Icons.exit_to_app, color: redColor),
|
||||
icon: const Icon(Icons.exit_to_app, color: redColor),
|
||||
label: Text(
|
||||
translate('profile.logout'),
|
||||
),
|
||||
|
|
|
@ -7,19 +7,21 @@ import '../../core/viewmodels/startup_model.dart';
|
|||
class StartUpView extends StatelessWidget {
|
||||
static const routeName = '/';
|
||||
|
||||
const StartUpView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder<StartUpViewModel>.reactive(
|
||||
viewModelBuilder: () => StartUpViewModel(),
|
||||
onModelReady: (model) => model.handleStartUpLogic(),
|
||||
builder: (context, model, child) => Scaffold(
|
||||
body: model.state == ViewState.Busy
|
||||
body: model.state == ViewState.busy
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
const CircularProgressIndicator(),
|
||||
(model.stateMessage!.isNotEmpty ? Text(model.stateMessage!) : Container())
|
||||
]))
|
||||
: Container()));
|
||||
|
|
|
@ -6,17 +6,17 @@ import 'package:provider/provider.dart';
|
|||
import '../../core/models/session.dart';
|
||||
|
||||
class TabBarContainerView extends StatelessWidget {
|
||||
const TabBarContainerView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Session? currentSession = Provider.of<Session?>(context);
|
||||
bool isAuthenticated = currentSession != null ? currentSession.apiKey.isNotEmpty : false;
|
||||
|
||||
if (isAuthenticated) {
|
||||
return AuthenticatedNavBarView();
|
||||
return const AuthenticatedNavBarView();
|
||||
}
|
||||
|
||||
return Container(
|
||||
child: LoginView(),
|
||||
);
|
||||
return LoginView();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import 'base_view.dart';
|
|||
class UploadView extends StatelessWidget {
|
||||
static const routeName = '/upload';
|
||||
|
||||
const UploadView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseView<UploadModel>(
|
||||
|
@ -23,19 +25,19 @@ class UploadView extends StatelessWidget {
|
|||
}
|
||||
|
||||
bool _isUploadButtonEnabled(UploadModel model) {
|
||||
return model.pasteTextTouched || (model.paths != null && model.paths!.length > 0);
|
||||
return model.pasteTextTouched || (model.paths != null && model.paths!.isNotEmpty);
|
||||
}
|
||||
|
||||
Widget _render(UploadModel model, BuildContext context) {
|
||||
var url = Provider.of<Session>(context).url;
|
||||
|
||||
return model.state == ViewState.Busy
|
||||
return model.state == ViewState.busy
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
const CircularProgressIndicator(),
|
||||
(model.stateMessage != null && model.stateMessage!.isNotEmpty ? Text(model.stateMessage!) : Container())
|
||||
]))
|
||||
: ListView(children: <Widget>[
|
||||
|
@ -50,15 +52,15 @@ class UploadView extends StatelessWidget {
|
|||
minLines: 1,
|
||||
maxLines: 7,
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: Icon(
|
||||
prefixIcon: const Icon(
|
||||
Icons.text_snippet,
|
||||
),
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () => model.pasteTextController.clear(),
|
||||
icon: Icon(Icons.clear),
|
||||
icon: const Icon(Icons.clear),
|
||||
),
|
||||
hintText: translate('upload.text_to_be_pasted'),
|
||||
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
|
||||
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
|
||||
),
|
||||
controller: model.pasteTextController)),
|
||||
|
@ -75,14 +77,14 @@ class UploadView extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.file_copy_sharp, color: blueColor),
|
||||
icon: const Icon(Icons.file_copy_sharp, color: blueColor),
|
||||
onPressed: () => model.openFileExplorer(),
|
||||
label: Text(
|
||||
translate('upload.open_file_explorer'),
|
||||
)),
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.cancel, color: orangeColor),
|
||||
onPressed: model.paths != null && model.paths!.length > 0
|
||||
icon: const Icon(Icons.cancel, color: orangeColor),
|
||||
onPressed: model.paths != null && model.paths!.isNotEmpty
|
||||
? () => model.clearCachedFiles()
|
||||
: null,
|
||||
label: Text(
|
||||
|
@ -126,13 +128,13 @@ class UploadView extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
content: Text(translate('upload.uploaded')),
|
||||
duration: Duration(seconds: 10),
|
||||
duration: const Duration(seconds: 10),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
});
|
||||
}
|
||||
},
|
||||
icon: Icon(Icons.upload_rounded, color: greenColor),
|
||||
icon: const Icon(Icons.upload_rounded, color: greenColor),
|
||||
label: Text(
|
||||
translate('upload.upload'),
|
||||
)),
|
||||
|
@ -144,9 +146,9 @@ class UploadView extends StatelessWidget {
|
|||
: Container(),
|
||||
Builder(
|
||||
builder: (BuildContext context) => model.loadingPath
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10.0),
|
||||
child: const CircularProgressIndicator(),
|
||||
? const Padding(
|
||||
padding: EdgeInsets.only(bottom: 10.0),
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: model.paths != null
|
||||
? Container(
|
||||
|
@ -159,7 +161,7 @@ class UploadView extends StatelessWidget {
|
|||
final String name = (isMultiPath
|
||||
? model.paths!.map((e) => e.name).toList()[index]
|
||||
: model.fileName ?? '...');
|
||||
final path = model.paths!.length > 0
|
||||
final path = model.paths!.isNotEmpty
|
||||
? model.paths!.map((e) => e.path).toList()[index].toString()
|
||||
: '';
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@ import '../../locator.dart';
|
|||
import '../../ui/views/about_view.dart';
|
||||
|
||||
class AboutIconButton extends StatelessWidget {
|
||||
AboutIconButton();
|
||||
AboutIconButton({super.key});
|
||||
|
||||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: Icon(Icons.help),
|
||||
icon: const Icon(Icons.help),
|
||||
onPressed: () {
|
||||
_navigationService.navigateTo(AboutView.routeName);
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ class CenteredErrorRow extends StatelessWidget {
|
|||
final Function? retryCallback;
|
||||
final String? message;
|
||||
|
||||
CenteredErrorRow(this.message, {this.retryCallback});
|
||||
const CenteredErrorRow(this.message, {super.key, this.retryCallback});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -20,7 +20,7 @@ class CenteredErrorRow extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(child: Center(child: Text(message!, style: TextStyle(color: redColor)))),
|
||||
Expanded(child: Center(child: Text(message!, style: const TextStyle(color: redColor)))),
|
||||
],
|
||||
),
|
||||
(retryCallback != null
|
||||
|
@ -30,7 +30,7 @@ class CenteredErrorRow extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
Center(
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.refresh),
|
||||
icon: const Icon(Icons.refresh),
|
||||
color: primaryAccentColor,
|
||||
onPressed: () {
|
||||
retryCallback!();
|
||||
|
|
|
@ -10,18 +10,19 @@ class LoginApiKeyHeaders extends StatelessWidget {
|
|||
|
||||
final String? validationMessage;
|
||||
|
||||
LoginApiKeyHeaders({required this.uriController, required this.apiKeyController, this.validationMessage});
|
||||
const LoginApiKeyHeaders(
|
||||
{super.key, required this.uriController, required this.apiKeyController, this.validationMessage});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(children: <Widget>[
|
||||
this.validationMessage != null ? Text(validationMessage!, style: TextStyle(color: redColor)) : Container(),
|
||||
LoginTextField(uriController, translate('login.url_placeholder'), Icon(Icons.link),
|
||||
validationMessage != null ? Text(validationMessage!, style: const TextStyle(color: redColor)) : Container(),
|
||||
LoginTextField(uriController, translate('login.url_placeholder'), const Icon(Icons.link),
|
||||
keyboardType: TextInputType.url),
|
||||
LoginTextField(
|
||||
apiKeyController,
|
||||
translate('login.apikey_placeholder'),
|
||||
Icon(Icons.vpn_key),
|
||||
const Icon(Icons.vpn_key),
|
||||
obscureText: true,
|
||||
),
|
||||
]);
|
||||
|
|
|
@ -11,8 +11,9 @@ class LoginCredentialsHeaders extends StatelessWidget {
|
|||
|
||||
final String? validationMessage;
|
||||
|
||||
LoginCredentialsHeaders(
|
||||
{required this.uriController,
|
||||
const LoginCredentialsHeaders(
|
||||
{super.key,
|
||||
required this.uriController,
|
||||
required this.usernameController,
|
||||
required this.passwordController,
|
||||
this.validationMessage});
|
||||
|
@ -20,12 +21,12 @@ class LoginCredentialsHeaders extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(children: <Widget>[
|
||||
this.validationMessage != null ? Text(validationMessage!, style: TextStyle(color: redColor)) : Container(),
|
||||
LoginTextField(uriController, translate('login.url_placeholder'), Icon(Icons.link),
|
||||
validationMessage != null ? Text(validationMessage!, style: const TextStyle(color: redColor)) : Container(),
|
||||
LoginTextField(uriController, translate('login.url_placeholder'), const Icon(Icons.link),
|
||||
keyboardType: TextInputType.url),
|
||||
LoginTextField(usernameController, translate('login.username_placeholder'), Icon(Icons.person),
|
||||
LoginTextField(usernameController, translate('login.username_placeholder'), const Icon(Icons.person),
|
||||
keyboardType: TextInputType.name),
|
||||
LoginTextField(passwordController, translate('login.password_placeholder'), Icon(Icons.vpn_key),
|
||||
LoginTextField(passwordController, translate('login.password_placeholder'), const Icon(Icons.vpn_key),
|
||||
obscureText: true),
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ class LoginTextField extends StatelessWidget {
|
|||
final bool obscureText;
|
||||
final Widget prefixIcon;
|
||||
|
||||
LoginTextField(this.controller, this.placeHolder, this.prefixIcon,
|
||||
{this.keyboardType = TextInputType.text, this.obscureText = false});
|
||||
const LoginTextField(this.controller, this.placeHolder, this.prefixIcon,
|
||||
{super.key, this.keyboardType = TextInputType.text, this.obscureText = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.0),
|
||||
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
|
||||
height: 50.0,
|
||||
alignment: Alignment.centerLeft,
|
||||
decoration: BoxDecoration(color: whiteColor, borderRadius: BorderRadius.circular(10.0)),
|
||||
|
@ -26,11 +26,11 @@ class LoginTextField extends StatelessWidget {
|
|||
decoration: InputDecoration(
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () => controller.clear(),
|
||||
icon: Icon(Icons.clear),
|
||||
icon: const Icon(Icons.clear),
|
||||
),
|
||||
prefixIcon: prefixIcon,
|
||||
hintText: placeHolder,
|
||||
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
|
||||
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
|
||||
),
|
||||
controller: controller),
|
||||
|
|
|
@ -10,9 +10,7 @@ class MyAppBar extends AppBar {
|
|||
: super(key: key, title: Row(children: <Widget>[title]), actions: _renderIconButtons(actionWidgets, enableAbout));
|
||||
|
||||
static List<Widget> _renderIconButtons(List<Widget>? actionWidgets, bool aboutEnabled) {
|
||||
if (actionWidgets == null) {
|
||||
actionWidgets = [];
|
||||
}
|
||||
actionWidgets ??= [];
|
||||
|
||||
List<Widget> widgets = [...actionWidgets];
|
||||
|
||||
|
|
20
pubspec.lock
20
pubspec.lock
|
@ -70,7 +70,7 @@ packages:
|
|||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
version: "2.3.3"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -237,6 +237,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -316,7 +323,7 @@ packages:
|
|||
source: hosted
|
||||
version: "4.0.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -357,6 +364,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
logger:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -428,7 +442,7 @@ packages:
|
|||
source: hosted
|
||||
version: "2.0.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
|
|
|
@ -41,13 +41,16 @@ dependencies:
|
|||
package_info_plus: 3.0.2
|
||||
json_annotation: 4.7.0
|
||||
dynamic_color: 1.5.4
|
||||
intl: 0.17.0
|
||||
path: 1.8.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
build_runner: 2.3.2
|
||||
build_runner: 2.3.3
|
||||
built_value_generator: 8.4.2
|
||||
json_serializable: 6.5.4
|
||||
flutter_lints: 2.0.1
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
|
Loading…
Reference in a new issue