Compare commits

..

3 commits

Author SHA1 Message Date
8d11584811 Merge pull request 'feature/5-use-material-3-material-you #2 #5' (#6) from feature/5-use-material-3-material-you into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #6

Closes #2 #5
2022-12-16 15:46:52 +00:00
db9fef6798 Adapt min dart sdk version for pipeline #5
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-16 16:33:01 +01:00
6fedb8c661 Update dependencies and flutter 3.3, use Material You and remove unsupported swipe for Material You navigation bar #5
Some checks failed
continuous-integration/drone/push Build is failing
2022-12-16 16:30:07 +01:00
23 changed files with 251 additions and 523 deletions

View file

@ -4,7 +4,7 @@ name: default
steps:
- name: build
image: cirrusci/flutter:3.0.5
image: cirrusci/flutter:3.3.9
commands:
- flutter doctor
- flutter pub get

View file

@ -1,11 +1,13 @@
# CHANGELOG
## 1.4.3+16 - UNRELEASED
## 1.5.0+16 - UNRELEASED
* Switched to Material You defaulting to blue swatch colors respecting dark mode
* Switched to Material You navigation bar and removed unsupported swipe navigation
* Increased target SDK to `33`
* Increased dart to `>= 2.17.3`
* Increased dart to `>= 2.18.6`
* Indicate configuration loading in profile view
* Switched linked git repository away from GitHub
* Updated dependencies
* Updated internal dependencies
## 1.4.2+15
* Minor cleanup

View file

@ -1,10 +1,10 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:provider/provider.dart';
import 'core/enums/refresh_event.dart';
import 'core/enums/swipe_event.dart';
import 'core/manager/dialog_manager.dart';
import 'core/manager/lifecycle_manager.dart';
import 'core/models/session.dart';
@ -12,13 +12,14 @@ import 'core/services/dialog_service.dart';
import 'core/services/navigation_service.dart';
import 'core/services/refresh_service.dart';
import 'core/services/session_service.dart';
import 'core/services/swipe_service.dart';
import 'locator.dart';
import 'ui/app_router.dart';
import 'ui/shared/app_colors.dart';
import 'ui/views/startup_view.dart';
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() {
initializeDateFormatting('en');
@ -30,34 +31,32 @@ class MyApp extends StatelessWidget {
return LocalizationProvider(
state: LocalizationProvider.of(context).state,
child: StreamProvider<SwipeEvent?>(
child: StreamProvider<RefreshEvent?>(
initialData: null,
create: (context) => locator<SwipeService>().swipeEventController.stream,
child: StreamProvider<RefreshEvent?>(
initialData: null,
create: (context) => locator<RefreshService>().refreshEventController.stream,
child: StreamProvider<Session?>(
initialData: Session.initial(),
create: (context) => locator<SessionService>().sessionController.stream,
child: LifeCycleManager(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: translate('app.title'),
builder: (context, child) => Navigator(
key: locator<DialogService>().dialogNavigationKey,
onGenerateRoute: (settings) =>
MaterialPageRoute(builder: (context) => DialogManager(child: child)),
),
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: primaryAccentColor as MaterialColor?,
primaryColor: primaryAccentColor),
onGenerateRoute: AppRouter.generateRoute,
navigatorKey: locator<NavigationService>().navigationKey,
home: StartUpView(),
supportedLocales: localizationDelegate.supportedLocales,
locale: localizationDelegate.currentLocale,
)),
))));
create: (context) => locator<RefreshService>().refreshEventController.stream,
child: StreamProvider<Session?>(
initialData: Session.initial(),
create: (context) => locator<SessionService>().sessionController.stream,
child: LifeCycleManager(child: DynamicColorBuilder(builder: (lightColorScheme, darkColorScheme) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: translate('app.title'),
builder: (context, child) => Navigator(
key: locator<DialogService>().dialogNavigationKey,
onGenerateRoute: (settings) => MaterialPageRoute(builder: (context) => DialogManager(child: child)),
),
theme: ThemeData(
useMaterial3: true,
brightness: Brightness.light,
colorScheme: lightColorScheme ?? _defaultLightColorScheme),
darkTheme: ThemeData(useMaterial3: true, colorScheme: darkColorScheme ?? _defaultDarkColorScheme),
onGenerateRoute: AppRouter.generateRoute,
navigatorKey: locator<NavigationService>().navigationKey,
home: StartUpView(),
supportedLocales: localizationDelegate.supportedLocales,
locale: localizationDelegate.currentLocale,
);
})),
)));
}
}

View file

@ -1 +0,0 @@
enum SwipeEvent { Start, Left, Right, End }

View file

@ -1,13 +0,0 @@
import 'dart:async';
import '../enums/swipe_event.dart';
class SwipeService {
StreamController<SwipeEvent> swipeEventController = StreamController<SwipeEvent>.broadcast();
void addEvent(SwipeEvent event) {
if (swipeEventController.hasListener) {
swipeEventController.add(event);
}
}
}

View file

@ -12,7 +12,6 @@ import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import '../../locator.dart';
import '../enums/error_code.dart';
import '../enums/refresh_event.dart';
import '../enums/swipe_event.dart';
import '../enums/viewstate.dart';
import '../error/rest_service_exception.dart';
import '../error/service_exception.dart';
@ -22,7 +21,6 @@ import '../models/rest/uploaded_response.dart';
import '../services/file_service.dart';
import '../services/link_service.dart';
import '../services/refresh_service.dart';
import '../services/swipe_service.dart';
import '../util/logger.dart';
import '../util/paste_util.dart';
import 'base_model.dart';
@ -32,7 +30,6 @@ class UploadModel extends BaseModel {
final FileService _fileService = locator<FileService>();
final LinkService _linkService = locator<LinkService>();
final RefreshService _refreshService = locator<RefreshService>();
final SwipeService _swipeService = locator<SwipeService>();
TextEditingController _pasteTextController = TextEditingController();
bool pasteTextTouched = false;
@ -67,9 +64,6 @@ class UploadModel extends BaseModel {
});
}).toList();
setStateView(ViewState.Idle);
if (paths!.isNotEmpty && paths!.length > 0) {
_swipeService.addEvent(SwipeEvent.Start);
}
}
}, onError: (err) {
_errorIntentHandle(err);
@ -88,9 +82,6 @@ class UploadModel extends BaseModel {
});
}).toList();
setStateView(ViewState.Idle);
if (paths!.isNotEmpty && paths!.length > 0) {
_swipeService.addEvent(SwipeEvent.Start);
}
}
}, onError: (err) {
_errorIntentHandle(err);
@ -102,7 +93,6 @@ class UploadModel extends BaseModel {
setStateView(ViewState.Busy);
pasteTextController.text = value;
setStateView(ViewState.Idle);
_swipeService.addEvent(SwipeEvent.Start);
}
}, onError: (err) {
_errorIntentHandle(err);
@ -114,9 +104,6 @@ class UploadModel extends BaseModel {
setStateView(ViewState.Busy);
pasteTextController.text = value;
setStateView(ViewState.Idle);
if (paths!.isNotEmpty && paths!.length > 0) {
_swipeService.addEvent(SwipeEvent.Start);
}
}
}, onError: (err) {
_errorIntentHandle(err);
@ -128,8 +115,6 @@ class UploadModel extends BaseModel {
errorMessage = translate('upload.retrieval_intent');
_logger.e('Error while retrieving shared data: $err');
setStateView(ViewState.Idle);
_swipeService.addEvent(SwipeEvent.Start);
}
String? generatePasteLinks(Map<String, bool>? uploads, String url) {

View file

@ -11,7 +11,6 @@ import 'core/services/permission_service.dart';
import 'core/services/refresh_service.dart';
import 'core/services/session_service.dart';
import 'core/services/storage_service.dart';
import 'core/services/swipe_service.dart';
import 'core/services/user_service.dart';
import 'core/viewmodels/about_model.dart';
import 'core/viewmodels/history_model.dart';
@ -42,7 +41,6 @@ void setupLocator() {
locator.registerLazySingleton(() => LinkService());
locator.registerLazySingleton(() => PermissionService());
locator.registerLazySingleton(() => RefreshService());
locator.registerLazySingleton(() => SwipeService());
/// view models
locator.registerFactory(() => StartUpViewModel());

View file

@ -1,10 +1,5 @@
import 'package:flutter/material.dart';
const Color backgroundColor = whiteColor;
/// Colors
const Color primaryBackgroundColor = whiteColor;
const Map<int, Color> colors = {
50: Color.fromRGBO(63, 69, 75, .1),
100: Color.fromRGBO(63, 69, 75, .2),
@ -19,8 +14,6 @@ const Map<int, Color> colors = {
};
const MaterialColor myColor = MaterialColor(0xFF3F454B, colors);
const Color primaryAccentColor = myColor;
const Color buttonBackgroundColor = primaryAccentColor;
const Color buttonForegroundColor = whiteColor;
const Color blueColor = Colors.blue;
const Color whiteColor = Colors.white;

View file

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
const headerStyle = TextStyle(fontSize: 35, fontWeight: FontWeight.w900);
const subHeaderStyle = TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500);

View file

@ -6,7 +6,6 @@ import '../../core/enums/viewstate.dart';
import '../../core/viewmodels/about_model.dart';
import '../../ui/shared/text_styles.dart';
import '../../ui/shared/ui_helpers.dart';
import '../shared/app_colors.dart';
import '../widgets/my_appbar.dart';
import 'base_view.dart';
@ -31,7 +30,6 @@ class AboutView extends StatelessWidget {
title: Text(translate('titles.about')),
enableAbout: false,
),
backgroundColor: backgroundColor,
body: model.state == ViewState.Busy
? Center(child: CircularProgressIndicator())
: Container(

View file

@ -13,7 +13,6 @@ import '../../core/viewmodels/history_model.dart';
import '../../ui/widgets/centered_error_row.dart';
import '../shared/app_colors.dart';
import '../widgets/my_appbar.dart';
import '../widgets/swipe_navigation.dart';
import 'base_view.dart';
class HistoryView extends StatelessWidget {
@ -26,10 +25,8 @@ class HistoryView extends StatelessWidget {
model.init();
return model.getHistory();
},
builder: (context, model, child) => Scaffold(
appBar: MyAppBar(title: Text(translate('titles.history'))),
backgroundColor: backgroundColor,
body: SwipeNavigation(child: _render(model, context))),
builder: (context, model, child) =>
Scaffold(appBar: MyAppBar(title: Text(translate('titles.history'))), body: _render(model, context)),
);
}

View file

@ -3,7 +3,6 @@ import 'package:flutter_translate/flutter_translate.dart';
import '../../core/enums/viewstate.dart';
import '../../core/viewmodels/home_model.dart';
import '../shared/app_colors.dart';
import '../widgets/my_appbar.dart';
import 'base_view.dart';
@ -15,7 +14,6 @@ class HomeView extends StatelessWidget {
return BaseView<HomeModel>(
builder: (context, model, child) => Scaffold(
appBar: MyAppBar(title: Text(translate('app.title'))),
backgroundColor: backgroundColor,
body: model.state == ViewState.Busy ? Center(child: CircularProgressIndicator()) : Container()),
);
}

View file

@ -36,7 +36,6 @@ class LoginView extends StatelessWidget {
onModelReady: (model) => model.init(),
builder: (context, model, child) => Scaffold(
appBar: MyAppBar(title: Text(translate('titles.login'))),
backgroundColor: backgroundColor,
body: model.state == ViewState.Busy
? Center(child: CircularProgressIndicator())
: ListView(
@ -56,7 +55,7 @@ class LoginView extends StatelessWidget {
style: subHeaderStyle,
),
InkWell(
child: Icon(Icons.help, color: buttonBackgroundColor),
child: Icon(Icons.help),
onTap: () {
_dialogService.showDialog(
title: translate('login.compatibility_dialog.title'),
@ -85,7 +84,7 @@ class LoginView extends StatelessWidget {
apiKeyController: model.apiKeyController),
UIHelper.verticalSpaceMedium(),
ElevatedButton(
child: Text(translate('login.button'), style: TextStyle(color: buttonForegroundColor)),
child: Text(translate('login.button')),
onPressed: () async {
var loginSuccess = await model.login();
if (loginSuccess) {

View file

@ -0,0 +1,70 @@
import 'package:fbmobile/core/util/logger.dart';
import 'package:fbmobile/ui/views/profile_view.dart';
import 'package:fbmobile/ui/views/upload_view.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import '../shared/app_colors.dart';
import 'history_view.dart';
class AuthenticatedNavBarView extends StatefulWidget {
@override
AuthenticatedNavBarState createState() => AuthenticatedNavBarState();
}
class AuthenticatedNavBarState extends State<AuthenticatedNavBarView> with SingleTickerProviderStateMixin {
final Logger _logger = getLogger();
int _currentTabIndex = 0;
void updateIndex(int targetIndex) {
setState(() {
_currentTabIndex = targetIndex;
_logger.d("Changing current tab index to '$targetIndex'");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: NavigationBar(
key: UniqueKey(),
onDestinationSelected: (int index) {
updateIndex(index);
},
selectedIndex: _currentTabIndex,
labelBehavior: NavigationDestinationLabelBehavior.alwaysHide,
destinations: const <Widget>[
NavigationDestination(
icon: Icon(Icons.upload_outlined),
label: 'Upload',
),
NavigationDestination(
icon: Icon(Icons.history_outlined),
label: 'History',
),
NavigationDestination(
icon: Icon(Icons.person_outlined),
label: 'Profile',
),
],
),
body: <Widget>[
Container(
color: myColor,
alignment: Alignment.center,
child: UploadView(),
),
Container(
color: myColor,
alignment: Alignment.center,
child: HistoryView(),
),
Container(
color: myColor,
alignment: Alignment.center,
child: ProfileView(),
),
][_currentTabIndex],
);
}
}

View file

@ -10,7 +10,6 @@ import '../shared/app_colors.dart';
import '../shared/text_styles.dart';
import '../shared/ui_helpers.dart';
import '../widgets/my_appbar.dart';
import '../widgets/swipe_navigation.dart';
import 'base_view.dart';
class ProfileView extends StatelessWidget {
@ -19,10 +18,8 @@ class ProfileView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BaseView<ProfileModel>(
builder: (context, model, child) => Scaffold(
appBar: MyAppBar(title: Text(translate('titles.profile'))),
backgroundColor: backgroundColor,
body: SwipeNavigation(child: _render(model, context))));
builder: (context, model, child) =>
Scaffold(appBar: MyAppBar(title: Text(translate('titles.profile'))), body: _render(model, context)));
}
Widget _render(ProfileModel model, BuildContext context) {
@ -60,15 +57,13 @@ class ProfileView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text(translate('profile.show_config_loading'),
style: TextStyle(color: buttonBackgroundColor))
Text(translate('profile.show_config_loading')),
],
))
: ElevatedButton.icon(
icon: Icon(Icons.settings, color: blueColor),
label: Text(
translate('profile.show_config'),
style: TextStyle(color: buttonForegroundColor),
),
onPressed: () async {
await model.showConfig(url);
@ -80,7 +75,6 @@ class ProfileView extends StatelessWidget {
icon: Icon(Icons.lock, color: orangeColor),
label: Text(
translate('profile.reveal_api_key'),
style: TextStyle(color: buttonForegroundColor),
),
onPressed: () {
model.revealApiKey(apiKey);
@ -92,7 +86,6 @@ class ProfileView extends StatelessWidget {
icon: Icon(Icons.exit_to_app, color: redColor),
label: Text(
translate('profile.logout'),
style: TextStyle(color: buttonForegroundColor),
),
onPressed: () async {
await model.logout();

View file

@ -1,67 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart';
import '../shared/app_colors.dart';
import 'login_view.dart';
class AnonymousTabBarView extends StatefulWidget {
@override
AnonymousTabBarState createState() => AnonymousTabBarState();
}
class AnonymousTabBarState extends State<AnonymousTabBarView> with SingleTickerProviderStateMixin {
TabController? _tabController;
int _currentTabIndex = 0;
List<Widget> _realPages = [LoginView()];
List<Widget> _tabPages = [LoginView()];
List<bool> _hasInit = [true];
List<Widget> _tabsButton = [
Tab(
icon: Icon(Icons.person_outline, color: blueColor),
child: Text(
translate('tabs.login'),
style: TextStyle(color: blueColor),
),
)
];
@override
void initState() {
super.initState();
_tabController = TabController(length: _realPages.length, vsync: this)
..addListener(() {
int selectedIndex = _tabController!.index;
if (_currentTabIndex != selectedIndex) {
if (!_hasInit[selectedIndex]) {
_tabPages[selectedIndex] = _realPages[selectedIndex];
_hasInit[selectedIndex] = true;
}
setState(() => _currentTabIndex = selectedIndex);
}
});
}
@override
void dispose() {
_tabController!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(index: _currentTabIndex, children: _tabPages),
bottomNavigationBar: BottomAppBar(
child: TabBar(
labelColor: primaryAccentColor,
indicatorColor: blueColor,
indicatorWeight: 3.0,
tabs: _tabsButton,
controller: _tabController,
),
),
);
}
}

View file

@ -1,149 +0,0 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:logger/logger.dart';
import '../../core/enums/swipe_event.dart';
import '../../core/services/swipe_service.dart';
import '../../core/util/logger.dart';
import '../../locator.dart';
import '../shared/app_colors.dart';
import 'history_view.dart';
import 'profile_view.dart';
import 'upload_view.dart';
class AuthenticatedTabBarView extends StatefulWidget {
@override
AuthenticatedTabBarState createState() => AuthenticatedTabBarState();
}
class AuthenticatedTabBarState extends State<AuthenticatedTabBarView> with SingleTickerProviderStateMixin {
final Logger _logger = getLogger();
final SwipeService _swipeService = locator<SwipeService>();
late StreamSubscription _swipeEventSubscription;
TabController? _tabController;
int _currentTabIndex = 0;
List<Widget> _realPages = [UploadView(), HistoryView(), ProfileView()];
List<Widget> _tabPages = [
UploadView(),
Container(),
Container(),
];
List<bool> _hasInit = [true, false, false];
@override
void initState() {
super.initState();
_tabController = TabController(length: _realPages.length, vsync: this)
..addListener(() {
int selectedIndex = _tabController!.index;
if (_currentTabIndex != selectedIndex) {
if (!_hasInit[selectedIndex]) {
_tabPages[selectedIndex] = _realPages[selectedIndex];
_hasInit[selectedIndex] = true;
}
setState(() => _currentTabIndex = selectedIndex);
}
});
_swipeEventSubscription = _swipeService.swipeEventController.stream.listen((SwipeEvent event) {
_logger.d('Received a swipe event for the authenticated tab bar: $event');
int targetIndex = _currentTabIndex;
if (SwipeEvent.Left == event) {
targetIndex = min(_currentTabIndex + 1, _realPages.length - 1);
}
if (SwipeEvent.Right == event) {
targetIndex = max(_currentTabIndex - 1, 0);
}
if (SwipeEvent.Start == event) {
targetIndex = 0;
}
if (SwipeEvent.End == event) {
targetIndex = _tabPages.length - 1;
}
_logger.d("Changing to tab '$targetIndex' because of a swipe event '$event'");
_tabController!.animateTo(targetIndex);
});
}
@override
void dispose() {
_tabController!.dispose();
_swipeEventSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double yourWidth = width / 3;
double yourHeight = 55;
Color colorTabItem0 = _currentTabIndex == 0 ? blueColor : primaryAccentColor;
Color colorTabItem1 = _currentTabIndex == 1 ? blueColor : primaryAccentColor;
Color colorTabItem2 = _currentTabIndex == 2 ? blueColor : primaryAccentColor;
List<Widget> _tabsButton = [
Container(
width: yourWidth,
height: yourHeight,
alignment: Alignment.center,
child: Tab(
icon: Icon(
_currentTabIndex == 0 ? Icons.upload_outlined : Icons.upload_rounded,
color: colorTabItem0,
),
child: Text(translate('tabs.upload'), style: TextStyle(color: colorTabItem0)),
),
),
Container(
width: yourWidth,
height: yourHeight,
alignment: Alignment.center,
child: Tab(
icon: Icon(
_currentTabIndex == 1 ? Icons.history_outlined : Icons.history_rounded,
color: colorTabItem1,
),
child: Text(translate('tabs.history'), style: TextStyle(color: colorTabItem1)),
),
),
Container(
width: yourWidth,
height: yourHeight,
alignment: Alignment.center,
child: Tab(
icon: Icon(
_currentTabIndex == 2 ? Icons.person_outlined : Icons.person_rounded,
color: colorTabItem2,
),
child: Text(translate('tabs.profile'), style: TextStyle(color: colorTabItem2)),
),
),
];
return Scaffold(
body: IndexedStack(index: _currentTabIndex, children: _tabPages),
bottomNavigationBar: BottomAppBar(
child: TabBar(
indicatorSize: TabBarIndicatorSize.label,
labelColor: primaryAccentColor,
indicatorColor: blueColor,
indicatorWeight: 3.0,
labelPadding: EdgeInsets.all(0),
tabs: _tabsButton,
isScrollable: true,
controller: _tabController,
)),
);
}
}

View file

@ -1,9 +1,9 @@
import 'package:fbmobile/ui/views/login_view.dart';
import 'package:fbmobile/ui/views/navbar_authenticated.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../core/models/session.dart';
import 'tabbar_anonymous.dart';
import 'tabbar_authenticated.dart';
class TabBarContainerView extends StatelessWidget {
@override
@ -12,9 +12,11 @@ class TabBarContainerView extends StatelessWidget {
bool isAuthenticated = currentSession != null ? currentSession.apiKey.isNotEmpty : false;
if (isAuthenticated) {
return AuthenticatedTabBarView();
return AuthenticatedNavBarView();
}
return AnonymousTabBarView();
return Container(
child: LoginView(),
);
}
}

View file

@ -9,7 +9,6 @@ import '../../core/viewmodels/upload_model.dart';
import '../shared/app_colors.dart';
import '../widgets/centered_error_row.dart';
import '../widgets/my_appbar.dart';
import '../widgets/swipe_navigation.dart';
import 'base_view.dart';
class UploadView extends StatelessWidget {
@ -19,10 +18,8 @@ class UploadView extends StatelessWidget {
Widget build(BuildContext context) {
return BaseView<UploadModel>(
onModelReady: (model) => model.init(),
builder: (context, model, child) => Scaffold(
appBar: MyAppBar(title: Text(translate('titles.upload'))),
backgroundColor: backgroundColor,
body: SwipeNavigation(child: _render(model, context))));
builder: (context, model, child) =>
Scaffold(appBar: MyAppBar(title: Text(translate('titles.upload'))), body: _render(model, context)));
}
bool _isUploadButtonEnabled(UploadModel model) {
@ -55,7 +52,6 @@ class UploadView extends StatelessWidget {
decoration: InputDecoration(
prefixIcon: Icon(
Icons.text_snippet,
color: buttonBackgroundColor,
),
suffixIcon: IconButton(
onPressed: () => model.pasteTextController.clear(),
@ -83,7 +79,6 @@ class UploadView extends StatelessWidget {
onPressed: () => model.openFileExplorer(),
label: Text(
translate('upload.open_file_explorer'),
style: TextStyle(color: buttonForegroundColor),
)),
ElevatedButton.icon(
icon: Icon(Icons.cancel, color: orangeColor),
@ -92,7 +87,6 @@ class UploadView extends StatelessWidget {
: null,
label: Text(
translate('upload.clear_temporary_files'),
style: TextStyle(color: buttonForegroundColor),
)),
],
)),
@ -141,7 +135,6 @@ class UploadView extends StatelessWidget {
icon: Icon(Icons.upload_rounded, color: greenColor),
label: Text(
translate('upload.upload'),
style: TextStyle(color: buttonForegroundColor),
)),
])),
model.errorMessage != null && model.errorMessage!.isNotEmpty

View file

@ -1,7 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../shared/app_colors.dart';
import '../widgets/about_iconbutton.dart';
class MyAppBar extends AppBar {
@ -9,15 +7,7 @@ class MyAppBar extends AppBar {
static final List<Widget> aboutDisabledWidgets = [];
MyAppBar({Key? key, required Widget title, List<Widget>? actionWidgets, bool enableAbout = true})
: super(
key: key,
title: Row(children: <Widget>[title]),
actions: _renderIconButtons(actionWidgets, enableAbout),
systemOverlayStyle: SystemUiOverlayStyle(
systemNavigationBarColor: primaryAccentColor, // Navigation bar
statusBarColor: primaryAccentColor, // Status bar
),
backgroundColor: primaryAccentColor);
: super(key: key, title: Row(children: <Widget>[title]), actions: _renderIconButtons(actionWidgets, enableAbout));
static List<Widget> _renderIconButtons(List<Widget>? actionWidgets, bool aboutEnabled) {
if (actionWidgets == null) {

View file

@ -1,37 +0,0 @@
import 'package:flutter/material.dart';
import 'package:simple_gesture_detector/simple_gesture_detector.dart';
import '../../core/enums/swipe_event.dart';
import '../../core/services/swipe_service.dart';
import '../../locator.dart';
class SwipeNavigation extends StatefulWidget {
/// Widget to be augmented with gesture detection.
final Widget? child;
/// Creates a [SwipeNavigation] widget.
const SwipeNavigation({
Key? key,
this.child,
}) : super(key: key);
@override
_SwipeNavigationState createState() => _SwipeNavigationState();
}
class _SwipeNavigationState extends State<SwipeNavigation> {
final SwipeService _swipeService = locator<SwipeService>();
void _onHorizontalSwipe(SwipeDirection direction) {
if (direction == SwipeDirection.left) {
_swipeService.addEvent(SwipeEvent.Left);
} else {
_swipeService.addEvent(SwipeEvent.Right);
}
}
@override
Widget build(BuildContext context) {
return SimpleGestureDetector(onHorizontalSwipe: _onHorizontalSwipe, child: widget.child!);
}
}

View file

@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "46.0.0"
version: "50.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "4.6.0"
version: "5.2.0"
args:
dependency: transitive
description:
@ -28,7 +28,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
@ -42,14 +42,14 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.3.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
build_daemon:
dependency: transitive
description:
@ -63,21 +63,21 @@ packages:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
version: "2.1.0"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
version: "2.3.2"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.3"
version: "7.2.7"
built_collection:
dependency: transitive
description:
@ -91,28 +91,21 @@ packages:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.4.0"
version: "8.4.2"
built_value_generator:
dependency: "direct dev"
description:
name: built_value_generator
url: "https://pub.dartlang.org"
source: hosted
version: "8.4.0"
version: "8.4.2"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "1.2.1"
checked_yaml:
dependency: transitive
description:
@ -133,14 +126,14 @@ packages:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.0"
version: "4.3.0"
collection:
dependency: transitive
description:
@ -154,7 +147,14 @@ packages:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
version: "3.1.1"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3+2"
crypto:
dependency: transitive
description:
@ -175,7 +175,14 @@ packages:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
version: "2.2.4"
dynamic_color:
dependency: "direct main"
description:
name: dynamic_color
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.4"
expandable:
dependency: "direct main"
description:
@ -189,7 +196,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.3.1"
ffi:
dependency: transitive
description:
@ -203,14 +210,14 @@ packages:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
version: "6.1.4"
file_picker:
dependency: "direct main"
description:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.1"
version: "5.2.4"
fixnum:
dependency: transitive
description:
@ -265,7 +272,7 @@ packages:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
version: "3.2.0"
get_it:
dependency: "direct main"
description:
@ -279,14 +286,14 @@ packages:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.2.0"
http:
dependency: "direct main"
description:
@ -307,7 +314,7 @@ packages:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.0.2"
intl:
dependency: transitive
description:
@ -335,14 +342,14 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.6.0"
version: "4.7.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.dartlang.org"
source: hosted
version: "6.3.1"
version: "6.5.4"
linkify:
dependency: transitive
description:
@ -363,35 +370,35 @@ packages:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.1.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.0.3"
nested:
dependency: transitive
description:
@ -412,49 +419,42 @@ packages:
name: package_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.3+1"
package_info_plus_linux:
dependency: transitive
description:
name: package_info_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
package_info_plus_macos:
dependency: transitive
description:
name: package_info_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "3.0.2"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
package_info_plus_web:
dependency: transitive
description:
name: package_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
package_info_plus_windows:
dependency: transitive
description:
name: package_info_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.1"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
version: "1.8.2"
path_provider:
dependency: transitive
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.22"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
path_provider_linux:
dependency: transitive
description:
@ -462,55 +462,62 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
version: "2.0.5"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
version: "2.1.3"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
version: "10.0.0"
version: "10.2.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
url: "https://pub.dartlang.org"
source: hosted
version: "10.0.0"
version: "10.2.0"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
url: "https://pub.dartlang.org"
source: hosted
version: "9.0.4"
version: "9.0.7"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.0"
version: "3.9.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
version: "0.1.2"
platform:
dependency: transitive
description:
@ -524,7 +531,7 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
version: "2.1.3"
pool:
dependency: transitive
description:
@ -545,21 +552,21 @@ packages:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.3"
version: "6.0.5"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.3"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
quiver:
dependency: transitive
description:
@ -580,42 +587,14 @@ packages:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.10+1"
share_plus_linux:
dependency: transitive
description:
name: share_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
share_plus_macos:
dependency: transitive
description:
name: share_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "6.3.0"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.3"
share_plus_web:
dependency: transitive
description:
name: share_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
share_plus_windows:
dependency: transitive
description:
name: share_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.2.0"
shared_preferences:
dependency: "direct main"
description:
@ -629,7 +608,7 @@ packages:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.12"
version: "2.0.14"
shared_preferences_ios:
dependency: transitive
description:
@ -643,7 +622,7 @@ packages:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.2"
shared_preferences_macos:
dependency: transitive
description:
@ -657,7 +636,7 @@ packages:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
shared_preferences_web:
dependency: transitive
description:
@ -671,28 +650,21 @@ packages:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.2"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
version: "1.4.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
simple_gesture_detector:
dependency: "direct main"
description:
name: simple_gesture_detector
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
version: "1.0.3"
sky_engine:
dependency: transitive
description: flutter
@ -704,21 +676,21 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.2"
version: "1.2.6"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
version: "1.3.3"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
@ -732,7 +704,7 @@ packages:
name: stacked
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.15"
version: "3.0.1"
stacked_core:
dependency: transitive
description:
@ -753,28 +725,28 @@ packages:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
version: "0.4.12"
timing:
dependency: transitive
description:
@ -802,14 +774,14 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.5"
version: "6.1.7"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.17"
version: "6.0.22"
url_launcher_ios:
dependency: transitive
description:
@ -837,7 +809,7 @@ packages:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
url_launcher_web:
dependency: transitive
description:
@ -852,6 +824,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.7"
validators:
dependency: "direct main"
description:
@ -872,7 +851,7 @@ packages:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.0.2"
web_socket_channel:
dependency: transitive
description:
@ -886,14 +865,14 @@ packages:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.7.0"
version: "3.1.2"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+1"
version: "0.2.0+2"
yaml:
dependency: transitive
description:
@ -902,5 +881,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.17.3 <3.0.0"
flutter: ">=3.0.0"
dart: ">=2.18.6 <3.0.0"
flutter: ">=3.3.0"

View file

@ -11,10 +11,10 @@ description: A mobile client for FileBin.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.4.3+16
version: 1.5.0+16
environment:
sdk: '>=2.17.3 <3.0.0'
sdk: '>=2.18.5 <3.0.0'
dependencies:
flutter:
@ -23,31 +23,31 @@ dependencies:
flutter_localizations:
sdk: flutter
flutter_translate: 4.0.3
provider: 6.0.3
stacked: 2.3.15
provider: 6.0.5
stacked: 3.0.1
get_it: 7.2.0
logger: 1.1.0
shared_preferences: 2.0.15
http: 0.13.5
validators: 3.0.0
flutter_linkify: 5.0.2
url_launcher: 6.1.5
url_launcher: 6.1.7
expandable: 5.0.1
share_plus: 4.0.10+1
file_picker: 5.0.1
share_plus: 6.3.0
file_picker: 5.2.4
clipboard: 0.1.3
receive_sharing_intent: 1.4.5
permission_handler: 10.0.0
package_info_plus: 1.4.3+1
simple_gesture_detector: 0.2.0
json_annotation: 4.6.0
permission_handler: 10.2.0
package_info_plus: 3.0.2
json_annotation: 4.7.0
dynamic_color: 1.5.4
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: 2.2.0
built_value_generator: 8.4.0
json_serializable: 6.3.1
build_runner: 2.3.2
built_value_generator: 8.4.2
json_serializable: 6.5.4
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec