Tablet layout
This commit is contained in:
parent
7179b51260
commit
83a7e840ec
|
|
@ -18,3 +18,4 @@ google-services.json
|
|||
GoogleService-Info.plist
|
||||
ios/Runner/Info.plist
|
||||
android/app/build.gradle
|
||||
android/app/release/
|
||||
|
|
@ -20,6 +20,9 @@ const String kSharedPrefAppVersion = 'app_version';
|
|||
const String kSharedPrefRequireAuthentication = 'require_authentication';
|
||||
const String kSharedPrefAddDocumentsToInvoice = 'add_documents_to_invoice';
|
||||
|
||||
const int kMobileLayoutWidth = 600;
|
||||
const int kTabletLayoutWidth = 1000;
|
||||
|
||||
const String kPlanFree = '';
|
||||
const String kPlanPro = 'pro';
|
||||
const String kPlanEnterprise = 'enterprise';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ part of 'serializers.dart';
|
|||
|
||||
Serializers _$serializers = (new Serializers().toBuilder()
|
||||
..add(ActivityEntity.serializer)
|
||||
..add(AppLayout.serializer)
|
||||
..add(AppState.serializer)
|
||||
..add(AuthState.serializer)
|
||||
..add(ClientEntity.serializer)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:invoiceninja_flutter/.env.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/main_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/view/product_view_vm.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
|
||||
|
|
@ -96,7 +97,8 @@ void main() async {
|
|||
final store = Store<AppState>(appReducer,
|
||||
initialState: AppState(
|
||||
enableDarkMode: enableDarkMode,
|
||||
requireAuthentication: requireAuthentication),
|
||||
requireAuthentication: requireAuthentication,
|
||||
),
|
||||
middleware: []
|
||||
..addAll(createStoreAuthMiddleware())
|
||||
..addAll(createStoreDocumentsMiddleware())
|
||||
|
|
@ -221,7 +223,6 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
|||
final state = widget.store.state;
|
||||
Intl.defaultLocale = localeSelector(state);
|
||||
final localization = AppLocalization(Locale(Intl.defaultLocale));
|
||||
|
||||
return MaterialApp(
|
||||
supportedLocales: kLanguages
|
||||
.map((String locale) => AppLocalization.createLocale(locale))
|
||||
|
|
@ -286,6 +287,9 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
|||
LoginScreen.route: (context) {
|
||||
return LoginScreen();
|
||||
},
|
||||
MainScreen.route: (context) {
|
||||
return MainScreen();
|
||||
},
|
||||
DashboardScreen.route: (context) {
|
||||
if (widget.store.state.dashboardState.isStale) {
|
||||
widget.store.dispatch(LoadDashboard());
|
||||
|
|
@ -348,7 +352,6 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
|||
},
|
||||
ProjectViewScreen.route: (context) => ProjectViewScreen(),
|
||||
ProjectEditScreen.route: (context) => ProjectEditScreen(),
|
||||
|
||||
PaymentScreen.route: (context) {
|
||||
if (widget.store.state.paymentState.isStale) {
|
||||
widget.store.dispatch(LoadPayments());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
||||
|
||||
class PersistUI {}
|
||||
|
||||
|
|
@ -13,6 +15,18 @@ class RefreshClient {
|
|||
final int clientId;
|
||||
}
|
||||
|
||||
|
||||
class UpdateLayout {
|
||||
|
||||
UpdateLayout(this.layout);
|
||||
final AppLayout layout;
|
||||
}
|
||||
|
||||
class ViewMainScreen {
|
||||
ViewMainScreen(this.context);
|
||||
BuildContext context;
|
||||
}
|
||||
|
||||
class StartLoading {}
|
||||
|
||||
class StopLoading {}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/main_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
|
|
@ -110,6 +111,8 @@ List<Middleware<AppState>> createStorePersistenceMiddleware([
|
|||
company4Repository,
|
||||
company5Repository);
|
||||
|
||||
final viewMainScreen = _createViewMainScreen();
|
||||
|
||||
return [
|
||||
TypedMiddleware<AppState, UserLogout>(deleteState),
|
||||
TypedMiddleware<AppState, LoadStateRequest>(loadState),
|
||||
|
|
@ -118,6 +121,7 @@ List<Middleware<AppState>> createStorePersistenceMiddleware([
|
|||
TypedMiddleware<AppState, PersistData>(persistData),
|
||||
TypedMiddleware<AppState, PersistStatic>(persistStatic),
|
||||
TypedMiddleware<AppState, PersistUI>(persistUI),
|
||||
TypedMiddleware<AppState, ViewMainScreen>(viewMainScreen),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +186,7 @@ Middleware<AppState> _createLoadState(
|
|||
if (uiState.currentRoute != LoginScreen.route &&
|
||||
authState.url.isNotEmpty) {
|
||||
final NavigatorState navigator = Navigator.of(action.context);
|
||||
if (uiState.layout == AppLayout.mobile) {
|
||||
bool isFirst = true;
|
||||
_getRoutes(appState).forEach((route) {
|
||||
if (isFirst) {
|
||||
|
|
@ -191,6 +196,11 @@ Middleware<AppState> _createLoadState(
|
|||
}
|
||||
isFirst = false;
|
||||
});
|
||||
} else {
|
||||
store.dispatch(ViewMainScreen(action.context));
|
||||
}
|
||||
} else {
|
||||
throw 'Unknown page';
|
||||
}
|
||||
} catch (error) {
|
||||
print(error);
|
||||
|
|
@ -238,7 +248,8 @@ List<String> _getRoutes(AppState state) {
|
|||
route += '/view';
|
||||
}
|
||||
} else {
|
||||
if (!['dashboard', 'settings'].contains(part) && entityType == null) {
|
||||
if (!['main', 'dashboard', 'settings'].contains(part) &&
|
||||
entityType == null) {
|
||||
entityType = EntityType.valueOf(part);
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +395,15 @@ Middleware<AppState> _createDeleteState(
|
|||
};
|
||||
}
|
||||
|
||||
Middleware<AppState> _createViewMainScreen() {
|
||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
Navigator.of(action.context).pushNamedAndRemoveUntil(
|
||||
MainScreen.route, (Route<dynamic> route) => false);
|
||||
|
||||
next(action);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Future<bool> _checkLastLoadWasSuccesfull() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
|
|
|
|||
|
|
@ -25,8 +25,12 @@ import 'package:invoiceninja_flutter/redux/quote/quote_state.dart';
|
|||
part 'app_state.g.dart';
|
||||
|
||||
abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||
factory AppState(
|
||||
{String appVersion, bool enableDarkMode, bool requireAuthentication}) {
|
||||
factory AppState({
|
||||
String appVersion,
|
||||
bool enableDarkMode,
|
||||
bool requireAuthentication,
|
||||
AppLayout layout,
|
||||
}) {
|
||||
return _$AppState._(
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
|
|
@ -38,9 +42,12 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
|||
companyState3: CompanyState(),
|
||||
companyState4: CompanyState(),
|
||||
companyState5: CompanyState(),
|
||||
uiState: UIState(CompanyEntity(),
|
||||
uiState: UIState(
|
||||
CompanyEntity(),
|
||||
enableDarkMode: enableDarkMode,
|
||||
requireAuthentication: requireAuthentication),
|
||||
requireAuthentication: requireAuthentication,
|
||||
layout: layout ?? AppLayout.mobile,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +163,9 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
|||
|
||||
// STARTER: state getters - do not remove comment
|
||||
DocumentState get documentState => selectedCompanyState.documentState;
|
||||
|
||||
ListUIState get documentListState => uiState.documentUIState.listUIState;
|
||||
|
||||
DocumentUIState get documentUIState => uiState.documentUIState;
|
||||
|
||||
ExpenseState get expenseState => selectedCompanyState.expenseState;
|
||||
|
|
@ -219,6 +228,6 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
|||
String toString() {
|
||||
//return 'Is Loading: ${this.isLoading}, Invoice: ${this.invoiceUIState.selected}';
|
||||
//return 'Expense Categories: ${selectedCompany.expenseCategories}';
|
||||
return 'Route: ${uiState.currentRoute}: Server Version: $serverVersion';
|
||||
return 'Layout: ${uiState.layout}, Route: ${uiState.currentRoute}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|||
import 'package:invoiceninja_flutter/ui/client/client_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/view/client_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
|
|
@ -45,12 +46,14 @@ Middleware<AppState> _editClient() {
|
|||
store.dispatch(UpdateCurrentRoute(ClientEditScreen.route));
|
||||
}
|
||||
|
||||
if (action.context != null && isMobile(action.context)) {
|
||||
final client =
|
||||
await Navigator.of(action.context).pushNamed(ClientEditScreen.route);
|
||||
|
||||
if (action.completer != null && client != null) {
|
||||
action.completer.complete(client);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/dashboard/dashboard_screen.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
|
|
@ -24,7 +25,7 @@ Middleware<AppState> _createViewDashboard() {
|
|||
store.dispatch(LoadDashboard());
|
||||
store.dispatch(UpdateCurrentRoute(DashboardScreen.route));
|
||||
|
||||
if (action.context != null) {
|
||||
if (action.context != null && isMobile(action.context)) {
|
||||
Navigator.of(action.context).pushNamedAndRemoveUntil(
|
||||
DashboardScreen.route, (Route<dynamic> route) => false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
|||
import 'package:invoiceninja_flutter/ui/product/edit/product_edit_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/view/product_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
|
|
@ -48,7 +49,10 @@ Middleware<AppState> _viewProduct() {
|
|||
next(action);
|
||||
|
||||
store.dispatch(UpdateCurrentRoute(ProductViewScreen.route));
|
||||
|
||||
if (action.context != null && isMobile(action.context)) {
|
||||
Navigator.of(action.context).pushNamed(ProductViewScreen.route);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ UIState uiReducer(UIState state, dynamic action) {
|
|||
..filter = filterReducer(state.filter, action)
|
||||
..selectedCompanyIndex =
|
||||
selectedCompanyIndexReducer(state.selectedCompanyIndex, action)
|
||||
..layout = layoutReducer(state.layout, action)
|
||||
..currentRoute = currentRouteReducer(state.currentRoute, action)
|
||||
..enableDarkMode = darkModeReducer(state.enableDarkMode, action)
|
||||
..autoStartTasks = autoStartTasksReducer(state.autoStartTasks, action)
|
||||
|
|
@ -59,6 +60,14 @@ String updateFilter(String filter, FilterCompany action) {
|
|||
return action.filter;
|
||||
}
|
||||
|
||||
Reducer<AppLayout> layoutReducer = combineReducers([
|
||||
TypedReducer<AppLayout, UpdateLayout>(updateLayout),
|
||||
]);
|
||||
|
||||
AppLayout updateLayout(AppLayout layout, UpdateLayout action) {
|
||||
return action.layout;
|
||||
}
|
||||
|
||||
Reducer<bool> emailPaymentReducer = combineReducers([
|
||||
TypedReducer<bool, UserSettingsChanged>(updateEmailPaymentReducer),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/company_model.dart';
|
||||
|
|
@ -26,9 +27,10 @@ part 'ui_state.g.dart';
|
|||
|
||||
abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||
factory UIState(CompanyEntity company,
|
||||
{bool enableDarkMode, bool requireAuthentication}) {
|
||||
{bool enableDarkMode, bool requireAuthentication, AppLayout layout}) {
|
||||
return _$UIState._(
|
||||
selectedCompanyIndex: 0,
|
||||
layout: layout ?? AppLayout.mobile,
|
||||
currentRoute: LoginScreen.route,
|
||||
enableDarkMode: enableDarkMode ?? false,
|
||||
requireAuthentication: requireAuthentication ?? false,
|
||||
|
|
@ -41,7 +43,6 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
invoiceUIState: InvoiceUIState(),
|
||||
// STARTER: constructor - do not remove comment
|
||||
documentUIState: DocumentUIState(),
|
||||
|
||||
expenseUIState: ExpenseUIState(),
|
||||
vendorUIState: VendorUIState(),
|
||||
taskUIState: TaskUIState(),
|
||||
|
|
@ -53,6 +54,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
|
||||
UIState._();
|
||||
|
||||
AppLayout get layout;
|
||||
|
||||
int get selectedCompanyIndex;
|
||||
|
||||
String get currentRoute;
|
||||
|
|
@ -97,3 +100,17 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
|
||||
bool containsRoute(String route) => currentRoute.contains(route);
|
||||
}
|
||||
|
||||
class AppLayout extends EnumClass {
|
||||
const AppLayout._(String name) : super(name);
|
||||
|
||||
static Serializer<AppLayout> get serializer => _$appLayoutSerializer;
|
||||
|
||||
static const AppLayout mobile = _$mobile;
|
||||
static const AppLayout tablet = _$tablet;
|
||||
static const AppLayout desktop = _$desktop;
|
||||
|
||||
static BuiltSet<AppLayout> get values => _$values;
|
||||
|
||||
static AppLayout valueOf(String name) => _$valueOf(name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,31 @@ part of 'ui_state.dart';
|
|||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
const AppLayout _$mobile = const AppLayout._('mobile');
|
||||
const AppLayout _$tablet = const AppLayout._('tablet');
|
||||
const AppLayout _$desktop = const AppLayout._('desktop');
|
||||
|
||||
AppLayout _$valueOf(String name) {
|
||||
switch (name) {
|
||||
case 'mobile':
|
||||
return _$mobile;
|
||||
case 'tablet':
|
||||
return _$tablet;
|
||||
case 'desktop':
|
||||
return _$desktop;
|
||||
default:
|
||||
throw new ArgumentError(name);
|
||||
}
|
||||
}
|
||||
|
||||
final BuiltSet<AppLayout> _$values = new BuiltSet<AppLayout>(const <AppLayout>[
|
||||
_$mobile,
|
||||
_$tablet,
|
||||
_$desktop,
|
||||
]);
|
||||
|
||||
Serializer<UIState> _$uIStateSerializer = new _$UIStateSerializer();
|
||||
Serializer<AppLayout> _$appLayoutSerializer = new _$AppLayoutSerializer();
|
||||
|
||||
class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
||||
@override
|
||||
|
|
@ -18,6 +42,9 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
|||
Iterable<Object> serialize(Serializers serializers, UIState object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object>[
|
||||
'layout',
|
||||
serializers.serialize(object.layout,
|
||||
specifiedType: const FullType(AppLayout)),
|
||||
'selectedCompanyIndex',
|
||||
serializers.serialize(object.selectedCompanyIndex,
|
||||
specifiedType: const FullType(int)),
|
||||
|
|
@ -93,6 +120,10 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
|||
iterator.moveNext();
|
||||
final dynamic value = iterator.current;
|
||||
switch (key) {
|
||||
case 'layout':
|
||||
result.layout = serializers.deserialize(value,
|
||||
specifiedType: const FullType(AppLayout)) as AppLayout;
|
||||
break;
|
||||
case 'selectedCompanyIndex':
|
||||
result.selectedCompanyIndex = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
|
|
@ -178,7 +209,26 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
|||
}
|
||||
}
|
||||
|
||||
class _$AppLayoutSerializer implements PrimitiveSerializer<AppLayout> {
|
||||
@override
|
||||
final Iterable<Type> types = const <Type>[AppLayout];
|
||||
@override
|
||||
final String wireName = 'AppLayout';
|
||||
|
||||
@override
|
||||
Object serialize(Serializers serializers, AppLayout object,
|
||||
{FullType specifiedType = FullType.unspecified}) =>
|
||||
object.name;
|
||||
|
||||
@override
|
||||
AppLayout deserialize(Serializers serializers, Object serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) =>
|
||||
AppLayout.valueOf(serialized as String);
|
||||
}
|
||||
|
||||
class _$UIState extends UIState {
|
||||
@override
|
||||
final AppLayout layout;
|
||||
@override
|
||||
final int selectedCompanyIndex;
|
||||
@override
|
||||
|
|
@ -222,7 +272,8 @@ class _$UIState extends UIState {
|
|||
(new UIStateBuilder()..update(updates)).build();
|
||||
|
||||
_$UIState._(
|
||||
{this.selectedCompanyIndex,
|
||||
{this.layout,
|
||||
this.selectedCompanyIndex,
|
||||
this.currentRoute,
|
||||
this.enableDarkMode,
|
||||
this.requireAuthentication,
|
||||
|
|
@ -242,6 +293,9 @@ class _$UIState extends UIState {
|
|||
this.paymentUIState,
|
||||
this.quoteUIState})
|
||||
: super._() {
|
||||
if (layout == null) {
|
||||
throw new BuiltValueNullFieldError('UIState', 'layout');
|
||||
}
|
||||
if (selectedCompanyIndex == null) {
|
||||
throw new BuiltValueNullFieldError('UIState', 'selectedCompanyIndex');
|
||||
}
|
||||
|
|
@ -309,6 +363,7 @@ class _$UIState extends UIState {
|
|||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is UIState &&
|
||||
layout == other.layout &&
|
||||
selectedCompanyIndex == other.selectedCompanyIndex &&
|
||||
currentRoute == other.currentRoute &&
|
||||
enableDarkMode == other.enableDarkMode &&
|
||||
|
|
@ -349,9 +404,12 @@ class _$UIState extends UIState {
|
|||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
0,
|
||||
layout
|
||||
.hashCode),
|
||||
selectedCompanyIndex
|
||||
.hashCode),
|
||||
currentRoute
|
||||
|
|
@ -383,6 +441,7 @@ class _$UIState extends UIState {
|
|||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('UIState')
|
||||
..add('layout', layout)
|
||||
..add('selectedCompanyIndex', selectedCompanyIndex)
|
||||
..add('currentRoute', currentRoute)
|
||||
..add('enableDarkMode', enableDarkMode)
|
||||
|
|
@ -409,6 +468,10 @@ class _$UIState extends UIState {
|
|||
class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||
_$UIState _$v;
|
||||
|
||||
AppLayout _layout;
|
||||
AppLayout get layout => _$this._layout;
|
||||
set layout(AppLayout layout) => _$this._layout = layout;
|
||||
|
||||
int _selectedCompanyIndex;
|
||||
int get selectedCompanyIndex => _$this._selectedCompanyIndex;
|
||||
set selectedCompanyIndex(int selectedCompanyIndex) =>
|
||||
|
|
@ -516,6 +579,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
|||
|
||||
UIStateBuilder get _$this {
|
||||
if (_$v != null) {
|
||||
_layout = _$v.layout;
|
||||
_selectedCompanyIndex = _$v.selectedCompanyIndex;
|
||||
_currentRoute = _$v.currentRoute;
|
||||
_enableDarkMode = _$v.enableDarkMode;
|
||||
|
|
@ -559,6 +623,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
|||
try {
|
||||
_$result = _$v ??
|
||||
new _$UIState._(
|
||||
layout: layout,
|
||||
selectedCompanyIndex: selectedCompanyIndex,
|
||||
currentRoute: currentRoute,
|
||||
enableDarkMode: enableDarkMode,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/app_drawer_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
||||
|
||||
class MainScreen extends StatelessWidget {
|
||||
static const String route = '/main';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
AppDrawerBuilder(),
|
||||
//Expanded(child: DashboardScreen()),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: InvoiceScreen(),
|
||||
),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: InvoiceEditScreen(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
|
|
@ -63,8 +64,14 @@ class LoginVM {
|
|||
);
|
||||
|
||||
void _handleLogin(BuildContext context) {
|
||||
store.dispatch(UpdateLayout(calculateLayout(context)));
|
||||
AppBuilder.of(context).rebuild();
|
||||
|
||||
if (isMobile(context)) {
|
||||
store.dispatch(ViewDashboard(context));
|
||||
} else {
|
||||
store.dispatch(ViewMainScreen(context));
|
||||
}
|
||||
}
|
||||
|
||||
return LoginVM(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
||||
|
||||
bool isAndroid(BuildContext context) =>
|
||||
Theme.of(context).platform == TargetPlatform.android;
|
||||
|
|
@ -17,3 +20,24 @@ String getPlatform(BuildContext context) =>
|
|||
|
||||
String getAppURL(BuildContext context) =>
|
||||
isAndroid(context) ? kGoogleStoreUrl : kAppleStoreUrl;
|
||||
|
||||
AppLayout calculateLayout(BuildContext context) {
|
||||
final size = MediaQuery.of(context).size.shortestSide;
|
||||
if (size < kMobileLayoutWidth) {
|
||||
return AppLayout.mobile;
|
||||
} else if (size > kTabletLayoutWidth) {
|
||||
return AppLayout.desktop;
|
||||
} else {
|
||||
return AppLayout.tablet;
|
||||
}
|
||||
}
|
||||
|
||||
AppLayout getLayout(BuildContext context) =>
|
||||
StoreProvider.of<AppState>(context).state.uiState.layout ??
|
||||
AppLayout.mobile;
|
||||
|
||||
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;
|
||||
|
||||
bool isTablet(BuildContext context) => getLayout(context) == AppLayout.tablet;
|
||||
|
||||
bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop;
|
||||
|
|
|
|||
Loading…
Reference in New Issue