Increased target SDK to 33, Increased dart to 2.17.3, Indicate configuration loading in profile view

This commit is contained in:
Varakh 2022-06-23 00:42:37 +02:00
parent c8007e8415
commit 7ef179906d
15 changed files with 196 additions and 182 deletions

View file

@ -1,7 +1,9 @@
# CHANGELOG # CHANGELOG
## 1.4.3+16 - UNRELEASED ## 1.4.3+16 - UNRELEASED
* ... * Increased target SDK to `33`
* Increased dart to `>= 2.17.3`
* Indicate configuration loading in profile view
## 1.4.2+15 ## 1.4.2+15
* Minor cleanup * Minor cleanup

View file

@ -32,8 +32,11 @@ Start by installing dependencies and generating entities!
### Working versions for SDK ### Working versions for SDK
``` ```
Flutter version 2.10.5 • Flutter version 3.0.2
Dart version 2.16.2 • Framework revision cd41fdd495
• Engine revision f15f824b57
• Dart version 2.17.3
• DevTools version 2.12.2
``` ```
## Dependencies ## Dependencies

View file

@ -31,7 +31,7 @@ if (keystorePropertiesFile.exists()) {
} }
android { android {
compileSdkVersion 31 compileSdkVersion 33
lintOptions { lintOptions {
disable 'InvalidPackage' disable 'InvalidPackage'
@ -40,7 +40,7 @@ android {
defaultConfig { defaultConfig {
applicationId "de.varakh.fbmobile" applicationId "de.varakh.fbmobile"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 31 targetSdkVersion 33
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View file

@ -105,6 +105,7 @@
"instance": "Instance", "instance": "Instance",
"connection": "{url}", "connection": "{url}",
"show_config": "Show configuration", "show_config": "Show configuration",
"show_config_loading": "Loading configuration...",
"shown_config": { "shown_config": {
"title": "Configuration", "title": "Configuration",
"description": "Upload max size: {uploadMaxSize}\n\nMax files per request: {maxFilesPerRequest}\n\nMax inputs vars: {maxInputVars}\n\nRequest max size: {requestMaxSize}", "description": "Upload max size: {uploadMaxSize}\n\nMax files per request: {maxFilesPerRequest}\n\nMax inputs vars: {maxInputVars}\n\nRequest max size: {requestMaxSize}",

View file

@ -26,23 +26,21 @@ class MyApp extends StatelessWidget {
state: LocalizationProvider.of(context).state, state: LocalizationProvider.of(context).state,
child: StreamProvider<SwipeEvent?>( child: StreamProvider<SwipeEvent?>(
initialData: null, initialData: null,
create: (context) => create: (context) => locator<SwipeService>().swipeEventController.stream,
locator<SwipeService>().swipeEventController.stream,
child: StreamProvider<RefreshEvent?>( child: StreamProvider<RefreshEvent?>(
initialData: null, initialData: null,
create: (context) => create: (context) => locator<RefreshService>().refreshEventController.stream,
locator<RefreshService>().refreshEventController.stream,
child: StreamProvider<Session?>( child: StreamProvider<Session?>(
initialData: Session.initial(), initialData: Session.initial(),
create: (context) => create: (context) => locator<SessionService>().sessionController.stream,
locator<SessionService>().sessionController.stream,
child: LifeCycleManager( child: LifeCycleManager(
child: MaterialApp( child: MaterialApp(
debugShowCheckedModeBanner: false,
title: translate('app.title'), title: translate('app.title'),
builder: (context, child) => Navigator( builder: (context, child) => Navigator(
key: locator<DialogService>().dialogNavigationKey, key: locator<DialogService>().dialogNavigationKey,
onGenerateRoute: (settings) => MaterialPageRoute( onGenerateRoute: (settings) =>
builder: (context) => DialogManager(child: child)), MaterialPageRoute(builder: (context) => DialogManager(child: child)),
), ),
theme: ThemeData( theme: ThemeData(
brightness: Brightness.light, brightness: Brightness.light,

View file

@ -16,14 +16,10 @@ class LifeCycleManager extends StatefulWidget {
_LifeCycleManagerState createState() => _LifeCycleManagerState(); _LifeCycleManagerState createState() => _LifeCycleManagerState();
} }
class _LifeCycleManagerState extends State<LifeCycleManager> class _LifeCycleManagerState extends State<LifeCycleManager> with WidgetsBindingObserver {
with WidgetsBindingObserver {
final Logger logger = getLogger(); final Logger logger = getLogger();
List<StoppableService> servicesToManage = [ List<StoppableService> servicesToManage = [locator<SessionService>(), locator<PermissionService>()];
locator<SessionService>(),
locator<PermissionService>()
];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -33,13 +29,13 @@ class _LifeCycleManagerState extends State<LifeCycleManager>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance!.addObserver(this); WidgetsBinding.instance.addObserver(this);
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
WidgetsBinding.instance!.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
} }
@override @override

View file

@ -18,7 +18,37 @@ class BaseModel extends ChangeNotifier {
String? get stateMessage => _stateMap[STATE_MESSAGE] as String?; String? get stateMessage => _stateMap[STATE_MESSAGE] as String?;
void setStateValue(String key, Object? stateValue) { bool getStateValueAsBoolean(String key) {
if (_stateMap.containsKey(key) && _stateMap[key] is bool) {
return _stateMap[key] as bool;
}
return false;
}
String? getStateValueAsString(String key) {
if (_stateMap.containsKey(key) && _stateMap[key] is String) {
return _stateMap[key] as String;
}
return null;
}
int? getStateValueAsInt(String key) {
if (_stateMap.containsKey(key) && _stateMap[key] is int) {
return _stateMap[key] as int;
}
return null;
}
void setStateBoolValue(String key, bool stateValue) => _setStateValue(key, stateValue);
void setStateIntValue(String key, int? stateValue) => _setStateValue(key, stateValue);
void setStateStringValue(String key, String? stateValue) => _setStateValue(key, stateValue);
void _setStateValue(String key, Object? stateValue) {
if (_stateMap.containsKey(key)) { if (_stateMap.containsKey(key)) {
_stateMap.update(key, (value) => stateValue); _stateMap.update(key, (value) => stateValue);
} else { } else {
@ -41,11 +71,11 @@ class BaseModel extends ChangeNotifier {
} }
void setStateView(ViewState stateView) { void setStateView(ViewState stateView) {
setStateValue(STATE_VIEW, stateView); _setStateValue(STATE_VIEW, stateView);
} }
void setStateMessage(String? stateMessage) { void setStateMessage(String? stateMessage) {
setStateValue(STATE_MESSAGE, stateMessage); _setStateValue(STATE_MESSAGE, stateMessage);
} }
@override @override

View file

@ -6,7 +6,6 @@ import 'package:logger/logger.dart';
import '../../core/services/session_service.dart'; import '../../core/services/session_service.dart';
import '../../locator.dart'; import '../../locator.dart';
import '../enums/error_code.dart'; import '../enums/error_code.dart';
import '../enums/viewstate.dart';
import '../error/rest_service_exception.dart'; import '../error/rest_service_exception.dart';
import '../error/service_exception.dart'; import '../error/service_exception.dart';
import '../models/rest/config.dart'; import '../models/rest/config.dart';
@ -18,18 +17,21 @@ import '../util/logger.dart';
import 'base_model.dart'; import 'base_model.dart';
class ProfileModel extends BaseModel { class ProfileModel extends BaseModel {
static const _configurationButtonLoading = 'configurationButtonLoading';
final SessionService _sessionService = locator<SessionService>(); final SessionService _sessionService = locator<SessionService>();
final DialogService _dialogService = locator<DialogService>(); final DialogService _dialogService = locator<DialogService>();
final LinkService _linkService = locator<LinkService>(); final LinkService _linkService = locator<LinkService>();
final FileService _fileService = locator<FileService>(); final FileService _fileService = locator<FileService>();
final Logger _logger = getLogger(); final Logger _logger = getLogger();
bool get configLoading => getStateValueAsBoolean(_configurationButtonLoading);
String? errorMessage; String? errorMessage;
Future logout() async { Future logout() async {
var dialogResult = await _dialogService.showConfirmationDialog( var dialogResult = await _dialogService.showConfirmationDialog(
title: translate('logout.title'), title: translate('logout.title'), description: translate('logout.confirm'));
description: translate('logout.confirm'));
if (dialogResult.confirmed!) { if (dialogResult.confirmed!) {
await _sessionService.logout(); await _sessionService.logout();
@ -39,12 +41,11 @@ class ProfileModel extends BaseModel {
Future revealApiKey(String? apiKey) async { Future revealApiKey(String? apiKey) async {
await _dialogService.showDialog( await _dialogService.showDialog(
title: translate('profile.revealed_api_key.title'), title: translate('profile.revealed_api_key.title'),
description: translate('profile.revealed_api_key.description', description: translate('profile.revealed_api_key.description', args: {'apiKey': apiKey}));
args: {'apiKey': apiKey}));
} }
Future showConfig(String url) async { Future showConfig(String url) async {
setStateView(ViewState.Busy); setStateBoolValue(_configurationButtonLoading, true);
Config? config; Config? config;
try { try {
config = await _fileService.getConfig(url); config = await _fileService.getConfig(url);
@ -53,15 +54,13 @@ class ProfileModel extends BaseModel {
if (e is RestServiceException) { if (e is RestServiceException) {
if (e.statusCode == HttpStatus.unauthorized) { if (e.statusCode == HttpStatus.unauthorized) {
errorMessage = translate('login.errors.wrong_credentials'); errorMessage = translate('login.errors.wrong_credentials');
} else if (e.statusCode != HttpStatus.unauthorized && } else if (e.statusCode != HttpStatus.unauthorized && e.statusCode == HttpStatus.forbidden) {
e.statusCode == HttpStatus.forbidden) {
errorMessage = translate('login.errors.forbidden'); errorMessage = translate('login.errors.forbidden');
} else if (e.statusCode == HttpStatus.notFound) { } else if (e.statusCode == HttpStatus.notFound) {
errorMessage = translate('api.incompatible_error_not_found'); errorMessage = translate('api.incompatible_error_not_found');
} }
if (e.statusCode == HttpStatus.badRequest) { if (e.statusCode == HttpStatus.badRequest) {
errorMessage = translate('api.bad_request', errorMessage = translate('api.bad_request', args: {'reason': e.responseBody.message});
args: {'reason': e.responseBody.message});
} else { } else {
errorMessage = translate('api.general_rest_error'); errorMessage = translate('api.general_rest_error');
} }
@ -71,32 +70,29 @@ class ProfileModel extends BaseModel {
errorMessage = translate('api.socket_timeout'); errorMessage = translate('api.socket_timeout');
} else { } else {
errorMessage = translate('app.unknown_error'); errorMessage = translate('app.unknown_error');
setStateView(ViewState.Idle); setStateBoolValue(_configurationButtonLoading, false);
_sessionService.logout(); _sessionService.logout();
setStateView(ViewState.Idle); setStateBoolValue(_configurationButtonLoading, false);
_logger.e('An unknown error occurred', e); _logger.e('An unknown error occurred', e);
throw e; throw e;
} }
} }
setStateView(ViewState.Idle); setStateBoolValue(_configurationButtonLoading, false);
if (config != null && errorMessage == null) { if (config != null && errorMessage == null) {
await _dialogService.showDialog( await _dialogService.showDialog(
title: translate('profile.shown_config.title'), title: translate('profile.shown_config.title'),
description: translate('profile.shown_config.description', args: { description: translate('profile.shown_config.description', args: {
'uploadMaxSize': 'uploadMaxSize': FormatterUtil.formatBytes(config.uploadMaxSize as int, 2),
FormatterUtil.formatBytes(config.uploadMaxSize as int, 2),
'maxFilesPerRequest': config.maxFilesPerRequest, 'maxFilesPerRequest': config.maxFilesPerRequest,
'maxInputVars': config.maxInputVars, 'maxInputVars': config.maxInputVars,
'requestMaxSize': 'requestMaxSize': FormatterUtil.formatBytes(config.requestMaxSize as int, 2)
FormatterUtil.formatBytes(config.requestMaxSize as int, 2)
})); }));
} else { } else {
await _dialogService.showDialog( await _dialogService.showDialog(
title: translate('profile.shown_config.error.title'), title: translate('profile.shown_config.error.title'),
description: translate('profile.shown_config.error.description', description: translate('profile.shown_config.error.description', args: {'message': errorMessage}));
args: {'message': errorMessage}));
} }
} }

View file

@ -51,12 +51,11 @@ class UploadModel extends BaseModel {
void init() { void init() {
_pasteTextController.addListener(() { _pasteTextController.addListener(() {
pasteTextTouched = pasteTextController.text.isNotEmpty; pasteTextTouched = pasteTextController.text.isNotEmpty;
setStateValue("PASTE_TEXT_TOUCHED", pasteTextTouched); setStateBoolValue("PASTE_TEXT_TOUCHED", pasteTextTouched);
}); });
// For sharing images coming from outside the app while the app is in the memory // For sharing images coming from outside the app while the app is in the memory
_intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream() _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream().listen((List<SharedMediaFile> value) {
.listen((List<SharedMediaFile> value) {
if (value.length > 0) { if (value.length > 0) {
setStateView(ViewState.Busy); setStateView(ViewState.Busy);
paths = value.map((sharedFile) { paths = value.map((sharedFile) {
@ -98,8 +97,7 @@ class UploadModel extends BaseModel {
}); });
// For sharing or opening urls/text coming from outside the app while the app is in the memory // For sharing or opening urls/text coming from outside the app while the app is in the memory
_intentDataStreamSubscription = _intentDataStreamSubscription = ReceiveSharingIntent.getTextStream().listen((String value) {
ReceiveSharingIntent.getTextStream().listen((String value) {
if (value.isNotEmpty) { if (value.isNotEmpty) {
setStateView(ViewState.Busy); setStateView(ViewState.Busy);
pasteTextController.text = value; pasteTextController.text = value;
@ -167,9 +165,7 @@ class UploadModel extends BaseModel {
allowMultiple: true, allowMultiple: true,
withData: false, withData: false,
withReadStream: true, withReadStream: true,
allowedExtensions: (_extension?.isNotEmpty ?? false) allowedExtensions: (_extension?.isNotEmpty ?? false) ? _extension?.replaceAll(' ', '').split(',') : null,
? _extension?.replaceAll(' ', '').split(',')
: null,
)) ))
?.files; ?.files;
} on PlatformException catch (e) { } on PlatformException catch (e) {
@ -204,25 +200,21 @@ class UploadModel extends BaseModel {
Map<String, String>? additionalFiles; Map<String, String>? additionalFiles;
if (pasteTextController.text.isNotEmpty) { if (pasteTextController.text.isNotEmpty) {
additionalFiles = Map.from({ additionalFiles = Map.from(
'paste-${(new DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt': {'paste-${(new DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt': pasteTextController.text});
pasteTextController.text
});
} }
if (paths != null && paths!.length > 0) { if (paths != null && paths!.length > 0) {
files = paths!.map((e) => new File(e.path!)).toList(); files = paths!.map((e) => new File(e.path!)).toList();
} }
UploadedResponse response = UploadedResponse response = await _fileService.uploadPaste(files, additionalFiles);
await _fileService.uploadPaste(files, additionalFiles);
response.data.ids.forEach((element) { response.data.ids.forEach((element) {
uploadedPasteIds.putIfAbsent(element, () => false); uploadedPasteIds.putIfAbsent(element, () => false);
}); });
if (createMulti && response.data.ids.length > 1) { if (createMulti && response.data.ids.length > 1) {
UploadedMultiResponse multiResponse = UploadedMultiResponse multiResponse = await _fileService.uploadMultiPaste(response.data.ids);
await _fileService.uploadMultiPaste(response.data.ids);
uploadedPasteIds.putIfAbsent(multiResponse.data.urlId, () => true); uploadedPasteIds.putIfAbsent(multiResponse.data.urlId, () => true);
} }
@ -242,11 +234,9 @@ class UploadModel extends BaseModel {
e.responseBody is RestError && e.responseBody is RestError &&
e.responseBody.message != null) { e.responseBody.message != null) {
if (e.statusCode == HttpStatus.badRequest) { if (e.statusCode == HttpStatus.badRequest) {
errorMessage = translate('api.bad_request', errorMessage = translate('api.bad_request', args: {'reason': e.responseBody.message});
args: {'reason': e.responseBody.message});
} else { } else {
errorMessage = translate('api.general_rest_error_payload', errorMessage = translate('api.general_rest_error_payload', args: {'message': e.responseBody.message});
args: {'message': e.responseBody.message});
} }
} else { } else {
errorMessage = translate('api.general_rest_error'); errorMessage = translate('api.general_rest_error');

View file

@ -9,10 +9,10 @@ import 'locator.dart';
/// main entry point used to configure log level, locales, ... /// main entry point used to configure log level, locales, ...
void main() async { void main() async {
setupLogger(Level.info); setupLogger(Level.info);
// setupLogger(Level.debug);
setupLocator(); setupLocator();
var delegate = await LocalizationDelegate.create(fallbackLocale: 'en', supportedLocales: ['en']); var delegate = await LocalizationDelegate.create(fallbackLocale: 'en', supportedLocales: ['en', 'en_US']);
WidgetsFlutterBinding.ensureInitialized();
runApp(LocalizedApp(delegate, MyApp())); runApp(LocalizedApp(delegate, MyApp()));
} }

View file

@ -53,15 +53,26 @@ class ProfileView extends StatelessWidget {
UIHelper.verticalSpaceMedium(), UIHelper.verticalSpaceMedium(),
Padding( Padding(
padding: const EdgeInsets.only(left: 25.0, right: 25.0), padding: const EdgeInsets.only(left: 25.0, right: 25.0),
child: ElevatedButton.icon( child: model.configLoading
icon: Icon(Icons.settings, color: blueColor), ? Center(
label: Text( child: Column(
translate('profile.show_config'), mainAxisAlignment: MainAxisAlignment.center,
style: TextStyle(color: buttonForegroundColor), crossAxisAlignment: CrossAxisAlignment.center,
), children: [
onPressed: () async { CircularProgressIndicator(),
await model.showConfig(url); Text(translate('profile.show_config_loading'),
})), style: TextStyle(color: buttonBackgroundColor))
],
))
: ElevatedButton.icon(
icon: Icon(Icons.settings, color: blueColor),
label: Text(
translate('profile.show_config'),
style: TextStyle(color: buttonForegroundColor),
),
onPressed: () async {
await model.showConfig(url);
})),
UIHelper.verticalSpaceMedium(), UIHelper.verticalSpaceMedium(),
Padding( Padding(
padding: const EdgeInsets.only(left: 25.0, right: 25.0), padding: const EdgeInsets.only(left: 25.0, right: 25.0),

View file

@ -19,8 +19,7 @@ class AuthenticatedTabBarView extends StatefulWidget {
AuthenticatedTabBarState createState() => AuthenticatedTabBarState(); AuthenticatedTabBarState createState() => AuthenticatedTabBarState();
} }
class AuthenticatedTabBarState extends State<AuthenticatedTabBarView> class AuthenticatedTabBarState extends State<AuthenticatedTabBarView> with SingleTickerProviderStateMixin {
with SingleTickerProviderStateMixin {
final Logger _logger = getLogger(); final Logger _logger = getLogger();
final SwipeService _swipeService = locator<SwipeService>(); final SwipeService _swipeService = locator<SwipeService>();
@ -51,8 +50,7 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
} }
}); });
_swipeEventSubscription = _swipeEventSubscription = _swipeService.swipeEventController.stream.listen((SwipeEvent event) {
_swipeService.swipeEventController.stream.listen((SwipeEvent event) {
_logger.d('Received a swipe event for the authenticated tab bar: $event'); _logger.d('Received a swipe event for the authenticated tab bar: $event');
int targetIndex = _currentTabIndex; int targetIndex = _currentTabIndex;
@ -72,8 +70,7 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
targetIndex = _tabPages.length - 1; targetIndex = _tabPages.length - 1;
} }
_logger.d( _logger.d("Changing to tab '$targetIndex' because of a swipe event '$event'");
"Changing to tab '$targetIndex' because of a swipe event '$event'");
_tabController!.animateTo(targetIndex); _tabController!.animateTo(targetIndex);
}); });
} }
@ -91,12 +88,9 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
double yourWidth = width / 3; double yourWidth = width / 3;
double yourHeight = 55; double yourHeight = 55;
Color colorTabItem0 = Color colorTabItem0 = _currentTabIndex == 0 ? blueColor : primaryAccentColor;
_currentTabIndex == 0 ? blueColor : primaryAccentColor; Color colorTabItem1 = _currentTabIndex == 1 ? blueColor : primaryAccentColor;
Color colorTabItem1 = Color colorTabItem2 = _currentTabIndex == 2 ? blueColor : primaryAccentColor;
_currentTabIndex == 1 ? blueColor : primaryAccentColor;
Color colorTabItem2 =
_currentTabIndex == 2 ? blueColor : primaryAccentColor;
List<Widget> _tabsButton = [ List<Widget> _tabsButton = [
Container( Container(
@ -105,13 +99,10 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
alignment: Alignment.center, alignment: Alignment.center,
child: Tab( child: Tab(
icon: Icon( icon: Icon(
_currentTabIndex == 0 _currentTabIndex == 0 ? Icons.upload_outlined : Icons.upload_rounded,
? Icons.upload_outlined
: Icons.upload_rounded,
color: colorTabItem0, color: colorTabItem0,
), ),
child: Text(translate('tabs.upload'), child: Text(translate('tabs.upload'), style: TextStyle(color: colorTabItem0)),
style: TextStyle(color: colorTabItem0)),
), ),
), ),
Container( Container(
@ -120,13 +111,10 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
alignment: Alignment.center, alignment: Alignment.center,
child: Tab( child: Tab(
icon: Icon( icon: Icon(
_currentTabIndex == 1 _currentTabIndex == 1 ? Icons.history_outlined : Icons.history_rounded,
? Icons.history_outlined
: Icons.history_rounded,
color: colorTabItem1, color: colorTabItem1,
), ),
child: Text(translate('tabs.history'), child: Text(translate('tabs.history'), style: TextStyle(color: colorTabItem1)),
style: TextStyle(color: colorTabItem1)),
), ),
), ),
Container( Container(
@ -135,13 +123,10 @@ class AuthenticatedTabBarState extends State<AuthenticatedTabBarView>
alignment: Alignment.center, alignment: Alignment.center,
child: Tab( child: Tab(
icon: Icon( icon: Icon(
_currentTabIndex == 2 _currentTabIndex == 2 ? Icons.person_outlined : Icons.person_rounded,
? Icons.person_outlined
: Icons.person_rounded,
color: colorTabItem2, color: colorTabItem2,
), ),
child: Text(translate('tabs.profile'), child: Text(translate('tabs.profile'), style: TextStyle(color: colorTabItem2)),
style: TextStyle(color: colorTabItem2)),
), ),
), ),
]; ];

View file

@ -8,11 +8,7 @@ class MyAppBar extends AppBar {
static final List<Widget> aboutEnabledWidgets = [AboutIconButton()]; static final List<Widget> aboutEnabledWidgets = [AboutIconButton()];
static final List<Widget> aboutDisabledWidgets = []; static final List<Widget> aboutDisabledWidgets = [];
MyAppBar( MyAppBar({Key? key, required Widget title, List<Widget>? actionWidgets, bool enableAbout = true})
{Key? key,
required Widget title,
List<Widget>? actionWidgets,
bool enableAbout = true})
: super( : super(
key: key, key: key,
title: Row(children: <Widget>[title]), title: Row(children: <Widget>[title]),
@ -23,8 +19,7 @@ class MyAppBar extends AppBar {
), ),
backgroundColor: primaryAccentColor); backgroundColor: primaryAccentColor);
static List<Widget> _renderIconButtons( static List<Widget> _renderIconButtons(List<Widget>? actionWidgets, bool aboutEnabled) {
List<Widget>? actionWidgets, bool aboutEnabled) {
if (actionWidgets == null) { if (actionWidgets == null) {
actionWidgets = []; actionWidgets = [];
} }

View file

@ -7,21 +7,21 @@ packages:
name: _fe_analyzer_shared name: _fe_analyzer_shared
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "39.0.0" version: "40.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.1.0"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.0" version: "2.3.1"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -63,14 +63,14 @@ packages:
name: build_resolvers name: build_resolvers
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.8" version: "2.0.9"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.10" version: "2.1.11"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
@ -91,14 +91,14 @@ packages:
name: built_value name: built_value
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "8.2.3" version: "8.3.3"
built_value_generator: built_value_generator:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: built_value_generator name: built_value_generator
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "8.2.3" version: "8.3.3"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -147,14 +147,14 @@ packages:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.0.2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@ -168,7 +168,7 @@ packages:
name: cupertino_icons name: cupertino_icons
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
@ -189,14 +189,14 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.2" version: "1.2.1"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -210,14 +210,14 @@ packages:
name: file_picker name: file_picker
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.5.1" version: "4.6.1"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -241,7 +241,7 @@ packages:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.0.6"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -253,7 +253,7 @@ packages:
name: flutter_translate name: flutter_translate
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.1.0"
flutter_web_plugins: flutter_web_plugins:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -265,7 +265,7 @@ packages:
name: frontend_server_client name: frontend_server_client
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
get_it: get_it:
dependency: "direct main" dependency: "direct main"
description: description:
@ -279,7 +279,7 @@ packages:
name: glob name: glob
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.1.0"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
@ -300,14 +300,14 @@ packages:
name: http_multi_server name: http_multi_server
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.2.0" version: "3.2.1"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.0.1"
intl: intl:
dependency: transitive dependency: transitive
description: description:
@ -328,7 +328,7 @@ packages:
name: js name: js
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.3" version: "0.6.4"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -377,7 +377,7 @@ packages:
name: material_color_utilities name: material_color_utilities
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "0.1.4"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@ -405,7 +405,7 @@ packages:
name: package_config name: package_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.1.0"
package_info_plus: package_info_plus:
dependency: "direct main" dependency: "direct main"
description: description:
@ -454,42 +454,42 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.5" version: "2.1.7"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "2.0.4"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.0.7"
permission_handler: permission_handler:
dependency: "direct main" dependency: "direct main"
description: description:
name: permission_handler name: permission_handler
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "9.2.0" version: "10.0.0"
permission_handler_android: permission_handler_android:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_android name: permission_handler_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "9.0.2+1" version: "10.0.0"
permission_handler_apple: permission_handler_apple:
dependency: transitive dependency: transitive
description: description:
@ -531,7 +531,7 @@ packages:
name: pool name: pool
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.0" version: "1.5.1"
process: process:
dependency: transitive dependency: transitive
description: description:
@ -545,7 +545,7 @@ packages:
name: provider name: provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.2" version: "6.0.3"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@ -566,7 +566,7 @@ packages:
name: quiver name: quiver
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1+1" version: "3.1.0"
receive_sharing_intent: receive_sharing_intent:
dependency: "direct main" dependency: "direct main"
description: description:
@ -580,7 +580,7 @@ packages:
name: share_plus name: share_plus
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.4" version: "4.0.9"
share_plus_linux: share_plus_linux:
dependency: transitive dependency: transitive
description: description:
@ -594,63 +594,63 @@ packages:
name: share_plus_macos name: share_plus_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.2" version: "3.0.3"
share_plus_web: share_plus_web:
dependency: transitive dependency: transitive
description: description:
name: share_plus_web name: share_plus_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
share_plus_windows: share_plus_windows:
dependency: transitive dependency: transitive
description: description:
name: share_plus_windows name: share_plus_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.13" version: "2.0.15"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.11" version: "2.0.12"
shared_preferences_ios: shared_preferences_ios:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_ios name: shared_preferences_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.1"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.1"
shared_preferences_macos: shared_preferences_macos:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_macos name: shared_preferences_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "2.0.4"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -664,28 +664,28 @@ packages:
name: shared_preferences_web name: shared_preferences_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "2.0.4"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
simple_gesture_detector: simple_gesture_detector:
dependency: "direct main" dependency: "direct main"
description: description:
@ -718,7 +718,7 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.2"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -732,7 +732,14 @@ packages:
name: stacked name: stacked
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.3" version: "2.3.12"
stacked_core:
dependency: transitive
description:
name: stacked_core
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.3"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
@ -767,7 +774,7 @@ packages:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.8" version: "0.4.9"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@ -781,7 +788,7 @@ packages:
name: typed_data name: typed_data
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
universal_io: universal_io:
dependency: transitive dependency: transitive
description: description:
@ -795,56 +802,56 @@ packages:
name: url_launcher name: url_launcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.0" version: "6.1.4"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.16" version: "6.0.17"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.15" version: "6.0.17"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_platform_interface name: url_launcher_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.1.0"
url_launcher_web: url_launcher_web:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.9" version: "2.0.12"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
validators: validators:
dependency: "direct main" dependency: "direct main"
description: description:
@ -858,7 +865,7 @@ packages:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@ -879,7 +886,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.5.2" version: "2.6.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@ -893,7 +900,7 @@ packages:
name: yaml name: yaml
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.1.1"
sdks: sdks:
dart: ">=2.16.2 <3.0.0" dart: ">=2.17.3 <3.0.0"
flutter: ">=2.10.0" flutter: ">=2.10.0"

View file

@ -14,30 +14,30 @@ description: A mobile client for FileBin.
version: 1.4.3+16 version: 1.4.3+16
environment: environment:
sdk: '>=2.16.2 <3.0.0' sdk: '>=2.17.3 <3.0.0'
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
cupertino_icons: 1.0.4 cupertino_icons: 1.0.5
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
flutter_translate: 3.0.1 flutter_translate: 3.1.0 # > 3.x breaks with WidgetBinding, wait for dependency update
provider: 6.0.2 provider: 6.0.3
stacked: 2.3.3 stacked: 2.3.12
get_it: 7.2.0 get_it: 7.2.0
logger: 1.1.0 logger: 1.1.0
shared_preferences: 2.0.13 shared_preferences: 2.0.15
http: 0.13.4 http: 0.13.4
validators: 3.0.0 validators: 3.0.0
flutter_linkify: 5.0.2 flutter_linkify: 5.0.2
url_launcher: 6.1.0 url_launcher: 6.1.4
expandable: 5.0.1 expandable: 5.0.1
share_plus: 4.0.4 share_plus: 4.0.9
file_picker: 4.5.1 file_picker: 4.6.1
clipboard: 0.1.3 clipboard: 0.1.3
receive_sharing_intent: 1.4.5 receive_sharing_intent: 1.4.5
permission_handler: 9.2.0 permission_handler: 10.0.0
package_info_plus: 1.4.2 package_info_plus: 1.4.2
simple_gesture_detector: 0.2.0 simple_gesture_detector: 0.2.0
json_annotation: 4.5.0 json_annotation: 4.5.0
@ -45,8 +45,8 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: 2.1.10 build_runner: 2.1.11
built_value_generator: ^8.2.3 built_value_generator: 8.3.3
json_serializable: 6.2.0 json_serializable: 6.2.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the