Compare commits
2 Commits
7647542421
...
bad485ac1d
Author | SHA1 | Date | |
---|---|---|---|
bad485ac1d | |||
bfd828f520 |
@ -29,6 +29,8 @@ def get(user, id):
|
|||||||
owner = user and (user.get('_id') == proj['user'])
|
owner = user and (user.get('_id') == proj['user'])
|
||||||
if not owner and proj['visibility'] != 'public':
|
if not owner and proj['visibility'] != 'public':
|
||||||
raise util.errors.BadRequest('Forbidden')
|
raise util.errors.BadRequest('Forbidden')
|
||||||
|
if obj['type'] == 'file' and 'storedName' in obj:
|
||||||
|
obj['url'] = uploads.get_presigned_url('projects/{0}/{1}'.format(proj['_id'], obj['storedName']))
|
||||||
if obj['type'] == 'pattern' and 'preview' in obj and '.png' in obj['preview']:
|
if obj['type'] == 'pattern' and 'preview' in obj and '.png' in obj['preview']:
|
||||||
obj['previewUrl'] = uploads.get_presigned_url('projects/{0}/{1}'.format(proj['_id'], obj['preview']))
|
obj['previewUrl'] = uploads.get_presigned_url('projects/{0}/{1}'.format(proj['_id'], obj['preview']))
|
||||||
del obj['preview']
|
del obj['preview']
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -6,31 +6,41 @@ import 'group_noticeboard.dart';
|
|||||||
import 'group_members.dart';
|
import 'group_members.dart';
|
||||||
|
|
||||||
class _GroupScreenState extends State<GroupScreen> {
|
class _GroupScreenState extends State<GroupScreen> {
|
||||||
|
final String id;
|
||||||
|
Map<String, dynamic>? _group;
|
||||||
int _selectedIndex = 0;
|
int _selectedIndex = 0;
|
||||||
List<Widget> _widgetOptions = <Widget> [];
|
|
||||||
final Map<String, dynamic> _group;
|
|
||||||
|
|
||||||
_GroupScreenState(this._group) {
|
_GroupScreenState(this.id) { }
|
||||||
_widgetOptions = <Widget> [
|
|
||||||
GroupNoticeBoardTab(this._group),
|
@override
|
||||||
GroupMembersTab(this._group)
|
void initState() {
|
||||||
];
|
fetchGroup();
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onItemTapped(int index) {
|
void fetchGroup() async {
|
||||||
setState(() {
|
Api api = Api();
|
||||||
_selectedIndex = index;
|
var data = await api.request('GET', '/groups/' + id);
|
||||||
});
|
if (data['success'] == true) {
|
||||||
|
setState(() {
|
||||||
|
_group = data['payload'];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(_group['name'])
|
title: Text(_group?['name'] ?? 'Group')
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: _widgetOptions.elementAt(_selectedIndex),
|
child: _group != null ?
|
||||||
|
[
|
||||||
|
GroupNoticeBoardTab(_group!),
|
||||||
|
GroupMembersTab(_group!)
|
||||||
|
].elementAt(_selectedIndex)
|
||||||
|
: CircularProgressIndicator(),
|
||||||
),
|
),
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
items: const <BottomNavigationBarItem>[
|
items: const <BottomNavigationBarItem>[
|
||||||
@ -45,15 +55,17 @@ class _GroupScreenState extends State<GroupScreen> {
|
|||||||
],
|
],
|
||||||
currentIndex: _selectedIndex,
|
currentIndex: _selectedIndex,
|
||||||
selectedItemColor: Colors.pink[600],
|
selectedItemColor: Colors.pink[600],
|
||||||
onTap: _onItemTapped,
|
onTap: (int index) => setState(() {
|
||||||
|
_selectedIndex = index;
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupScreen extends StatefulWidget {
|
class GroupScreen extends StatefulWidget {
|
||||||
final Map<String,dynamic> group;
|
final String id;
|
||||||
GroupScreen(this.group) { }
|
GroupScreen(this.id) { }
|
||||||
@override
|
@override
|
||||||
_GroupScreenState createState() => _GroupScreenState(group);
|
_GroupScreenState createState() => _GroupScreenState(id);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'group.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'model.dart';
|
import 'model.dart';
|
||||||
import 'lib.dart';
|
import 'lib.dart';
|
||||||
@ -16,6 +16,8 @@ class _GroupsTabState extends State<GroupsTab> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getGroups() async {
|
void getGroups() async {
|
||||||
|
AppModel model = Provider.of<AppModel>(context, listen: false);
|
||||||
|
if (model.user == null) return;
|
||||||
setState(() => _loading = true);
|
setState(() => _loading = true);
|
||||||
Api api = Api();
|
Api api = Api();
|
||||||
var data = await api.request('GET', '/groups');
|
var data = await api.request('GET', '/groups');
|
||||||
@ -36,14 +38,7 @@ class _GroupsTabState extends State<GroupsTab> {
|
|||||||
}
|
}
|
||||||
return Card(
|
return Card(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () => context.push('/groups/' + group['_id']),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => GroupScreen(group),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: Icon(Icons.people),
|
leading: Icon(Icons.people),
|
||||||
trailing: Icon(Icons.keyboard_arrow_right),
|
trailing: Icon(Icons.keyboard_arrow_right),
|
||||||
|
@ -263,12 +263,7 @@ class PatternCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
context.push('/' + object['userObject']['username'] + '/' + object['projectObject']['path'] + '/' + object['_id']);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => ObjectScreen(object, object['projectObject']),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -13,7 +13,9 @@ import 'register.dart';
|
|||||||
import 'onboarding.dart';
|
import 'onboarding.dart';
|
||||||
import 'home.dart';
|
import 'home.dart';
|
||||||
import 'project.dart';
|
import 'project.dart';
|
||||||
|
import 'object.dart';
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
|
import 'group.dart';
|
||||||
|
|
||||||
final router = GoRouter(
|
final router = GoRouter(
|
||||||
routes: [
|
routes: [
|
||||||
@ -37,7 +39,9 @@ final router = GoRouter(
|
|||||||
GoRoute(path: '/onboarding', builder: (context, state) => OnboardingScreen()),
|
GoRoute(path: '/onboarding', builder: (context, state) => OnboardingScreen()),
|
||||||
GoRoute(path: '/home', builder: (context, state) => HomeScreen()),
|
GoRoute(path: '/home', builder: (context, state) => HomeScreen()),
|
||||||
GoRoute(path: '/settings', builder: (context, state) => SettingsScreen()),
|
GoRoute(path: '/settings', builder: (context, state) => SettingsScreen()),
|
||||||
GoRoute(path: '/:username/:id', builder: (context, state) => ProjectScreen(state.pathParameters['username']!, state.pathParameters['id']!)),
|
GoRoute(path: '/groups/:id', builder: (context, state) => GroupScreen(state.pathParameters['id']!)),
|
||||||
|
GoRoute(path: '/:username/:path', builder: (context, state) => ProjectScreen(state.pathParameters['username']!, state.pathParameters['path']!)),
|
||||||
|
GoRoute(path: '/:username/:path/:id', builder: (context, state) => ObjectScreen(state.pathParameters['username']!, state.pathParameters['path']!, state.pathParameters['id']!)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -114,9 +118,7 @@ class Startup extends StatelessWidget {
|
|||||||
_handled = true;
|
_handled = true;
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
String? token = prefs.getString('apiToken');
|
String? token = prefs.getString('apiToken');
|
||||||
print('Nooo');
|
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
print('HEE');
|
|
||||||
AppModel model = Provider.of<AppModel>(context, listen: false);
|
AppModel model = Provider.of<AppModel>(context, listen: false);
|
||||||
await model.setToken(token!);
|
await model.setToken(token!);
|
||||||
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
||||||
|
@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:flutter_html/flutter_html.dart';
|
import 'package:flutter_html/flutter_html.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'util.dart';
|
import 'util.dart';
|
||||||
@ -10,30 +11,32 @@ import 'patterns/pattern.dart';
|
|||||||
import 'patterns/viewer.dart';
|
import 'patterns/viewer.dart';
|
||||||
|
|
||||||
class _ObjectScreenState extends State<ObjectScreen> {
|
class _ObjectScreenState extends State<ObjectScreen> {
|
||||||
final Map<String,dynamic> _project;
|
final String username;
|
||||||
Map<String,dynamic> _object;
|
final String projectPath;
|
||||||
Map<String,dynamic>? _pattern;
|
final String id;
|
||||||
|
final Map<String,dynamic>? project;
|
||||||
|
Map<String,dynamic>? object;
|
||||||
|
Map<String,dynamic>? pattern;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
final Function? onUpdate;
|
final Function? onUpdate;
|
||||||
final Function? onDelete;
|
final Function? onDelete;
|
||||||
final Api api = Api();
|
final Api api = Api();
|
||||||
final Util util = Util();
|
final Util util = Util();
|
||||||
|
|
||||||
_ObjectScreenState(this._object, this._project, {this.onUpdate, this.onDelete}) { }
|
_ObjectScreenState(this.username, this.projectPath, this.id, {this.object, this.project, this.onUpdate, this.onDelete}) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (_object['type'] == 'pattern') {
|
fetchObject();
|
||||||
_fetchPattern();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchPattern() async {
|
void fetchObject() async {
|
||||||
var data = await api.request('GET', '/objects/' + _object['_id']);
|
var data = await api.request('GET', '/objects/' + id);
|
||||||
if (data['success'] == true) {
|
if (data['success'] == true) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_pattern = data['payload']['pattern'];
|
object = data['payload'];
|
||||||
|
pattern = data['payload']['pattern'];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,14 +44,14 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
void _shareObject() async {
|
void _shareObject() async {
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
File? file;
|
File? file;
|
||||||
if (_object['type'] == 'pattern') {
|
if (object!['type'] == 'pattern') {
|
||||||
var data = await api.request('GET', '/objects/' + _object['_id'] + '/wif');
|
var data = await api.request('GET', '/objects/' + id + '/wif');
|
||||||
if (data['success'] == true) {
|
if (data['success'] == true) {
|
||||||
file = await util.writeFile(_object['name'] + '.wif', data['payload']['wif']);
|
file = await util.writeFile(object!['name'] + '.wif', data['payload']['wif']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String fileName = Uri.file(_object['url']).pathSegments.last;
|
String fileName = Uri.file(object!['url']).pathSegments.last;
|
||||||
file = await api.downloadFile(_object['url'], fileName);
|
file = await api.downloadFile(object!['url'], fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
@ -58,12 +61,10 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _deleteObject(BuildContext context, BuildContext modalContext) async {
|
void _deleteObject(BuildContext context, BuildContext modalContext) async {
|
||||||
var data = await api.request('DELETE', '/objects/' + _object['_id']);
|
var data = await api.request('DELETE', '/objects/' + id);
|
||||||
if (data['success']) {
|
if (data['success']) {
|
||||||
Navigator.pop(context);
|
context.go('/home');
|
||||||
Navigator.pop(modalContext);
|
onDelete!(id);
|
||||||
Navigator.pop(context);
|
|
||||||
onDelete!(_object['_id']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
isDefaultAction: true,
|
isDefaultAction: true,
|
||||||
child: Text('No'),
|
child: Text('No'),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => context.pop(),
|
||||||
),
|
),
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
isDestructiveAction: true,
|
isDestructiveAction: true,
|
||||||
@ -105,22 +106,22 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
child: Text('CANCEL'),
|
child: Text('CANCEL'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
context.pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text('OK'),
|
child: Text('OK'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
var data = await api.request('PUT', '/objects/' + _object['_id'], {'name': renameController.text});
|
var data = await api.request('PUT', '/objects/' + id, {'name': renameController.text});
|
||||||
if (data['success']) {
|
if (data['success']) {
|
||||||
Navigator.pop(context);
|
context.pop();
|
||||||
_object['name'] = data['payload']['name'];
|
object!['name'] = data['payload']['name'];
|
||||||
onUpdate!(_object['_id'], data['payload']);
|
onUpdate!(id, data['payload']);
|
||||||
setState(() {
|
setState(() {
|
||||||
_object = _object;
|
object = object;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Navigator.pop(context);
|
context.pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -136,7 +137,7 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
return CupertinoActionSheet(
|
return CupertinoActionSheet(
|
||||||
title: Text('Manage this object'),
|
title: Text('Manage this object'),
|
||||||
cancelButton: CupertinoActionSheetAction(
|
cancelButton: CupertinoActionSheetAction(
|
||||||
onPressed: () => Navigator.of(modalContext).pop(),
|
onPressed: () => modalContext.pop(),
|
||||||
child: Text('Cancel')
|
child: Text('Cancel')
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@ -156,15 +157,22 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getObjectWidget() {
|
Widget getObjectWidget() {
|
||||||
if (_object['isImage'] == true) {
|
if (object == null) {
|
||||||
return Image.network(_object['url']);
|
return Center(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [CircularProgressIndicator()]
|
||||||
|
));
|
||||||
}
|
}
|
||||||
else if (_object['type'] == 'pattern') {
|
else if (object!['isImage'] == true && object!['url'] != null) {
|
||||||
if (_pattern != null) {
|
print(object!['url']);
|
||||||
return PatternViewer(_pattern!, withEditor: true);
|
return Image.network(object!['url']);
|
||||||
|
}
|
||||||
|
else if (object!['type'] == 'pattern') {
|
||||||
|
if (pattern != null) {
|
||||||
|
return PatternViewer(pattern!, withEditor: true);
|
||||||
}
|
}
|
||||||
else if (_object['previewUrl'] != null) {
|
else if (object!['previewUrl'] != null) {
|
||||||
return Image.network(_object['previewUrl']!);;
|
return Image.network(object!['previewUrl']!);;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Column(
|
return Column(
|
||||||
@ -184,7 +192,7 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
Text('Treadl cannot display this type of item.'),
|
Text('Treadl cannot display this type of item.'),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
ElevatedButton(child: Text('View file'), onPressed: () {
|
ElevatedButton(child: Text('View file'), onPressed: () {
|
||||||
launch(_object['url']);
|
launch(object!['url']);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
@ -194,11 +202,11 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String description = '';
|
String description = '';
|
||||||
if (_object['description'] != null)
|
if (object?['description'] != null)
|
||||||
description = _object['description'];
|
description = object!['description']!;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(_object['name']),
|
title: Text(object?['name'] ?? 'Object'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.ios_share),
|
icon: Icon(Icons.ios_share),
|
||||||
@ -228,12 +236,15 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ObjectScreen extends StatefulWidget {
|
class ObjectScreen extends StatefulWidget {
|
||||||
final Map<String,dynamic> _object;
|
final String username;
|
||||||
final Map<String,dynamic> _project;
|
final String projectPath;
|
||||||
|
final String id;
|
||||||
|
final Map<String,dynamic>? object;
|
||||||
|
final Map<String,dynamic>? project;
|
||||||
final Function? onUpdate;
|
final Function? onUpdate;
|
||||||
final Function? onDelete;
|
final Function? onDelete;
|
||||||
ObjectScreen(this._object, this._project, {this.onUpdate, this.onDelete}) { }
|
ObjectScreen(this.username, this.projectPath, this.id, {this.object, this.project, this.onUpdate, this.onDelete}) { }
|
||||||
@override
|
@override
|
||||||
_ObjectScreenState createState() => _ObjectScreenState(_object, _project, onUpdate: onUpdate, onDelete: onDelete);
|
_ObjectScreenState createState() => _ObjectScreenState(username, projectPath, id, object: object, project: project, onUpdate: onUpdate, onDelete: onDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: Text('Get started', style: TextStyle(color: Colors.pink)),
|
child: Text('Get started', style: TextStyle(color: Colors.pink)),
|
||||||
onPressed: () => context.go('/'),
|
onPressed: () => context.go('/home'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -9,7 +9,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'util.dart';
|
import 'util.dart';
|
||||||
import 'object.dart';
|
import 'model.dart';
|
||||||
|
|
||||||
class _ProjectScreenState extends State<ProjectScreen> {
|
class _ProjectScreenState extends State<ProjectScreen> {
|
||||||
final String username;
|
final String username;
|
||||||
@ -252,12 +252,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
return new Card(
|
return new Card(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
context.push('/' + username + '/' + projectPath + '/' + object['_id']);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => ObjectScreen(object, project!, onUpdate: _onUpdateObject, onDelete: _onDeleteObject),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: leader,
|
leading: leader,
|
||||||
@ -269,8 +264,31 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget getBody() {
|
||||||
|
if (_loading || project == null)
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
else if ((_objects != null && _objects.length > 0) || _creating)
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: _objects.length + (_creating ? 1 : 0),
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return getObjectCard(index);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
else
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('This project is currently empty', style: TextStyle(fontSize: 20), textAlign: TextAlign.center),
|
||||||
|
Image(image: AssetImage('assets/empty.png'), width: 300),
|
||||||
|
Text('Add a pattern file, an image, or something else to this project using the + button below.', textAlign: TextAlign.center),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
AppModel model = Provider.of<AppModel>(context);
|
||||||
|
User? user = model.user;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(project?['name'] ?? 'Project'),
|
title: Text(project?['name'] ?? 'Project'),
|
||||||
@ -289,33 +307,13 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
) : SizedBox(width: 0),
|
) : SizedBox(width: 0),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
body: _loading ?
|
body: Container(
|
||||||
Container(
|
|
||||||
margin: const EdgeInsets.all(10.0),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: CircularProgressIndicator()
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
margin: const EdgeInsets.all(10.0),
|
margin: const EdgeInsets.all(10.0),
|
||||||
child: ((_objects != null && _objects.length > 0) || _creating) ?
|
alignment: Alignment.center,
|
||||||
ListView.builder(
|
child: getBody(),
|
||||||
itemCount: _objects.length + (_creating ? 1 : 0),
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return getObjectCard(index);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
:
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text('This project is currently empty', style: TextStyle(fontSize: 20), textAlign: TextAlign.center),
|
|
||||||
Image(image: AssetImage('assets/empty.png'), width: 300),
|
|
||||||
Text('Add a pattern file, an image, or something else to this project using the + button below.', textAlign: TextAlign.center),
|
|
||||||
])
|
|
||||||
),
|
),
|
||||||
floatingActionButtonLocation: ExpandableFab.location,
|
floatingActionButtonLocation: ExpandableFab.location,
|
||||||
floatingActionButton: ExpandableFab(
|
floatingActionButton: user != null ? ExpandableFab(
|
||||||
distance: 70,
|
distance: 70,
|
||||||
type: ExpandableFabType.up,
|
type: ExpandableFabType.up,
|
||||||
openButtonBuilder: RotateFloatingActionButtonBuilder(
|
openButtonBuilder: RotateFloatingActionButtonBuilder(
|
||||||
@ -355,7 +353,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
),
|
) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ class _ProjectsTabState extends State<ProjectsTab> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getProjects() async {
|
void getProjects() async {
|
||||||
|
AppModel model = Provider.of<AppModel>(context, listen: false);
|
||||||
|
if (model.user == null) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_loading = true;
|
_loading = true;
|
||||||
});
|
});
|
||||||
@ -131,6 +133,8 @@ class _ProjectsTabState extends State<ProjectsTab> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
AppModel model = Provider.of<AppModel>(context);
|
||||||
|
User? user = model.user;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('My Projects'),
|
title: Text('My Projects'),
|
||||||
@ -148,11 +152,11 @@ class _ProjectsTabState extends State<ProjectsTab> {
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: getBody()
|
child: getBody()
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: user != null ? FloatingActionButton(
|
||||||
onPressed: showNewProjectDialog,
|
onPressed: showNewProjectDialog,
|
||||||
child: _creatingProject ? CircularProgressIndicator(backgroundColor: Colors.white) : Icon(Icons.add),
|
child: _creatingProject ? CircularProgressIndicator(backgroundColor: Colors.white) : Icon(Icons.add),
|
||||||
backgroundColor: Colors.pink[500],
|
backgroundColor: Colors.pink[500],
|
||||||
),
|
) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,8 @@ class SettingsScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
AppModel model = Provider.of<AppModel>(context);
|
||||||
|
User? user = model.user;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('About Treadl'),
|
title: Text('About Treadl'),
|
||||||
@ -96,16 +98,24 @@ class SettingsScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 30),
|
SizedBox(height: 30),
|
||||||
|
|
||||||
ListTile(
|
user != null ? Column(
|
||||||
leading: Icon(Icons.exit_to_app),
|
children: [
|
||||||
title: Text('Logout'),
|
ListTile(
|
||||||
onTap: () => _logout(context),
|
leading: Icon(Icons.exit_to_app),
|
||||||
),
|
title: Text('Logout'),
|
||||||
ListTile(
|
onTap: () => _logout(context),
|
||||||
leading: Icon(Icons.delete),
|
),
|
||||||
title: Text('Delete Account'),
|
ListTile(
|
||||||
onTap: () => _deleteAccount(context),
|
leading: Icon(Icons.delete),
|
||||||
|
title: Text('Delete Account'),
|
||||||
|
onTap: () => _deleteAccount(context),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
) : CupertinoButton(
|
||||||
|
color: Colors.pink,
|
||||||
|
child: Text('Join Treadl', style: TextStyle(color: Colors.white)),
|
||||||
|
onPressed: () => context.push('/welcome'),
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 30),
|
SizedBox(height: 30),
|
||||||
|
Loading…
Reference in New Issue
Block a user