added scrollbars'n'stuff. logout timeout configurable

This commit is contained in:
henne 2022-02-17 11:47:51 +01:00
parent 1a7d96efa5
commit f5bf6cfda0
13 changed files with 214 additions and 161 deletions

View File

@ -1,20 +1,32 @@
PODS:
- Flutter (1.0.0)
- package_info (0.0.1):
- Flutter
- screen_state (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- screen_state (from `.symlinks/plugins/screen_state/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
package_info:
:path: ".symlinks/plugins/package_info/ios"
screen_state:
:path: ".symlinks/plugins/screen_state/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
screen_state: a7ae251997e97f3f001839df09b57313b0ddef18
shared_preferences_ios: aef470a42dc4675a1cdd50e3158b42e3d1232b32
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -68,7 +68,6 @@
05F015517AA39E6E653CAEB9 /* Pods-Runner.release.xcconfig */,
168F2D3694321E0C4AC1CFC0 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
@ -356,13 +355,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = GGPL7UH958;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.snipeScanner;
PRODUCT_BUNDLE_IDENTIFIER = "com.itcreatesmedia.snipe-scanner";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -484,13 +484,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = GGPL7UH958;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.snipeScanner;
PRODUCT_BUNDLE_IDENTIFIER = "com.itcreatesmedia.snipe-scanner";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -506,13 +507,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = GGPL7UH958;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.snipeScanner;
PRODUCT_BUNDLE_IDENTIFIER = "com.itcreatesmedia.snipe-scanner";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -546,4 +548,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
}

View File

@ -31,8 +31,6 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>

View File

@ -4,98 +4,106 @@ import 'package:snipe_scanner/model/asset.dart';
Widget searchItemRow(Asset asset, BuildContext context,
{Function(Asset asset)? cb}) {
Size size = MediaQuery.of(context).size;
return Column(
children: [
Container(
width: size.width,
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (asset.image != null)
Container(
padding: const EdgeInsets.only(left: 10),
height: 50,
width: 50,
child: Image(image: NetworkImage(asset.image!)),
),
SizedBox(
width: asset.image != null ? size.width - 120 : size.width - 70,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(left: 20, bottom: 10),
width: 90,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Tag",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(asset.assetTag!)
],
)),
if (asset.name != null)
Expanded(
child: Container(
padding:
const EdgeInsets.only(left: 10, bottom: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Name",
style: TextStyle(fontWeight: FontWeight.bold),
),
Wrap(
direction: Axis.horizontal,
children: [Text(asset.name!)],
)
],
)),
)
]),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (asset.assignedTo != null)
Container(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Checked out to",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
asset.assignedTo!.name!,
)
],
))
],
)
],
),
),
if (cb != null)
Container(
width: 50,
color: Colors.black12,
child: IconButton(
icon: const Icon(Icons.arrow_right_alt),
tooltip: 'Manual Tag entry',
onPressed: () => cb(asset),
return Card(
child: Column(
children: [
Container(
width: size.width,
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (asset.image != null)
Container(
padding: const EdgeInsets.only(left: 10),
height: 50,
width: 50,
child: Image(image: NetworkImage(asset.image!)),
),
)
],
),
),
const Divider()
],
SizedBox(
width: asset.image != null ? size.width - 120 : size.width - 70,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.only(left: 20, bottom: 10),
width: 90,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Tag",
style:
TextStyle(fontWeight: FontWeight.bold),
),
Text(asset.assetTag!)
],
)),
if (asset.name != null)
Expanded(
child: Container(
padding: const EdgeInsets.only(
left: 10, bottom: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Text(
"Name",
style: TextStyle(
fontWeight: FontWeight.bold),
),
Wrap(
direction: Axis.horizontal,
children: [Text(asset.name!)],
)
],
)),
)
]),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (asset.assignedTo != null)
Container(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Checked out to",
style:
TextStyle(fontWeight: FontWeight.bold),
),
Text(
asset.assignedTo!.name!,
)
],
))
],
)
],
),
),
if (cb != null)
Container(
width: 50,
color: Colors.black12,
child: IconButton(
icon: const Icon(Icons.arrow_right_alt),
tooltip: 'Manual Tag entry',
onPressed: () => cb(asset),
),
)
],
),
)
],
),
);
}

View File

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

View File

@ -19,7 +19,6 @@ import 'package:snipe_scanner/widgets/user_detail.dart';
import 'model/app_state.dart';
const logoutTimeout = Duration(hours: 1);
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
@ -33,6 +32,8 @@ Future main() async {
'use_custom_user_url': false,
'tag_prefix': '',
'use_tag': true,
'auto_logout': false,
'auto_logout_time': 60
});
ZebraScan.init();
runApp(PrefService(
@ -55,18 +56,25 @@ class _MyAppState extends State<MyApp> {
@override
void initState() {
try {
_screen.screenStateStream!.listen((ScreenStateEvent e) => {
if (e == ScreenStateEvent.SCREEN_OFF && logoutTimer == null)
{
logoutTimer = Timer(logoutTimeout, () {
Provider.of<AppState>(context, listen: false).setToken("");
navigatorKey.currentState?.popUntil((route) => route.isFirst);
})
}
else if (e == ScreenStateEvent.SCREEN_UNLOCKED &&
logoutTimer != null)
{logoutTimer!.cancel(), logoutTimer = null, log("unlocked")}
_screen.screenStateStream!.listen((ScreenStateEvent e) {
log((logoutTimer == null).toString());
if (e == ScreenStateEvent.SCREEN_OFF &&
logoutTimer == null &&
PrefService.of(context).get('auto_logout')) {
Duration duration = Duration(
minutes: PrefService.of(context).get('auto_logout_time'));
logoutTimer = Timer(duration, () {
Provider.of<AppState>(context, listen: false).setToken("");
navigatorKey.currentState?.popUntil((route) => route.isFirst);
});
log("Locking in ${duration.toString()} minutes");
} else if (e == ScreenStateEvent.SCREEN_UNLOCKED &&
logoutTimer != null) {
logoutTimer!.cancel();
logoutTimer = null;
log("unlocked");
}
});
} catch (err) {
log(err.toString());
}

View File

@ -155,16 +155,18 @@ class _BulkCheckinState extends State<BulkCheckin> with RouteAware {
),
),
Expanded(
child: ListView.builder(
itemCount: _history.length,
itemBuilder: (BuildContext context, int index) {
var i = _history.length - (index + 1);
return itemRow(_history[i]["barcode"], context,
name: _history[i]["name"],
note: _history[i]["note"],
status: _history[i]["status"],
checkinFrom: _history[i]["checkinFrom"]);
}))
child: Scrollbar(
child: ListView.builder(
itemCount: _history.length,
itemBuilder: (BuildContext context, int index) {
var i = _history.length - (index + 1);
return itemRow(_history[i]["barcode"], context,
name: _history[i]["name"],
note: _history[i]["note"],
status: _history[i]["status"],
checkinFrom: _history[i]["checkinFrom"]);
})),
)
],
),
);

View File

@ -164,15 +164,17 @@ class _BulkCheckoutState extends State<BulkCheckout> with RouteAware {
),
),
Expanded(
child: ListView.builder(
itemCount: _history.length,
itemBuilder: (BuildContext context, int index) {
var i = _history.length - (index + 1);
return itemRow(_history[i]["barcode"], context,
name: _history[i]["name"],
note: _history[i]["note"],
status: _history[i]["status"]);
}))
child: Scrollbar(
child: ListView.builder(
itemCount: _history.length,
itemBuilder: (BuildContext context, int index) {
var i = _history.length - (index + 1);
return itemRow(_history[i]["barcode"], context,
name: _history[i]["name"],
note: _history[i]["note"],
status: _history[i]["status"]);
})),
)
],
),
);

View File

@ -11,7 +11,6 @@ import 'package:snipe_scanner/main.dart';
import 'package:snipe_scanner/model/app_state.dart';
import 'package:snipe_scanner/service/login_user.dart';
import 'package:snipe_scanner/utils/zebra_scan.dart';
import 'package:dropdown_search/dropdown_search.dart';
class DashboardWidget extends StatefulWidget {
const DashboardWidget({Key? key}) : super(key: key);

View File

@ -29,13 +29,15 @@ class ItemHistoryView extends StatelessWidget {
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: history.length,
itemBuilder: (BuildContext context, int index) {
var i = history.length - (index + 1);
return historyRow(history[i], context);
}))
child: Scrollbar(
child: ListView.builder(
shrinkWrap: true,
itemCount: history.length,
itemBuilder: (BuildContext context, int index) {
var i = history.length - (index + 1);
return historyRow(history[i], context);
})),
)
],
);
}

View File

@ -37,6 +37,24 @@ class PreferencesWidgetState extends State<PreferencesWidget> {
),
], pref: 'use_custom_user_url'),
const PrefText(pref: 'tag_prefix', label: 'Tag Prefix'),
PrefCheckbox(
pref: 'auto_logout',
title: const Text("Auto Logout"),
onChange: (value) {
if (!value) {
PrefService.of(context).set('auto_logout_time', 0);
}
},
),
PrefHider(children: [
PrefSlider(
pref: 'auto_logout_time',
title: const Text('Auto logout timeout'),
min: 0,
max: 300,
trailing: (num v) => Text('$v minutes'),
),
], pref: 'auto_logout')
],
));
}

View File

@ -70,15 +70,17 @@ class _SearchAssetState extends State<SearchAsset> {
TextStyle(fontSize: 20, fontWeight: FontWeight.bold))),
if (_assets.isNotEmpty)
Expanded(
child: ListView.builder(
itemCount: _assets.length,
itemBuilder: (BuildContext context, int index) {
var i = _assets.length - (index + 1);
return searchItemRow(_assets[i], context,
cb: (Asset asset) {
Navigator.pop(context, asset.assetTag);
});
}))
child: Scrollbar(
child: ListView.builder(
itemCount: _assets.length,
itemBuilder: (BuildContext context, int index) {
var i = _assets.length - (index + 1);
return searchItemRow(_assets[i], context,
cb: (Asset asset) {
Navigator.pop(context, asset.assetTag);
});
})),
)
],
),
);

View File

@ -26,7 +26,7 @@ class UserGeneralView extends StatelessWidget {
radius: 60, backgroundImage: NetworkImage(user.avatar))),
),
Expanded(
child: SingleChildScrollView(
child: Scrollbar(
child: Column(
children: [
TextRow(title: "Name", text: user.name),
@ -66,16 +66,18 @@ class UserAssetsView extends StatelessWidget {
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: assets.length,
itemBuilder: (BuildContext context, int index) {
var i = assets.length - (index + 1);
return searchItemRow(assets[i], context,
cb: (asset) => Navigator.pushNamed(
context, "/assetDetail",
arguments: asset.assetTag));
}))
child: Scrollbar(
child: ListView.builder(
shrinkWrap: true,
itemCount: assets.length,
itemBuilder: (BuildContext context, int index) {
var i = assets.length - (index + 1);
return searchItemRow(assets[i], context,
cb: (asset) => Navigator.pushNamed(
context, "/assetDetail",
arguments: asset.assetTag));
})),
)
],
);
}