add structure
This commit is contained in:
227
lib/pages/manual/instruction_data_page.dart
Normal file
227
lib/pages/manual/instruction_data_page.dart
Normal file
@@ -0,0 +1,227 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/language_model.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/pages/manual/moveable_stack_item.dart';
|
||||
import 'package:fcs/theme/theme.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
class InstructionDataPage extends StatefulWidget {
|
||||
final SlideData slideData;
|
||||
final String path;
|
||||
final int slideIndex;
|
||||
final int manIndex;
|
||||
|
||||
InstructionDataPage(
|
||||
{this.slideData, this.path, this.slideIndex, this.manIndex});
|
||||
@override
|
||||
_InstructionDataPageState createState() => _InstructionDataPageState();
|
||||
}
|
||||
|
||||
class _InstructionDataPageState extends State<InstructionDataPage> {
|
||||
String selectedLanguage;
|
||||
File slideImageFile;
|
||||
bool isEng;
|
||||
List<bool> _selection = List.generate(2, (_) => false);
|
||||
String imgName;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isEng = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var manualModel = Provider.of<ManualModel>(context);
|
||||
if (isEng) {
|
||||
imgName = widget.slideData.image;
|
||||
} else {
|
||||
imgName = widget.slideData.imagemm;
|
||||
}
|
||||
|
||||
var screenSize = MediaQuery.of(context).size;
|
||||
var width = screenSize.width;
|
||||
var imgWidth = width - (width * 0.15);
|
||||
var height = screenSize.height;
|
||||
var imgHeight = height - (height * 0.29);
|
||||
|
||||
var toggleButtons = Container(
|
||||
child: ToggleButtons(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
"assets/eng_flag.png",
|
||||
width: 25,
|
||||
),
|
||||
Text(
|
||||
"English",
|
||||
style:
|
||||
TextStyle(color: this.isEng ? secondaryColor : Colors.black),
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
"assets/myan_flag.png",
|
||||
width: 25,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: Text(
|
||||
"မြန်မာ",
|
||||
style: TextStyle(
|
||||
color: !this.isEng ? secondaryColor : Colors.black,
|
||||
fontFamily: "MyanmarUnicode"),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
renderBorder: false,
|
||||
isSelected: _selection,
|
||||
selectedColor: secondaryColor,
|
||||
onPressed: (int index) {
|
||||
setState(() {
|
||||
_selection[index] = !_selection[index];
|
||||
if (index == 0) {
|
||||
this.isEng = true;
|
||||
} else {
|
||||
this.isEng = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
));
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Instruction Data'),
|
||||
actions: <Widget>[toggleButtons],
|
||||
),
|
||||
body: Container(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Stack(
|
||||
children: instructionData(
|
||||
context, imgWidth, imgHeight, manualModel),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.image),
|
||||
onPressed: () {
|
||||
pickImageFromGallery(ImageSource.gallery, manualModel);
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
addInstructionData();
|
||||
},
|
||||
tooltip: 'Pick Image',
|
||||
child: Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
addInstructionData() {
|
||||
var instructionList =
|
||||
isEng ? widget.slideData.instructions : widget.slideData.instructionsmm;
|
||||
Instruction inst;
|
||||
if (instructionList.toList().length == 0) {
|
||||
inst = Instruction(
|
||||
id: 1,
|
||||
text: '',
|
||||
left: 0.0,
|
||||
top: 0.0,
|
||||
);
|
||||
} else {
|
||||
dynamic max = instructionList.first;
|
||||
instructionList.forEach((e) {
|
||||
if (e.id > max.id) max = e;
|
||||
});
|
||||
inst = Instruction(
|
||||
id: max.id + 1,
|
||||
text: '',
|
||||
left: 0.0,
|
||||
top: 0.0,
|
||||
);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
if (isEng) {
|
||||
widget.slideData.instructions.add(inst);
|
||||
} else {
|
||||
widget.slideData.instructionsmm.add(inst);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
instructionData(
|
||||
BuildContext context, double imgW, double imgH, ManualModel manualModel) {
|
||||
List<Widget> textFields = [];
|
||||
textFields.add(
|
||||
Image.file(
|
||||
File('${widget.path}/manual/img/' + imgName),
|
||||
alignment: AlignmentDirectional.topCenter,
|
||||
height: imgH,
|
||||
width: imgW,
|
||||
),
|
||||
);
|
||||
var instructionList =
|
||||
isEng ? widget.slideData.instructions : widget.slideData.instructionsmm;
|
||||
if (instructionList.length != 0) {
|
||||
instructionList.asMap().forEach((k, instruction) {
|
||||
MoveableStackItem mitem = MoveableStackItem(
|
||||
instruction: instruction,
|
||||
manIndex: widget.manIndex,
|
||||
slideIndex: widget.slideIndex,
|
||||
instIndex: k,
|
||||
isEng: this.isEng,
|
||||
key: Key(this.isEng.toString() + k.toString()),
|
||||
);
|
||||
|
||||
textFields.add(mitem);
|
||||
});
|
||||
}
|
||||
return textFields;
|
||||
}
|
||||
|
||||
pickImageFromGallery(ImageSource source, ManualModel manualModel) async {
|
||||
File tempImage = await ImagePicker.pickImage(
|
||||
source: source, imageQuality: 80, maxWidth: 300);
|
||||
|
||||
var fileName = Path.basename(tempImage.path);
|
||||
var path = '${manualModel.dataDir}';
|
||||
File newImage = await tempImage.copy('$path/manual/img/$fileName');
|
||||
var slideData = widget.slideData;
|
||||
if (this.isEng) {
|
||||
slideData.image = fileName;
|
||||
} else {
|
||||
slideData.imagemm = fileName;
|
||||
}
|
||||
|
||||
manualModel.changeSlideImage(widget.manIndex, widget.slideIndex, slideData);
|
||||
}
|
||||
}
|
||||
78
lib/pages/manual/manual_item_title_dialog.dart
Normal file
78
lib/pages/manual/manual_item_title_dialog.dart
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
|
||||
class ManualItemTitleDialog extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _ManualItemTitleDialogState();
|
||||
}
|
||||
}
|
||||
|
||||
class _ManualItemTitleDialogState extends State<ManualItemTitleDialog> {
|
||||
TextEditingController _engTextFieldController = TextEditingController();
|
||||
TextEditingController _mmTextFieldController = TextEditingController();
|
||||
ManualItem item;
|
||||
bool buyer = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: new Text('Enter Title'),
|
||||
content: Container(
|
||||
height: 200,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
controller: _engTextFieldController,
|
||||
decoration: InputDecoration(hintText: "Enter English"),
|
||||
maxLines: null,
|
||||
style: TextStyle(fontSize: 13.0),
|
||||
),
|
||||
TextField(
|
||||
controller: _mmTextFieldController,
|
||||
decoration: InputDecoration(hintText: "Enter Myanmar"),
|
||||
maxLines: null,
|
||||
style: TextStyle(fontSize: 13.0),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text("For Buyer"),
|
||||
value: buyer,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
buyer = val;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
onPressed: () {
|
||||
_save();
|
||||
},
|
||||
child: new Text('Save'))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_save() {
|
||||
try {
|
||||
String eng = _engTextFieldController.text;
|
||||
String mm = _mmTextFieldController.text;
|
||||
|
||||
ManualItem item =
|
||||
ManualItem(title: eng, titlemm: mm, isBuyer: buyer, slides: []);
|
||||
|
||||
Navigator.pop<ManualItem>(context, item);
|
||||
} catch (e) {
|
||||
// showMsgDialog(context, "Error", e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
234
lib/pages/manual/manual_page.dart
Normal file
234
lib/pages/manual/manual_page.dart
Normal file
@@ -0,0 +1,234 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/language_model.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/pages/manual/manual_item_title_dialog.dart';
|
||||
import 'package:fcs/pages/util.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
import 'package:fcs/widget/local_text.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
import 'slide_page.dart';
|
||||
|
||||
class ManualPage extends StatefulWidget {
|
||||
@override
|
||||
_ManualPageState createState() => _ManualPageState();
|
||||
}
|
||||
|
||||
class _ManualPageState extends State<ManualPage> {
|
||||
TextEditingController _manualVersionController = TextEditingController();
|
||||
final double dotSize = 10.0;
|
||||
List<ManualItem> helpList = new List();
|
||||
bool isEng;
|
||||
String versionName;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
helpList.clear();
|
||||
var manualModel = Provider.of<ManualModel>(context, listen: false);
|
||||
var mainModel = Provider.of<MainModel>(context, listen: false);
|
||||
versionName = manualModel.version;
|
||||
helpList = manualModel.getHelpList(mainModel.isBuyer());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var manualModel = Provider.of<ManualModel>(context);
|
||||
var mainModel = Provider.of<MainModel>(context);
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
isEng = languageModel.isEng;
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
actions: <Widget>[
|
||||
mainModel.isSysAdmin()
|
||||
? Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
versionName,
|
||||
style: TextStyle(fontSize: 15, color: Colors.black),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.refresh),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
manualModel.resetManualItems();
|
||||
helpList =
|
||||
manualModel.getHelpList(mainModel.isBuyer());
|
||||
});
|
||||
}),
|
||||
IconButton(
|
||||
icon: Icon(Icons.cloud_upload),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
_inputManualVersion(context, manualModel);
|
||||
})
|
||||
],
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
iconTheme: IconThemeData(
|
||||
color: Colors.grey,
|
||||
),
|
||||
centerTitle: true,
|
||||
title: Stack(
|
||||
children: <Widget>[
|
||||
LocalText(
|
||||
context,
|
||||
"manual.title",
|
||||
fontSize: 25,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
new Expanded(
|
||||
child: new ListView.builder(
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
|
||||
shrinkWrap: true,
|
||||
itemCount: helpList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Card(
|
||||
elevation: 10,
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SlidePage(
|
||||
helpDetail: helpList[index],
|
||||
index: index,
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Row(children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 5.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 15.0 - dotSize / 2),
|
||||
child: Container(
|
||||
child: Image.asset(
|
||||
"assets/page.png",
|
||||
width: 50,
|
||||
height: 50,
|
||||
)),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
isEng
|
||||
? helpList[index].title
|
||||
: helpList[index].titlemm,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Colors.grey),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
mainModel.isSysAdmin()
|
||||
? Container(
|
||||
padding: EdgeInsets.only(right: 20),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
showConfirmDialog(
|
||||
context, "manual.confirm", () {
|
||||
setState(() {
|
||||
manualModel.deleteManualItem(
|
||||
helpList[index]);
|
||||
helpList = manualModel.getHelpList(
|
||||
mainModel.isBuyer());
|
||||
});
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.delete),
|
||||
))
|
||||
: Container()
|
||||
])),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: mainModel.isSysAdmin()
|
||||
? FloatingActionButton(
|
||||
onPressed: () async {
|
||||
ManualItem newItem = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ManualItemTitleDialog());
|
||||
if (helpList.toList().length == 0) {
|
||||
newItem.id = 1;
|
||||
} else {
|
||||
dynamic max = helpList.first;
|
||||
helpList.forEach((e) {
|
||||
if (e.id > max.id) max = e;
|
||||
});
|
||||
newItem.id = max.id + 1;
|
||||
}
|
||||
setState(() {
|
||||
helpList.add(newItem);
|
||||
});
|
||||
manualModel.addManualTitle(newItem);
|
||||
},
|
||||
child: Icon(Icons.add),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_deleteManualItem(ManualItem item, ManualModel manualModel) {
|
||||
return showConfirmDialog(context, "manual.confirm", () {
|
||||
setState(() {
|
||||
manualModel.deleteManualItem(item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_inputManualVersion(BuildContext context, ManualModel manModel) async {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: new Text('Version'),
|
||||
content: TextField(
|
||||
controller: _manualVersionController,
|
||||
decoration: InputDecoration(hintText: "Enter manual version"),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
onPressed: () {
|
||||
String version = _manualVersionController.text;
|
||||
String dir = manModel.dataDir;
|
||||
manModel.uploadStorageManualData(version, dir);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: new Text('Save'))
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
123
lib/pages/manual/moveable_stack_item.dart
Normal file
123
lib/pages/manual/moveable_stack_item.dart
Normal file
@@ -0,0 +1,123 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
|
||||
class MoveableStackItem extends StatefulWidget {
|
||||
Instruction instruction;
|
||||
final int instIndex;
|
||||
final int slideIndex;
|
||||
final int manIndex;
|
||||
final bool isEng;
|
||||
|
||||
MoveableStackItem(
|
||||
{this.instIndex,
|
||||
this.slideIndex,
|
||||
this.manIndex,
|
||||
this.instruction,
|
||||
this.isEng,
|
||||
Key key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _MoveableStackItemState();
|
||||
}
|
||||
}
|
||||
|
||||
class _MoveableStackItemState extends State<MoveableStackItem> {
|
||||
TextEditingController _textFieldController = TextEditingController();
|
||||
double xPosition = 0;
|
||||
double yPosition = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_textFieldController.text = widget.instruction.text;
|
||||
yPosition =
|
||||
widget.instruction.top != null ? widget.instruction.top : yPosition;
|
||||
xPosition =
|
||||
widget.instruction.left != null ? widget.instruction.left : xPosition;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var manualModel = Provider.of<ManualModel>(context);
|
||||
return Positioned(
|
||||
top: yPosition,
|
||||
left: xPosition,
|
||||
child: GestureDetector(
|
||||
onPanUpdate: (tapInfo) {
|
||||
setState(() {
|
||||
xPosition += tapInfo.delta.dx;
|
||||
yPosition += tapInfo.delta.dy;
|
||||
});
|
||||
var data = Instruction(
|
||||
id: widget.instruction.id,
|
||||
top: yPosition,
|
||||
left: xPosition,
|
||||
text: _textFieldController.text,
|
||||
);
|
||||
manualModel.saveInstruction(widget.manIndex, widget.slideIndex,
|
||||
widget.instIndex, data, widget.instruction, widget.isEng);
|
||||
},
|
||||
child: Container(
|
||||
width: 250,
|
||||
color: Colors.grey,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_displayDialog(context, manualModel);
|
||||
},
|
||||
child: Container(
|
||||
child: Text(
|
||||
_textFieldController.text,
|
||||
maxLines: null,
|
||||
style:
|
||||
TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700),
|
||||
))))),
|
||||
);
|
||||
}
|
||||
|
||||
_displayDialog(BuildContext context, ManualModel manualModel) async {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: new Text('Instruction'),
|
||||
content: Container(
|
||||
height: 100,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
controller: _textFieldController,
|
||||
decoration: InputDecoration(hintText: "Enter Instruction"),
|
||||
maxLines: null,
|
||||
style: TextStyle(fontSize: 13.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
onPressed: () {
|
||||
var data = Instruction(
|
||||
id: widget.instruction.id,
|
||||
top: yPosition,
|
||||
left: xPosition,
|
||||
text: _textFieldController.text,
|
||||
);
|
||||
manualModel.saveInstruction(
|
||||
widget.manIndex,
|
||||
widget.slideIndex,
|
||||
widget.instIndex,
|
||||
data,
|
||||
widget.instruction,
|
||||
widget.isEng);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: new Text('Save'))
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
210
lib/pages/manual/slide_data_page.dart
Normal file
210
lib/pages/manual/slide_data_page.dart
Normal file
@@ -0,0 +1,210 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/pages/manual/instruction_data_page.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
import 'package:fcs/widget/img_file.dart';
|
||||
import 'package:fcs/widget/local_text.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
class SlideDataPage extends StatefulWidget {
|
||||
final ManualItem manItem;
|
||||
final int manIndex;
|
||||
|
||||
SlideDataPage({this.manItem, this.manIndex});
|
||||
@override
|
||||
_SlideDataPageState createState() => _SlideDataPageState();
|
||||
}
|
||||
|
||||
class _SlideDataPageState extends State<SlideDataPage> {
|
||||
File slideImageFile;
|
||||
List<SlideData> slideList = [];
|
||||
List<SlideData> _initSlideList = [];
|
||||
File imageFile;
|
||||
File engImgFile;
|
||||
File mmImgFile;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
pickImageFromGallery(ImageSource source, ManualModel manualModel) async {
|
||||
File tempImage = await ImagePicker.pickImage(
|
||||
source: source, imageQuality: 80, maxWidth: 300);
|
||||
|
||||
var fileName = Path.basename(tempImage.path);
|
||||
var path = '${manualModel.dataDir}';
|
||||
File newImage = await tempImage.copy('$path/manual/img/$fileName');
|
||||
var slideData =
|
||||
SlideData(id: slideList.length, image: fileName, instructions: []);
|
||||
setState(() {
|
||||
slideList.add(slideData);
|
||||
});
|
||||
// manualModel.saveSlideData(widget.manIndex, slideList.length, slideData);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var manualModel = Provider.of<ManualModel>(context);
|
||||
slideList = manualModel.getSlideList(widget.manIndex);
|
||||
|
||||
final engImgBox = Container(
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: Column(children: <Widget>[
|
||||
Text('English image'),
|
||||
ImageFile(
|
||||
imageSource: ImageSource.gallery,
|
||||
enabled: true,
|
||||
title: "Image",
|
||||
onFile: (file) {
|
||||
engImgFile = file;
|
||||
})
|
||||
]));
|
||||
|
||||
final mmImgBox = Container(
|
||||
padding: EdgeInsets.only(left: 20, top: 20),
|
||||
child: Column(children: <Widget>[
|
||||
Text('Myanmar image'),
|
||||
ImageFile(
|
||||
imageSource: ImageSource.gallery,
|
||||
enabled: true,
|
||||
title: "Image",
|
||||
onFile: (file) {
|
||||
mmImgFile = file;
|
||||
}),
|
||||
]));
|
||||
|
||||
final saveImages = Container(
|
||||
padding: EdgeInsets.only(left: 20, top: 20),
|
||||
child: FlatButton(
|
||||
onPressed: () {
|
||||
saveSlideImages(context, manualModel, widget.manIndex);
|
||||
},
|
||||
child: Text('Save')));
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Slide Data'),
|
||||
),
|
||||
body: Container(
|
||||
child: GridView.builder(
|
||||
itemCount: slideList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Card(
|
||||
child: InkWell(
|
||||
onTap: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => InstructionDataPage(
|
||||
slideData: slideList[index],
|
||||
path: manualModel.dataDir,
|
||||
slideIndex: index,
|
||||
manIndex: widget.manIndex,
|
||||
)))
|
||||
},
|
||||
child: Container(
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: <Widget>[
|
||||
Image.file(File('${manualModel.dataDir}/manual/img/' +
|
||||
slideList[index].image)),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.delete),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
manualModel.deleteSlideData(
|
||||
widget.manIndex, slideList[index]);
|
||||
});
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () async => await _dialog(
|
||||
context, manualModel, engImgBox, mmImgBox, saveImages),
|
||||
tooltip: 'Pick Image',
|
||||
child: Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _dialog(BuildContext context, ManualModel manualModel,
|
||||
Widget engImg, Widget mmImg, Widget saveImgs) {
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
content: Container(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[engImg, mmImg, saveImgs],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
saveSlideImages(
|
||||
BuildContext context, ManualModel manualModel, int manIndex) async {
|
||||
var engFileName = Path.basename(engImgFile.path);
|
||||
var mmFileName = Path.basename(mmImgFile.path);
|
||||
var path = '${manualModel.dataDir}';
|
||||
File engImage = await engImgFile.copy('$path/manual/img/$engFileName');
|
||||
File mmImage = await mmImgFile.copy('$path/manual/img/$mmFileName');
|
||||
var length = slideList.toList().length;
|
||||
|
||||
var slideData;
|
||||
if (length == 0) {
|
||||
slideData = SlideData(
|
||||
id: 1,
|
||||
image: engFileName,
|
||||
imagemm: mmFileName,
|
||||
instructions: [],
|
||||
instructionsmm: []);
|
||||
} else {
|
||||
dynamic max = slideList.first;
|
||||
slideList.forEach((e) {
|
||||
if (e.id > max.id) max = e;
|
||||
});
|
||||
slideData = SlideData(
|
||||
id: max.id + 1,
|
||||
image: engFileName,
|
||||
imagemm: mmFileName,
|
||||
instructions: [],
|
||||
instructionsmm: []);
|
||||
}
|
||||
manualModel.saveSlideData(manIndex, length, slideData);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
249
lib/pages/manual/slide_page.dart
Normal file
249
lib/pages/manual/slide_page.dart
Normal file
@@ -0,0 +1,249 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:introduction_screen/introduction_screen.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/language_model.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
import 'package:fcs/model/manual_model.dart';
|
||||
import 'package:fcs/pages/manual/slide_data_page.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
import 'package:fcs/widget/local_text.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
class SlidePage extends StatefulWidget {
|
||||
final ManualItem helpDetail;
|
||||
final int index;
|
||||
|
||||
SlidePage({this.helpDetail, this.index});
|
||||
@override
|
||||
_SlidePageState createState() => _SlidePageState();
|
||||
}
|
||||
|
||||
class _SlidePageState extends State<SlidePage> {
|
||||
bool isEng;
|
||||
bool _isLoading = false;
|
||||
|
||||
void _onIntroEnd(context) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
List<Widget> instructionText(BuildContext context, isEng, image, imgHeight,
|
||||
width, List<Instruction> instructions) {
|
||||
List<Widget> list = new List<Widget>();
|
||||
var imgWidth = width - (width * 0.25);
|
||||
File imgFile = File(image);
|
||||
|
||||
list.add(
|
||||
Card(
|
||||
color: const Color(0x7f7c94b6),
|
||||
child: Opacity(
|
||||
opacity: 0.6,
|
||||
child: Image.file(
|
||||
imgFile,
|
||||
alignment: AlignmentDirectional.topCenter,
|
||||
height: imgHeight,
|
||||
width: imgWidth,
|
||||
)),
|
||||
),
|
||||
);
|
||||
|
||||
for (var i = 0; i < instructions.length; i++) {
|
||||
var instruction = instructions[i];
|
||||
var textPositionTop = (imgHeight / 480) * instruction.top;
|
||||
var textPositionLeft = (imgWidth / 360) * instruction.left;
|
||||
|
||||
list.add(Positioned(
|
||||
top: double.parse(textPositionTop.toString()),
|
||||
left: double.parse(textPositionLeft.toString()),
|
||||
child: instruction.text.length > 1
|
||||
? Container(
|
||||
constraints: BoxConstraints(maxWidth: 300),
|
||||
child: Card(
|
||||
color: Colors.blue,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
child: Text(
|
||||
instruction.text,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
))
|
||||
: Container(
|
||||
constraints: BoxConstraints(maxWidth: 200),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
alignment: Alignment.topCenter,
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle, color: Colors.blue),
|
||||
child: isEng
|
||||
? Container(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
instruction.text,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white, fontSize: 14.0),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
instruction.text,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white, fontSize: 14.0),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var mainModel = Provider.of<MainModel>(context);
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
var manualModel = Provider.of<ManualModel>(context);
|
||||
isEng = languageModel.isEng;
|
||||
|
||||
List<PageViewModel> pageViews = new List();
|
||||
var screenSize = MediaQuery.of(context).size;
|
||||
var width = screenSize.width;
|
||||
var height = screenSize.height;
|
||||
var imgHeight = height - (height * 0.25);
|
||||
const bodyStyle = TextStyle(fontSize: 19.0);
|
||||
const pageDecoration = const PageDecoration(
|
||||
titleTextStyle: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w700),
|
||||
bodyTextStyle: bodyStyle,
|
||||
descriptionPadding: EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0),
|
||||
pageColor: Colors.white,
|
||||
imagePadding: EdgeInsets.zero,
|
||||
);
|
||||
|
||||
var pageSlides = widget.helpDetail.slides;
|
||||
|
||||
if (pageSlides.length == 0) {
|
||||
pageViews.add(
|
||||
PageViewModel(
|
||||
titleWidget: Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
isEng ? widget.helpDetail.title : widget.helpDetail.titlemm,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
mainModel.isSysAdmin()
|
||||
? FlatButton(
|
||||
textColor: Colors.blue,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SlideDataPage(
|
||||
manItem: widget.helpDetail,
|
||||
manIndex: widget.index)),
|
||||
);
|
||||
},
|
||||
child: Icon(Icons.edit),
|
||||
shape: CircleBorder(
|
||||
side: BorderSide(color: Colors.transparent)),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
bodyWidget: Container(
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
decoration: pageDecoration),
|
||||
);
|
||||
}
|
||||
|
||||
for (var i = 0; i < pageSlides.length; i++) {
|
||||
var instructions;
|
||||
if (isEng) {
|
||||
instructions = pageSlides[i].instructions;
|
||||
} else {
|
||||
instructions = pageSlides[i].instructionsmm;
|
||||
}
|
||||
|
||||
var imageName;
|
||||
if (isEng) {
|
||||
imageName = '${manualModel.dataDir}/manual/img/' + pageSlides[i].image;
|
||||
} else {
|
||||
imageName =
|
||||
'${manualModel.dataDir}/manual/img/' + pageSlides[i].imagemm;
|
||||
}
|
||||
|
||||
pageViews.add(
|
||||
PageViewModel(
|
||||
titleWidget: Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
isEng ? widget.helpDetail.title : widget.helpDetail.titlemm,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
mainModel.isSysAdmin()
|
||||
? FlatButton(
|
||||
textColor: Colors.blue,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SlideDataPage(
|
||||
manItem: widget.helpDetail,
|
||||
manIndex: widget.index)),
|
||||
);
|
||||
},
|
||||
child: Icon(Icons.edit),
|
||||
shape: CircleBorder(
|
||||
side: BorderSide(color: Colors.transparent)),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
bodyWidget: Container(
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.topStart,
|
||||
children: instructionText(
|
||||
context, isEng, imageName, imgHeight, width, instructions),
|
||||
),
|
||||
),
|
||||
decoration: pageDecoration),
|
||||
);
|
||||
}
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
body: IntroductionScreen(
|
||||
pages: pageViews,
|
||||
onDone: () => _onIntroEnd(context),
|
||||
showSkipButton: true,
|
||||
skipFlex: 0,
|
||||
nextFlex: 0,
|
||||
skip: const Text('Skip'),
|
||||
next: const Icon(Icons.arrow_forward),
|
||||
done: const Text('Done', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
dotsDecorator: DotsDecorator(spacing: EdgeInsets.all(1.0)),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user