Compare commits
No commits in common. "ee4b3ef43996773665f40db15fdf27fc044ca639" and "835777e5621a4b19c5a5bdb1cab6f2edfbc15a82" have entirely different histories.
ee4b3ef439
...
835777e562
3
api/.gitignore
vendored
3
api/.gitignore
vendored
@ -7,5 +7,4 @@ __pycache__/
|
|||||||
config-prod.yml
|
config-prod.yml
|
||||||
envfile
|
envfile
|
||||||
firebase.json
|
firebase.json
|
||||||
.DS_Store
|
.DS_Store
|
||||||
migration_projects/
|
|
@ -29,9 +29,6 @@ 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'] == 'pattern' and 'preview' in obj and '.png' in obj['preview']:
|
|
||||||
obj['previewUrl'] = uploads.get_presigned_url('projects/{0}/{1}'.format(proj['_id'], obj['preview']))
|
|
||||||
del obj['preview']
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def copy_to_project(user, id, project_id):
|
def copy_to_project(user, id, project_id):
|
||||||
|
@ -122,9 +122,6 @@ def get_objects(user, username, path):
|
|||||||
for obj in objs:
|
for obj in objs:
|
||||||
if obj['type'] == 'file' and 'storedName' in obj:
|
if obj['type'] == 'file' and 'storedName' in obj:
|
||||||
obj['url'] = uploads.get_presigned_url('projects/{0}/{1}'.format(project['_id'], obj['storedName']))
|
obj['url'] = uploads.get_presigned_url('projects/{0}/{1}'.format(project['_id'], obj['storedName']))
|
||||||
if obj['type'] == 'pattern' and 'preview' in obj and '.png' in obj['preview']:
|
|
||||||
obj['previewUrl'] = uploads.get_presigned_url('projects/{0}/{1}'.format(project['_id'], obj['preview']))
|
|
||||||
del obj['preview']
|
|
||||||
return objs
|
return objs
|
||||||
|
|
||||||
def create_object(user, username, path, data):
|
def create_object(user, username, path, data):
|
||||||
|
@ -91,9 +91,6 @@ def explore(page = 1):
|
|||||||
objects = list(db.objects.find({'project': {'$in': all_public_project_ids}, 'name': {'$not': re.compile('untitled pattern', re.IGNORECASE)}, 'preview': {'$exists': True}}, {'project': 1, 'name': 1, 'createdAt': 1, 'preview': 1}).sort('createdAt', pymongo.DESCENDING).skip((page - 1) * per_page).limit(per_page))
|
objects = list(db.objects.find({'project': {'$in': all_public_project_ids}, 'name': {'$not': re.compile('untitled pattern', re.IGNORECASE)}, 'preview': {'$exists': True}}, {'project': 1, 'name': 1, 'createdAt': 1, 'preview': 1}).sort('createdAt', pymongo.DESCENDING).skip((page - 1) * per_page).limit(per_page))
|
||||||
for object in objects:
|
for object in objects:
|
||||||
object['projectObject'] = project_map.get(object['project'])
|
object['projectObject'] = project_map.get(object['project'])
|
||||||
if 'preview' in object and '.png' in object['preview']:
|
|
||||||
object['previewUrl'] = uploads.get_presigned_url('projects/{0}/{1}'.format(object['project'], object['preview']))
|
|
||||||
del object['preview']
|
|
||||||
authors = list(db.users.find({'_id': {'$in': list(map(lambda o: o.get('projectObject', {}).get('user'), objects))}}, {'username': 1, 'avatar': 1, 'isSilverSupporter': 1, 'isGoldSupporter': 1}))
|
authors = list(db.users.find({'_id': {'$in': list(map(lambda o: o.get('projectObject', {}).get('user'), objects))}}, {'username': 1, 'avatar': 1, 'isSilverSupporter': 1, 'isGoldSupporter': 1}))
|
||||||
for a in authors:
|
for a in authors:
|
||||||
if 'avatar' in a:
|
if 'avatar' in a:
|
||||||
|
@ -4,7 +4,7 @@ from bson.objectid import ObjectId
|
|||||||
import boto3
|
import boto3
|
||||||
from botocore.client import Config
|
from botocore.client import Config
|
||||||
import blurhash
|
import blurhash
|
||||||
from util import database, util
|
from util import database
|
||||||
|
|
||||||
def sanitise_filename(s):
|
def sanitise_filename(s):
|
||||||
bad_chars = re.compile('[^a-zA-Z0-9_.]')
|
bad_chars = re.compile('[^a-zA-Z0-9_.]')
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
# Script to migrate from the old data: string URLs for images to image files directly on S3.
|
|
||||||
|
|
||||||
from pymongo import MongoClient
|
|
||||||
import base64, os
|
|
||||||
|
|
||||||
db = MongoClient('mongodb://USER:PASS@db/admin')['treadl']
|
|
||||||
|
|
||||||
os.makedirs('migration_projects/projects', exist_ok=True)
|
|
||||||
|
|
||||||
for obj in db.objects.find({'preview': {'$regex': '^data:'}}, {'preview': 1, 'project': 1}):
|
|
||||||
preview = obj['preview']
|
|
||||||
preview = preview.replace('data:image/png;base64,', '')
|
|
||||||
|
|
||||||
imgdata = base64.b64decode(preview)
|
|
||||||
filename = 'some_image.png'
|
|
||||||
|
|
||||||
os.makedirs('migration_projects/projects/'+str(obj['project']), exist_ok=True)
|
|
||||||
with open('migration_projects/projects/'+str(obj['project'])+'/preview_'+str(obj['_id'])+'.png' , 'wb') as f:
|
|
||||||
f.write(imgdata)
|
|
||||||
db.objects.update_one({'_id': obj['_id']}, {'$set': {'previewNew': 'preview_'+str(obj['_id'])+'.png'}})
|
|
||||||
#exit()
|
|
@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>11.0</string>
|
<string>9.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
# platform :ios, '11.0'
|
# platform :ios, '9.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
@ -1,91 +1,108 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Firebase/CoreOnly (10.9.0):
|
- Firebase/CoreOnly (8.11.0):
|
||||||
- FirebaseCore (= 10.9.0)
|
- FirebaseCore (= 8.11.0)
|
||||||
- Firebase/Messaging (10.9.0):
|
- Firebase/Messaging (8.11.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 10.9.0)
|
- FirebaseMessaging (~> 8.11.0)
|
||||||
- firebase_core (2.13.1):
|
- firebase_core (1.13.1):
|
||||||
- Firebase/CoreOnly (= 10.9.0)
|
- Firebase/CoreOnly (= 8.11.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (14.6.2):
|
- firebase_messaging (11.2.8):
|
||||||
- Firebase/Messaging (= 10.9.0)
|
- Firebase/Messaging (= 8.11.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseCore (10.9.0):
|
- FirebaseCore (8.11.0):
|
||||||
- FirebaseCoreInternal (~> 10.0)
|
- FirebaseCoreDiagnostics (~> 8.0)
|
||||||
- GoogleUtilities/Environment (~> 7.8)
|
|
||||||
- GoogleUtilities/Logger (~> 7.8)
|
|
||||||
- FirebaseCoreInternal (10.10.0):
|
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
|
||||||
- FirebaseInstallations (10.10.0):
|
|
||||||
- FirebaseCore (~> 10.0)
|
|
||||||
- GoogleUtilities/Environment (~> 7.8)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
|
||||||
- PromisesObjC (~> 2.1)
|
|
||||||
- FirebaseMessaging (10.9.0):
|
|
||||||
- FirebaseCore (~> 10.0)
|
|
||||||
- FirebaseInstallations (~> 10.0)
|
|
||||||
- GoogleDataTransport (~> 9.2)
|
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
|
||||||
- GoogleUtilities/Environment (~> 7.8)
|
|
||||||
- GoogleUtilities/Reachability (~> 7.8)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- GoogleDataTransport (9.2.3):
|
|
||||||
- GoogleUtilities/Environment (~> 7.7)
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- GoogleUtilities/Logger (~> 7.7)
|
||||||
|
- FirebaseCoreDiagnostics (8.12.0):
|
||||||
|
- GoogleDataTransport (~> 9.1)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/Logger (~> 7.7)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
|
- FirebaseInstallations (8.12.0):
|
||||||
|
- FirebaseCore (~> 8.0)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||||
- PromisesObjC (< 3.0, >= 1.2)
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (7.11.1):
|
- FirebaseMessaging (8.11.0):
|
||||||
|
- FirebaseCore (~> 8.0)
|
||||||
|
- FirebaseInstallations (~> 8.0)
|
||||||
|
- GoogleDataTransport (~> 9.1)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/Reachability (~> 7.7)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- fluttertoast (0.0.2):
|
||||||
|
- Flutter
|
||||||
|
- Toast
|
||||||
|
- GoogleDataTransport (9.1.2):
|
||||||
|
- GoogleUtilities/Environment (~> 7.2)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
|
||||||
- GoogleUtilities/Environment
|
- GoogleUtilities/Environment
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GoogleUtilities/Network
|
- GoogleUtilities/Network
|
||||||
- GoogleUtilities/Environment (7.11.1):
|
- GoogleUtilities/Environment (7.7.0):
|
||||||
- PromisesObjC (< 3.0, >= 1.2)
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
- GoogleUtilities/Logger (7.11.1):
|
- GoogleUtilities/Logger (7.7.0):
|
||||||
- GoogleUtilities/Environment
|
- GoogleUtilities/Environment
|
||||||
- GoogleUtilities/Network (7.11.1):
|
- GoogleUtilities/Network (7.7.0):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- "GoogleUtilities/NSData+zlib"
|
- "GoogleUtilities/NSData+zlib"
|
||||||
- GoogleUtilities/Reachability
|
- GoogleUtilities/Reachability
|
||||||
- "GoogleUtilities/NSData+zlib (7.11.1)"
|
- "GoogleUtilities/NSData+zlib (7.7.0)"
|
||||||
- GoogleUtilities/Reachability (7.11.1):
|
- GoogleUtilities/Reachability (7.7.0):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GoogleUtilities/UserDefaults (7.11.1):
|
- GoogleUtilities/UserDefaults (7.7.0):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- image_picker_ios (0.0.1):
|
- image_picker (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- nanopb (2.30909.0):
|
- nanopb (2.30908.0):
|
||||||
- nanopb/decode (= 2.30909.0)
|
- nanopb/decode (= 2.30908.0)
|
||||||
- nanopb/encode (= 2.30909.0)
|
- nanopb/encode (= 2.30908.0)
|
||||||
- nanopb/decode (2.30909.0)
|
- nanopb/decode (2.30908.0)
|
||||||
- nanopb/encode (2.30909.0)
|
- nanopb/encode (2.30908.0)
|
||||||
- PromisesObjC (2.2.0)
|
- PromisesObjC (2.0.0)
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- Toast (4.0.0)
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- video_player_avfoundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- wakelock (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- webview_flutter_wkwebview (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
|
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
||||||
|
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
||||||
|
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||||
|
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- Firebase
|
- Firebase
|
||||||
- FirebaseCore
|
- FirebaseCore
|
||||||
- FirebaseCoreInternal
|
- FirebaseCoreDiagnostics
|
||||||
- FirebaseInstallations
|
- FirebaseInstallations
|
||||||
- FirebaseMessaging
|
- FirebaseMessaging
|
||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
- nanopb
|
- nanopb
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
|
- Toast
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
firebase_core:
|
firebase_core:
|
||||||
@ -94,30 +111,43 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
image_picker_ios:
|
fluttertoast:
|
||||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||||
shared_preferences_foundation:
|
image_picker:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
|
:path: ".symlinks/plugins/image_picker/ios"
|
||||||
|
shared_preferences_ios:
|
||||||
|
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
video_player_avfoundation:
|
||||||
|
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
||||||
|
wakelock:
|
||||||
|
:path: ".symlinks/plugins/wakelock/ios"
|
||||||
|
webview_flutter_wkwebview:
|
||||||
|
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Firebase: bd152f0f3d278c4060c5c71359db08ebcfd5a3e2
|
Firebase: 44dd9724c84df18b486639e874f31436eaa9a20c
|
||||||
firebase_core: ce64b0941c6d87c6ef5022ae9116a158236c8c94
|
firebase_core: 08f6a85f62060111de5e98d6a214810d11365de9
|
||||||
firebase_messaging: 42912365e62efc1ea3e00724e5eecba6068ddb88
|
firebase_messaging: 36238f3d0b933af8c919aef608408aae06ba22e8
|
||||||
FirebaseCore: b68d3616526ec02e4d155166bbafb8eca64af557
|
FirebaseCore: 2f4f85b453cc8fea4bb2b37e370007d2bcafe3f0
|
||||||
FirebaseCoreInternal: 971029061d326000d65bfdc21f5502c75c8b0893
|
FirebaseCoreDiagnostics: 3b40dfadef5b90433a60ae01f01e90fe87aa76aa
|
||||||
FirebaseInstallations: 52153982b057d3afcb4e1fbb3eb0b6d00611e681
|
FirebaseInstallations: 25764cf322e77f99449395870a65b2bef88e1545
|
||||||
FirebaseMessaging: 6b7052cc3da7bc8e5f72bef871243e8f04a14eed
|
FirebaseMessaging: 02e248e8997f71fa8cc9d78e9d49ec1a701ba14a
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd
|
fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
|
||||||
GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
|
GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
|
||||||
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
|
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
|
||||||
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
image_picker: 541dcbb3b9cf32d87eacbd957845d8651d6c62c3
|
||||||
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
|
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58
|
||||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||||
|
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||||
|
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
||||||
|
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
||||||
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
|
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
|
||||||
|
|
||||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||||
|
|
||||||
COCOAPODS: 1.12.0
|
COCOAPODS: 1.10.1
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 54;
|
objectVersion = 51;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@ -232,7 +232,6 @@
|
|||||||
};
|
};
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
@ -247,7 +246,6 @@
|
|||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
|
@ -46,9 +46,5 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -6,23 +6,23 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
|
|
||||||
String? _token;
|
String _token;
|
||||||
final String apiBase = 'https://api.treadl.com';
|
final String apiBase = 'https://api.treadl.com';
|
||||||
//final String apiBase = 'http://192.168.5.86:2001';
|
//final String apiBase = 'http://localhost:2001';
|
||||||
|
|
||||||
Future<String?> loadToken() async {
|
Future<String> loadToken() async {
|
||||||
if (_token != null) {
|
if (_token != null) {
|
||||||
return _token!;
|
return _token;
|
||||||
}
|
}
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
String? token = prefs.getString('apiToken');
|
final String token = prefs.getString('apiToken');
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
Future<Map<String,String>> getHeaders(method) async {
|
Future<Map<String,String>> getHeaders(method) async {
|
||||||
Map<String,String> headers = {};
|
Map<String,String> headers = {};
|
||||||
String? token = await loadToken();
|
String token = await loadToken();
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
headers['Authorization'] = 'Bearer ' + token!;
|
headers['Authorization'] = 'Bearer ' + token;
|
||||||
}
|
}
|
||||||
if (method == 'POST' || method == 'DELETE') {
|
if (method == 'POST' || method == 'DELETE') {
|
||||||
headers['Content-Type'] = 'application/json';
|
headers['Content-Type'] = 'application/json';
|
||||||
@ -34,23 +34,17 @@ class Api {
|
|||||||
http.Client client = http.Client();
|
http.Client client = http.Client();
|
||||||
return await client.get(url, headers: await getHeaders('GET'));
|
return await client.get(url, headers: await getHeaders('GET'));
|
||||||
}
|
}
|
||||||
Future<http.Response> _post(Uri url, Map<String, dynamic>? data) async {
|
Future<http.Response> _post(Uri url, Map<String, dynamic> data) async {
|
||||||
String? json = null;
|
String json = jsonEncode(data);
|
||||||
if (data != null) {
|
|
||||||
json = jsonEncode(data!);
|
|
||||||
}
|
|
||||||
http.Client client = http.Client();
|
http.Client client = http.Client();
|
||||||
return await client.post(url, headers: await getHeaders('POST'), body: json);
|
return await client.post(url, headers: await getHeaders('POST'), body: json);
|
||||||
}
|
}
|
||||||
Future<http.Response> _put(Uri url, Map<String, dynamic>? data) async {
|
Future<http.Response> _put(Uri url, Map<String, dynamic> data) async {
|
||||||
String? json = null;
|
String json = jsonEncode(data);
|
||||||
if (data != null) {
|
|
||||||
json = jsonEncode(data!);
|
|
||||||
}
|
|
||||||
http.Client client = http.Client();
|
http.Client client = http.Client();
|
||||||
return await client.put(url, headers: await getHeaders('POST'), body: json);
|
return await client.put(url, headers: await getHeaders('POST'), body: json);
|
||||||
}
|
}
|
||||||
Future<http.Response> _delete(Uri url, [Map<String, dynamic>? data]) async {
|
Future<http.Response> _delete(Uri url, [Map<String, dynamic> data]) async {
|
||||||
http.Client client = http.Client();
|
http.Client client = http.Client();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
String json = jsonEncode(data);
|
String json = jsonEncode(data);
|
||||||
@ -60,10 +54,10 @@ class Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> request(String method, String path, [Map<String, dynamic>? data]) async {
|
Future<Map<String, dynamic>> request(String method, String path, [Map<String, dynamic> data]) async {
|
||||||
String url = apiBase + path;
|
String url = apiBase + path;
|
||||||
Uri uri = Uri.parse(url);
|
Uri uri = Uri.parse(url);
|
||||||
http.Response? response;
|
http.Response response;
|
||||||
if (method == 'POST') {
|
if (method == 'POST') {
|
||||||
response = await _post(uri, data);
|
response = await _post(uri, data);
|
||||||
}
|
}
|
||||||
@ -76,19 +70,16 @@ class Api {
|
|||||||
if (method == 'DELETE') {
|
if (method == 'DELETE') {
|
||||||
response = await _delete(uri, data);
|
response = await _delete(uri, data);
|
||||||
}
|
}
|
||||||
if (response == null) {
|
int status = response.statusCode;
|
||||||
return {'success': false, 'message': 'No response for your request'};
|
|
||||||
}
|
|
||||||
int status = response!.statusCode;
|
|
||||||
if (status == 200) {
|
if (status == 200) {
|
||||||
print('SUCCESS');
|
print('SUCCESS');
|
||||||
Map<String, dynamic> respData = jsonDecode(response!.body);
|
Map<String, dynamic> respData = jsonDecode(response.body);
|
||||||
return {'success': true, 'payload': respData};
|
return {'success': true, 'payload': respData};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print('ERROR');
|
print('ERROR');
|
||||||
Map<String, dynamic> respData = jsonDecode(response!.body);
|
Map<String, dynamic> respData = jsonDecode(response.body);
|
||||||
return {'success': false, 'code': status, 'message': respData['message']};
|
return {'success': false, 'code': response.statusCode, 'message': respData['message']};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ class Alert extends StatelessWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
final String description;
|
final String description;
|
||||||
final String actionText;
|
final String actionText;
|
||||||
final Widget? descriptionWidget;
|
final Widget descriptionWidget;
|
||||||
final Function? action;
|
final Function action;
|
||||||
Alert({this.type = 'info', this.title = '', this.description = '', this.descriptionWidget = null, this.actionText = 'Click here', this.action}) {}
|
Alert({this.type = 'info', this.title = '', this.description = '', this.descriptionWidget = null, this.actionText = 'Click here', this.action}) {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,7 +39,7 @@ class Alert extends StatelessWidget {
|
|||||||
color: accentColor,
|
color: accentColor,
|
||||||
borderRadius: new BorderRadius.all(Radius.circular(10.0)),
|
borderRadius: new BorderRadius.all(Radius.circular(10.0)),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(color: Colors.grey[50]!, spreadRadius: 5),
|
BoxShadow(color: Colors.grey[50], spreadRadius: 5),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -48,12 +48,12 @@ class Alert extends StatelessWidget {
|
|||||||
Icon(icon, color: color),
|
Icon(icon, color: color),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Text(description, textAlign: TextAlign.center),
|
Text(description, textAlign: TextAlign.center),
|
||||||
descriptionWidget != null ? descriptionWidget! : Text(""),
|
descriptionWidget,
|
||||||
action != null ? CupertinoButton(
|
action != null ? CupertinoButton(
|
||||||
child: Text(actionText),
|
child: Text(actionText),
|
||||||
onPressed: () => action!(),
|
onPressed: action,
|
||||||
) : Text("")
|
) : null
|
||||||
]
|
].where((o) => o != null).toList()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -61,8 +61,8 @@ class Alert extends StatelessWidget {
|
|||||||
|
|
||||||
class NoticeboardPost extends StatefulWidget {
|
class NoticeboardPost extends StatefulWidget {
|
||||||
final Map<String,dynamic> _entry;
|
final Map<String,dynamic> _entry;
|
||||||
final Function? onDelete;
|
final Function onDelete;
|
||||||
final Function? onReply;
|
final Function onReply;
|
||||||
NoticeboardPost(this._entry, {this.onDelete = null, this.onReply = null});
|
NoticeboardPost(this._entry, {this.onDelete = null, this.onReply = null});
|
||||||
_NoticeboardPostState createState() => _NoticeboardPostState(_entry, onDelete: onDelete, onReply: onReply);
|
_NoticeboardPostState createState() => _NoticeboardPostState(_entry, onDelete: onDelete, onReply: onReply);
|
||||||
}
|
}
|
||||||
@ -70,8 +70,8 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
final Map<String,dynamic> _entry;
|
final Map<String,dynamic> _entry;
|
||||||
final Util utils = new Util();
|
final Util utils = new Util();
|
||||||
final Api api = new Api();
|
final Api api = new Api();
|
||||||
final Function? onDelete;
|
final Function onDelete;
|
||||||
final Function? onReply;
|
final Function onReply;
|
||||||
final TextEditingController _replyController = TextEditingController();
|
final TextEditingController _replyController = TextEditingController();
|
||||||
bool _isReplying = false;
|
bool _isReplying = false;
|
||||||
bool _replying = false;
|
bool _replying = false;
|
||||||
@ -84,9 +84,7 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
if (data['success'] == true) {
|
if (data['success'] == true) {
|
||||||
_replyController.value = TextEditingValue(text: '');
|
_replyController.value = TextEditingValue(text: '');
|
||||||
FocusScope.of(context).requestFocus(FocusNode());
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
if (onReply != null) {
|
onReply(data['payload']);
|
||||||
onReply!(data['payload']);
|
|
||||||
}
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_replying = false;
|
_replying = false;
|
||||||
_isReplying = false;
|
_isReplying = false;
|
||||||
@ -97,9 +95,7 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
void _deletePost() async {
|
void _deletePost() async {
|
||||||
var data = await api.request('DELETE', '/groups/' + _entry['group'] + '/entries/' + _entry['_id']);
|
var data = await api.request('DELETE', '/groups/' + _entry['group'] + '/entries/' + _entry['_id']);
|
||||||
if (data['success'] == true) {
|
if (data['success'] == true) {
|
||||||
if (onDelete != null) {
|
onDelete(_entry);
|
||||||
onDelete!(_entry);
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,17 +104,17 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var createdAt = DateTime.parse(_entry['createdAt']);
|
var createdAt = DateTime.parse(_entry['createdAt']);
|
||||||
bool isReply = _entry['inReplyTo'] != null;
|
bool isReply = _entry['inReplyTo'] != null;
|
||||||
int replyCount = _entry['replies'] == null ? 0 : _entry['replies']!.length;
|
int replyCount = _entry['replies'] == null ? 0 : _entry['replies'].length;
|
||||||
String replyText = 'Write a reply...';
|
String replyText = 'Write a reply...';
|
||||||
if (replyCount == 1) replyText = '1 Reply';
|
if (replyCount == 1) replyText = '1 Reply';
|
||||||
if (replyCount > 1) replyText = replyCount.toString() + ' replies';
|
if (replyCount > 1) replyText = replyCount.toString() + ' replies';
|
||||||
if (_isReplying) replyText = 'Cancel reply';
|
if (_isReplying) replyText = 'Cancel reply';
|
||||||
List<Widget> replyWidgets = [];
|
List<Widget> replyWidgets = [];
|
||||||
if (_entry['replies'] != null) {
|
if (_entry['replies'] != null) {
|
||||||
for (int i = 0; i < _entry['replies']!.length; i++) {
|
for (int i = 0; i < _entry['replies'].length; i++) {
|
||||||
replyWidgets.add(new Container(
|
replyWidgets.add(new Container(
|
||||||
key: Key(_entry['replies']![i]['_id']),
|
key: Key(_entry['replies'][i]['_id']),
|
||||||
child: NoticeboardPost(_entry['replies']![i], onDelete: onDelete)
|
child: NoticeboardPost(_entry['replies'][i], onDelete: onDelete)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,20 +127,20 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
//color: Colors.orange,
|
color: Colors.orange,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
launch('https://www.treadl.com');
|
launch('https://www.treadl.com');
|
||||||
},
|
},
|
||||||
child: Text('Report this post'),
|
child: Text('Report this post'),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
//color: Colors.red,
|
color: Colors.red,
|
||||||
onPressed: _deletePost,
|
onPressed: _deletePost,
|
||||||
child: Text('Delete post'),
|
child: Text('Delete post'),
|
||||||
),
|
),
|
||||||
TextButton(
|
FlatButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
@ -180,18 +176,18 @@ class _NoticeboardPostState extends State<NoticeboardPost> {
|
|||||||
!isReply ? GestureDetector(
|
!isReply ? GestureDetector(
|
||||||
onTap: () => setState(() => _isReplying = !_isReplying),
|
onTap: () => setState(() => _isReplying = !_isReplying),
|
||||||
child: Text(replyText, style: TextStyle(color: replyCount > 0 ? Colors.pink : Colors.black, fontSize: 10, fontWeight: FontWeight.bold)),
|
child: Text(replyText, style: TextStyle(color: replyCount > 0 ? Colors.pink : Colors.black, fontSize: 10, fontWeight: FontWeight.bold)),
|
||||||
): SizedBox(width: 0),
|
): null,
|
||||||
],
|
].where((o) => o != null).toList(),
|
||||||
),
|
),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
SizedBox(width: 45),
|
SizedBox(width: 45),
|
||||||
Expanded(child: Text(_entry['content'], textAlign: TextAlign.left))
|
Expanded(child: Text(_entry['content'], textAlign: TextAlign.left))
|
||||||
]),
|
]),
|
||||||
_isReplying ? NoticeboardInput(_replyController, _sendReply, _replying, label: 'Reply to this post') : SizedBox(width: 0),
|
_isReplying ? NoticeboardInput(_replyController, _sendReply, _replying, label: 'Reply to this post') : null,
|
||||||
Column(
|
Column(
|
||||||
children: replyWidgets
|
children: replyWidgets
|
||||||
),
|
),
|
||||||
],
|
].where((o) => o != null).toList(),
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -219,7 +215,7 @@ class NoticeboardInput extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => _onPost!(),
|
onPressed: _onPost,
|
||||||
color: Colors.pink,
|
color: Colors.pink,
|
||||||
icon: _posting ? CircularProgressIndicator() : Icon(Icons.send),
|
icon: _posting ? CircularProgressIndicator() : Icon(Icons.send),
|
||||||
)
|
)
|
||||||
|
@ -80,9 +80,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
)]
|
)]
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
onPressed: () => _submit(context),
|
onPressed: () => _submit(context),
|
||||||
//color: Colors.pink,
|
color: Colors.pink,
|
||||||
child: _loggingIn ? SizedBox(height: 20, width: 20, child:CircularProgressIndicator(backgroundColor: Colors.white)) : Text("Login",
|
child: _loggingIn ? SizedBox(height: 20, width: 20, child:CircularProgressIndicator(backgroundColor: Colors.white)) : Text("Login",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(color: Colors.white, fontSize: 15)
|
style: TextStyle(color: Colors.white, fontSize: 15)
|
||||||
|
@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
//import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'store.dart';
|
import 'store.dart';
|
||||||
import 'welcome.dart';
|
import 'welcome.dart';
|
||||||
@ -42,7 +42,7 @@ class _AppState extends State<MyApp> {
|
|||||||
title: 'Treadl',
|
title: 'Treadl',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.pink,
|
primarySwatch: Colors.pink,
|
||||||
//textSelectionColor: Colors.blue,
|
textSelectionColor: Colors.blue,
|
||||||
),
|
),
|
||||||
home: Startup(),
|
home: Startup(),
|
||||||
routes: <String, WidgetBuilder>{
|
routes: <String, WidgetBuilder>{
|
||||||
@ -64,12 +64,12 @@ class Startup extends StatelessWidget {
|
|||||||
Startup() {
|
Startup() {
|
||||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||||
if (message.notification != null) {
|
if (message.notification != null) {
|
||||||
print(message.notification!);
|
print(message.notification.body);
|
||||||
String text = '';
|
String text = '';
|
||||||
if (message.notification != null && message.notification!.body != null) {
|
if (message.notification != null && message.notification.body != null) {
|
||||||
text = message.notification!.body!;
|
text = message.notification.body;
|
||||||
}
|
}
|
||||||
/*Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: text,
|
msg: text,
|
||||||
toastLength: Toast.LENGTH_LONG,
|
toastLength: Toast.LENGTH_LONG,
|
||||||
gravity: ToastGravity.TOP,
|
gravity: ToastGravity.TOP,
|
||||||
@ -77,7 +77,7 @@ class Startup extends StatelessWidget {
|
|||||||
backgroundColor: Colors.grey[100],
|
backgroundColor: Colors.grey[100],
|
||||||
textColor: Colors.black,
|
textColor: Colors.black,
|
||||||
fontSize: 16.0
|
fontSize: 16.0
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -86,9 +86,9 @@ class Startup extends StatelessWidget {
|
|||||||
if (_handled) return;
|
if (_handled) return;
|
||||||
_handled = true;
|
_handled = true;
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
String? token = prefs.getString('apiToken');
|
final String token = prefs.getString('apiToken');
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
Provider.of<Store>(context, listen: false).setToken(token!);
|
Provider.of<Store>(context, listen: false).setToken(token);
|
||||||
|
|
||||||
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
||||||
await _firebaseMessaging.requestPermission(
|
await _firebaseMessaging.requestPermission(
|
||||||
@ -100,14 +100,16 @@ class Startup extends StatelessWidget {
|
|||||||
provisional: false,
|
provisional: false,
|
||||||
sound: true,
|
sound: true,
|
||||||
);
|
);
|
||||||
String? _pushToken = await _firebaseMessaging.getToken();
|
String _pushToken = await _firebaseMessaging.getToken();
|
||||||
if (_pushToken != null) {
|
if (_pushToken != null) {
|
||||||
print("sending push");
|
print("sending push");
|
||||||
Api api = Api();
|
Api api = Api();
|
||||||
api.request('PUT', '/accounts/pushToken', {'pushToken': _pushToken!});
|
api.request('PUT', '/accounts/pushToken', {'pushToken': _pushToken});
|
||||||
}
|
}
|
||||||
|
print('111');
|
||||||
// Push without including current route in stack:
|
// Push without including current route in stack:
|
||||||
Navigator.of(context, rootNavigator: true).pushNamedAndRemoveUntil('/home', (Route<dynamic> route) => false);
|
Navigator.of(context, rootNavigator: true).pushNamedAndRemoveUntil('/home', (Route<dynamic> route) => false);
|
||||||
|
print('222');
|
||||||
} else {
|
} else {
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil('/welcome', (Route<dynamic> route) => false);
|
Navigator.of(context).pushNamedAndRemoveUntil('/welcome', (Route<dynamic> route) => false);
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,11 @@ import 'package:flutter_html/flutter_html.dart';
|
|||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
|
|
||||||
class _ObjectScreenState extends State<ObjectScreen> {
|
class _ObjectScreenState extends State<ObjectScreen> {
|
||||||
final Map<String,dynamic> _project;
|
final Map<String,dynamic> _object;
|
||||||
Map<String,dynamic> _object;
|
|
||||||
final Function _onUpdate;
|
|
||||||
final Function _onDelete;
|
final Function _onDelete;
|
||||||
final Api api = Api();
|
final Api api = Api();
|
||||||
|
|
||||||
_ObjectScreenState(this._object, this._project, this._onUpdate, this._onDelete) { }
|
_ObjectScreenState(this._object, this._onDelete) { }
|
||||||
|
|
||||||
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/' + _object['_id']);
|
||||||
@ -28,7 +26,7 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: modalContext,
|
context: modalContext,
|
||||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||||
title: new Text('Really delete this item?'),
|
title: new Text('Really delete this object?'),
|
||||||
content: new Text('This action cannot be undone.'),
|
content: new Text('This action cannot be undone.'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
@ -45,47 +43,6 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _renameObject(BuildContext context) {
|
|
||||||
TextEditingController renameController = TextEditingController();
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text('Rename this item'),
|
|
||||||
content: TextField(
|
|
||||||
autofocus: true,
|
|
||||||
controller: renameController,
|
|
||||||
decoration: InputDecoration(hintText: "Enter a new name for the item"),
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: Text('CANCEL'),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text('OK'),
|
|
||||||
onPressed: () async {
|
|
||||||
print(renameController.text);
|
|
||||||
var data = await api.request('PUT', '/objects/' + _object['_id'], {'name': renameController.text});
|
|
||||||
if (data['success']) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
_object['name'] = data['payload']['name'];
|
|
||||||
_onUpdate(_object['_id'], data['payload']);
|
|
||||||
setState(() {
|
|
||||||
_object = _object;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showSettingsModal(context) {
|
void _showSettingsModal(context) {
|
||||||
showCupertinoModalPopup(
|
showCupertinoModalPopup(
|
||||||
@ -98,13 +55,9 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
child: Text('Cancel')
|
child: Text('Cancel')
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
CupertinoActionSheetAction(
|
|
||||||
onPressed: () => _renameObject(context),
|
|
||||||
child: Text('Rename item'),
|
|
||||||
),
|
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () => _confirmDeleteObject(modalContext),
|
onPressed: () => _confirmDeleteObject(modalContext),
|
||||||
child: Text('Delete item'),
|
child: Text('Delete object'),
|
||||||
isDestructiveAction: true,
|
isDestructiveAction: true,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@ -118,22 +71,11 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
return Image.network(_object['url']);
|
return Image.network(_object['url']);
|
||||||
}
|
}
|
||||||
else if (_object['type'] == 'pattern') {
|
else if (_object['type'] == 'pattern') {
|
||||||
if (_object['previewUrl'] != null) {
|
var dat = Uri.parse(_object['preview']).data;
|
||||||
return Image.network(_object['previewUrl']!);;
|
return Image.memory(dat.contentAsBytes());
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(height: 50),
|
|
||||||
Icon(Icons.pattern, size: 40),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
Text('A preview of this pattern is not yet available'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ElevatedButton(child: Text('View file'), onPressed: () {
|
return RaisedButton(child: Text('View file'), onPressed: () {
|
||||||
launch(_object['url']);
|
launch(_object['url']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -171,10 +113,8 @@ class _ObjectScreenState extends State<ObjectScreen> {
|
|||||||
|
|
||||||
class ObjectScreen extends StatefulWidget {
|
class ObjectScreen extends StatefulWidget {
|
||||||
final Map<String,dynamic> _object;
|
final Map<String,dynamic> _object;
|
||||||
final Map<String,dynamic> _project;
|
|
||||||
final Function _onUpdate;
|
|
||||||
final Function _onDelete;
|
final Function _onDelete;
|
||||||
ObjectScreen(this._object, this._project, this._onUpdate, this._onDelete) { }
|
ObjectScreen(this._object, this._onDelete) { }
|
||||||
@override
|
@override
|
||||||
_ObjectScreenState createState() => _ObjectScreenState(_object, _project, _onUpdate, _onDelete);
|
_ObjectScreenState createState() => _ObjectScreenState(_object, _onDelete);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
);
|
);
|
||||||
final Api api = Api();
|
final Api api = Api();
|
||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
String? _pushToken;
|
String _pushToken;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -36,7 +36,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
);
|
);
|
||||||
_pushToken = await _firebaseMessaging.getToken();*/
|
_pushToken = await _firebaseMessaging.getToken();*/
|
||||||
if (_pushToken != null) {
|
if (_pushToken != null) {
|
||||||
api.request('PUT', '/accounts/pushToken', {'pushToken': _pushToken!});
|
api.request('PUT', '/accounts/pushToken', {'pushToken': _pushToken});
|
||||||
}
|
}
|
||||||
setState(() => _loading = false);
|
setState(() => _loading = false);
|
||||||
_controller.animateToPage(2, duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
|
_controller.animateToPage(2, duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
|
||||||
@ -63,7 +63,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text('You can create as many projects as you like. Upload weaving draft patterns, images, and other files to your projects to store and showcase your work.', style: TextStyle(color: Colors.white, fontSize: 13), textAlign: TextAlign.center),
|
Text('You can create as many projects as you like. Upload weaving draft patterns, images, and other files to your projects to store and showcase your work.', style: TextStyle(color: Colors.white, fontSize: 13), textAlign: TextAlign.center),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
child: Text('OK, I know what projects are!'),
|
child: Text('OK, I know what projects are!'),
|
||||||
onPressed: () => _controller.animateToPage(1, duration: Duration(milliseconds: 500), curve: Curves.easeInOut),
|
onPressed: () => _controller.animateToPage(1, duration: Duration(milliseconds: 500), curve: Curves.easeInOut),
|
||||||
)
|
)
|
||||||
@ -84,12 +84,12 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text('We recommend enabling push notifications so you can keep up-to-date with your groups and projects.', style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
Text('We recommend enabling push notifications so you can keep up-to-date with your groups and projects.', style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
_loading ? CircularProgressIndicator() : SizedBox(width: 0),
|
_loading ? CircularProgressIndicator() : null,
|
||||||
_loading ? SizedBox(width: 5) : SizedBox(width: 0),
|
_loading ? SizedBox(width: 5) : null,
|
||||||
Text('What\'s next?'),
|
Text('What\'s next?'),
|
||||||
]),
|
].where((o) => o != null).toList()),
|
||||||
onPressed: _requestPushPermissions,
|
onPressed: _requestPushPermissions,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -107,7 +107,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text('You\'re ready to get started. If you have any questions or want to get in touch then just send us a quick tweet.', style: TextStyle(color: Colors.white, fontSize: 13), textAlign: TextAlign.center),
|
Text('You\'re ready to get started. If you have any questions or want to get in touch then just send us a quick tweet.', style: TextStyle(color: Colors.white, fontSize: 13), textAlign: TextAlign.center),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
child: Text('Let\'s go'),
|
child: Text('Let\'s go'),
|
||||||
onPressed: () => Navigator.of(context).pushNamedAndRemoveUntil('/home', (Route<dynamic> route) => false),
|
onPressed: () => Navigator.of(context).pushNamedAndRemoveUntil('/home', (Route<dynamic> route) => false),
|
||||||
),
|
),
|
||||||
|
@ -6,8 +6,86 @@ import 'dart:io';
|
|||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'object.dart';
|
import 'object.dart';
|
||||||
|
|
||||||
|
class _ProjectSettingsDialog extends StatelessWidget {
|
||||||
|
final Map<String,dynamic> _project;
|
||||||
|
final Function _onDelete;
|
||||||
|
final Function _onUpdateProject;
|
||||||
|
final Api api = Api();
|
||||||
|
_ProjectSettingsDialog(this._project, this._onDelete, this._onUpdateProject) {}
|
||||||
|
|
||||||
|
void _toggleVisibility(BuildContext context, bool checked) async {
|
||||||
|
var data = await api.request('PUT', '/projects/' + _project['owner']['username'] + '/' + _project['path'], {'visibility': checked ? 'private': 'public'});
|
||||||
|
if (data['success']) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
_onUpdateProject(data['payload']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deleteProject(BuildContext context, BuildContext modalContext) async {
|
||||||
|
var data = await api.request('DELETE', '/projects/' + _project['owner']['username'] + '/' + _project['path']);
|
||||||
|
if (data['success']) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
Navigator.pop(modalContext);
|
||||||
|
_onDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _confirmDeleteProject(BuildContext modalContext) {
|
||||||
|
showDialog(
|
||||||
|
context: modalContext,
|
||||||
|
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||||
|
title: new Text('Really delete this project?'),
|
||||||
|
content: new Text('This will remove any files and objects inside the project. This action cannot be undone.'),
|
||||||
|
actions: <Widget>[
|
||||||
|
CupertinoDialogAction(
|
||||||
|
isDefaultAction: true,
|
||||||
|
child: Text('No'),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
CupertinoDialogAction(
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: Text('Yes'),
|
||||||
|
onPressed: () => _deleteProject(context, modalContext),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CupertinoActionSheet(
|
||||||
|
title: Text('Manage this project'),
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('Cancel')
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(5.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CupertinoSwitch(
|
||||||
|
value: _project['visibility'] == 'private',
|
||||||
|
onChanged: (c) => _toggleVisibility(context, c),
|
||||||
|
),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
Text('Private project', style: Theme.of(context).textTheme.bodyText1),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
CupertinoActionSheetAction(
|
||||||
|
onPressed: () { _confirmDeleteProject(context); },
|
||||||
|
child: Text('Delete project'),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _ProjectScreenState extends State<ProjectScreen> {
|
class _ProjectScreenState extends State<ProjectScreen> {
|
||||||
final Function _onUpdate;
|
|
||||||
final Function _onDelete;
|
final Function _onDelete;
|
||||||
final picker = ImagePicker();
|
final picker = ImagePicker();
|
||||||
final Api api = Api();
|
final Api api = Api();
|
||||||
@ -16,7 +94,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
bool _creating = false;
|
bool _creating = false;
|
||||||
|
|
||||||
_ProjectScreenState(this._project, this._onUpdate, this._onDelete) { }
|
_ProjectScreenState(this._project, this._onDelete) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
@ -44,20 +122,8 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_project = project;
|
_project = project;
|
||||||
});
|
});
|
||||||
_onUpdate(project['_id'], project);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateObject(String id, Map<String,dynamic> update) {
|
|
||||||
List<dynamic> _newObjects = _objects.map((o) {
|
|
||||||
if (o['_id'] == id) {
|
|
||||||
o.addAll(update);
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}).toList();
|
|
||||||
setState(() {
|
|
||||||
_objects = _newObjects;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void _onDeleteObject(String id) {
|
void _onDeleteObject(String id) {
|
||||||
List<dynamic> _newObjects = _objects.where((p) => p['_id'] != id).toList();
|
List<dynamic> _newObjects = _objects.where((p) => p['_id'] != id).toList();
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -130,7 +196,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
showCupertinoModalPopup(context: context, builder: (BuildContext context) => settingsDialog);
|
showCupertinoModalPopup(context: context, builder: (BuildContext context) => settingsDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getMemoryImageBox(data, [bool? isMemory, bool? isNetwork]) {
|
Widget getImageBox(data, [bool isMemory, bool isNetwork]) {
|
||||||
return new AspectRatio(
|
return new AspectRatio(
|
||||||
aspectRatio: 1 / 1,
|
aspectRatio: 1 / 1,
|
||||||
child: new Container(
|
child: new Container(
|
||||||
@ -138,21 +204,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
image: new DecorationImage(
|
image: new DecorationImage(
|
||||||
fit: BoxFit.fitWidth,
|
fit: BoxFit.fitWidth,
|
||||||
alignment: FractionalOffset.topCenter,
|
alignment: FractionalOffset.topCenter,
|
||||||
image: new MemoryImage(data),
|
image: isMemory == true ? new MemoryImage(data) : new NetworkImage(data)
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Widget getNetworkImageBox(String url) {
|
|
||||||
return new AspectRatio(
|
|
||||||
aspectRatio: 1 / 1,
|
|
||||||
child: new Container(
|
|
||||||
decoration: new BoxDecoration(
|
|
||||||
image: new DecorationImage(
|
|
||||||
fit: BoxFit.fitWidth,
|
|
||||||
alignment: FractionalOffset.topCenter,
|
|
||||||
image: new NetworkImage(url),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -180,30 +232,17 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
|
|
||||||
if (object['isImage'] == true) {
|
if (object['isImage'] == true) {
|
||||||
type = 'Image';
|
type = 'Image';
|
||||||
if (object['url'] != null) {
|
leader = getImageBox(object['url']);
|
||||||
leader = getNetworkImageBox(object['url']!);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
leader = getIconBox(Icon(Icons.photo));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (object['type'] == 'pattern') {
|
else if (object['type'] == 'pattern' && object['preview'] != null) {
|
||||||
type = 'Weaving pattern';
|
type = 'Weaving pattern';
|
||||||
if (object['previewUrl'] != null) {
|
var dat = Uri.parse(object['preview']).data;
|
||||||
leader = getNetworkImageBox(object['previewUrl']!);
|
leader = getImageBox(dat.contentAsBytes(), true);
|
||||||
}
|
|
||||||
else {
|
|
||||||
leader = getIconBox(Icon(Icons.pattern));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (object['type'] == 'file') {
|
else if (object['type'] == 'file') {
|
||||||
type = 'File';
|
type = 'File';
|
||||||
leader = getIconBox(Icon(Icons.insert_drive_file));
|
leader = getIconBox(Icon(Icons.insert_drive_file));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
type = 'Unknown';
|
|
||||||
leader = getIconBox(Icon(Icons.file_present));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Card(
|
return new Card(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@ -211,7 +250,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => ObjectScreen(object, _project, _onUpdateObject, _onDeleteObject),
|
builder: (context) => ObjectScreen(object, _onDeleteObject),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -280,129 +319,8 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
|||||||
|
|
||||||
class ProjectScreen extends StatefulWidget {
|
class ProjectScreen extends StatefulWidget {
|
||||||
final Map<String,dynamic> _project;
|
final Map<String,dynamic> _project;
|
||||||
final Function _onUpdate;
|
|
||||||
final Function _onDelete;
|
final Function _onDelete;
|
||||||
ProjectScreen(this._project, this._onUpdate, this._onDelete) { }
|
ProjectScreen(this._project, this._onDelete) { }
|
||||||
@override
|
@override
|
||||||
_ProjectScreenState createState() => _ProjectScreenState(_project, _onUpdate, _onDelete);
|
_ProjectScreenState createState() => _ProjectScreenState(_project, _onDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ProjectSettingsDialog extends StatelessWidget {
|
|
||||||
final Map<String,dynamic> _project;
|
|
||||||
final Function _onDelete;
|
|
||||||
final Function _onUpdateProject;
|
|
||||||
final Api api = Api();
|
|
||||||
_ProjectSettingsDialog(this._project, this._onDelete, this._onUpdateProject) {}
|
|
||||||
|
|
||||||
void _renameProject(BuildContext context) async {
|
|
||||||
TextEditingController renameController = TextEditingController();
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text('Rename your project'),
|
|
||||||
content: TextField(
|
|
||||||
autofocus: true,
|
|
||||||
controller: renameController,
|
|
||||||
decoration: InputDecoration(hintText: "Enter a new name for the project"),
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: Text('CANCEL'),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text('OK'),
|
|
||||||
onPressed: () async {
|
|
||||||
print(renameController.text);
|
|
||||||
var data = await api.request('PUT', '/projects/' + _project['owner']['username'] + '/' + _project['path'], {'name': renameController.text});
|
|
||||||
if (data['success']) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
_onUpdateProject(data['payload']);
|
|
||||||
}
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _toggleVisibility(BuildContext context, bool checked) async {
|
|
||||||
var data = await api.request('PUT', '/projects/' + _project['owner']['username'] + '/' + _project['path'], {'visibility': checked ? 'private': 'public'});
|
|
||||||
if (data['success']) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
_onUpdateProject(data['payload']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _deleteProject(BuildContext context, BuildContext modalContext) async {
|
|
||||||
var data = await api.request('DELETE', '/projects/' + _project['owner']['username'] + '/' + _project['path']);
|
|
||||||
if (data['success']) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
Navigator.pop(modalContext);
|
|
||||||
_onDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _confirmDeleteProject(BuildContext modalContext) {
|
|
||||||
showDialog(
|
|
||||||
context: modalContext,
|
|
||||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
|
||||||
title: new Text('Really delete this project?'),
|
|
||||||
content: new Text('This will remove any files and objects inside the project. This action cannot be undone.'),
|
|
||||||
actions: <Widget>[
|
|
||||||
CupertinoDialogAction(
|
|
||||||
isDefaultAction: true,
|
|
||||||
child: Text('No'),
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
),
|
|
||||||
CupertinoDialogAction(
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: Text('Yes'),
|
|
||||||
onPressed: () => _deleteProject(context, modalContext),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return CupertinoActionSheet(
|
|
||||||
title: Text('Manage this project'),
|
|
||||||
cancelButton: CupertinoActionSheetAction(
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
child: Text('Cancel')
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(5.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
CupertinoSwitch(
|
|
||||||
value: _project['visibility'] == 'private',
|
|
||||||
onChanged: (c) => _toggleVisibility(context, c),
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Text('Private project', style: Theme.of(context).textTheme.bodyText1),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
CupertinoActionSheetAction(
|
|
||||||
onPressed: () { _renameProject(context); },
|
|
||||||
child: Text('Rename project'),
|
|
||||||
),
|
|
||||||
CupertinoActionSheetAction(
|
|
||||||
onPressed: () { _confirmDeleteProject(context); },
|
|
||||||
child: Text('Delete project'),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,164 +6,6 @@ import 'api.dart';
|
|||||||
import 'project.dart';
|
import 'project.dart';
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
|
|
||||||
class _ProjectsTabState extends State<ProjectsTab> {
|
|
||||||
List<dynamic> _projects = [];
|
|
||||||
bool _loading = false;
|
|
||||||
bool _creatingProject = false;
|
|
||||||
final Api api = Api();
|
|
||||||
|
|
||||||
@override
|
|
||||||
initState() {
|
|
||||||
super.initState();
|
|
||||||
getProjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void getProjects() async {
|
|
||||||
setState(() {
|
|
||||||
_loading = true;
|
|
||||||
});
|
|
||||||
var data = await api.request('GET', '/users/me/projects');
|
|
||||||
if (data['success'] == true) {
|
|
||||||
setState(() {
|
|
||||||
_projects = data['payload']['projects'];
|
|
||||||
_loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onCreatingProject() {
|
|
||||||
setState(() {
|
|
||||||
_creatingProject = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void _onCreateProject(newProject) {
|
|
||||||
List<dynamic> _newProjects = _projects;
|
|
||||||
_newProjects.insert(0, newProject);
|
|
||||||
setState(() {
|
|
||||||
_projects = _newProjects;
|
|
||||||
_creatingProject = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onUpdateProject(String id, Map<String,dynamic> update) {
|
|
||||||
List<dynamic> _newProjects = _projects.map((p) {
|
|
||||||
if (p['_id'] == id) {
|
|
||||||
p.addAll(update);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}).toList();
|
|
||||||
setState(() {
|
|
||||||
_projects = _newProjects;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onDeleteProject(String id) {
|
|
||||||
List<dynamic> _newProjects = _projects.where((p) => p['_id'] != id).toList();
|
|
||||||
setState(() {
|
|
||||||
_projects = _newProjects;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void showNewProjectDialog() async {
|
|
||||||
Widget simpleDialog = new _NewProjectDialog(_onCreatingProject, _onCreateProject);
|
|
||||||
showDialog(context: context, builder: (BuildContext context) => simpleDialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildProjectCard(Map<String,dynamic> project) {
|
|
||||||
String description = project['description'] != null ? project['description'].replaceAll("\n", " ") : '';
|
|
||||||
if (description != null && description.length > 80) {
|
|
||||||
description = description.substring(0, 77) + '...';
|
|
||||||
}
|
|
||||||
if (project['visibility'] == 'public') {
|
|
||||||
description = "PUBLIC PROJECT\n" + description;
|
|
||||||
}
|
|
||||||
else description = "PRIVATE PROJECT\n" + description;
|
|
||||||
return new Card(
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => ProjectScreen(project, _onUpdateProject, _onDeleteProject),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
new ListTile(
|
|
||||||
leading: Icon(Icons.folder_open),
|
|
||||||
trailing: Icon(Icons.keyboard_arrow_right),
|
|
||||||
title: Text(project['name'] != null ? project['name'] : 'Untitled project'),
|
|
||||||
subtitle: Text(description),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Your Projects'),
|
|
||||||
actions: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.info_outline),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => SettingsScreen(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
),
|
|
||||||
body: _loading ?
|
|
||||||
Container(
|
|
||||||
margin: const EdgeInsets.all(10.0),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: CircularProgressIndicator()
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
margin: const EdgeInsets.all(10.0),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: (_projects != null && _projects.length > 0) ?
|
|
||||||
ListView.builder(
|
|
||||||
itemCount: _projects.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return buildProjectCard(_projects[index]);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
:
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text('Create your first project', style: TextStyle(fontSize: 20), textAlign: TextAlign.center),
|
|
||||||
Image(image: AssetImage('assets/reading.png'), width: 300),
|
|
||||||
Text('Projects contain all the files and patterns that make up a piece of work. Create one using the + button below.', textAlign: TextAlign.center),
|
|
||||||
])
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: showNewProjectDialog,
|
|
||||||
child: _creatingProject ? CircularProgressIndicator(backgroundColor: Colors.white) : Icon(Icons.add),
|
|
||||||
backgroundColor: Colors.pink[500],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProjectsTab extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_ProjectsTabState createState() => _ProjectsTabState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _NewProjectDialogState extends State<_NewProjectDialog> {
|
class _NewProjectDialogState extends State<_NewProjectDialog> {
|
||||||
final TextEditingController _newProjectNameController = TextEditingController();
|
final TextEditingController _newProjectNameController = TextEditingController();
|
||||||
final Function _onStart;
|
final Function _onStart;
|
||||||
@ -239,4 +81,156 @@ class _NewProjectDialog extends StatefulWidget {
|
|||||||
_NewProjectDialog(this._onStart, this._onComplete) {}
|
_NewProjectDialog(this._onStart, this._onComplete) {}
|
||||||
@override
|
@override
|
||||||
_NewProjectDialogState createState() => _NewProjectDialogState(_onStart, _onComplete);
|
_NewProjectDialogState createState() => _NewProjectDialogState(_onStart, _onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ProjectsTabState extends State<ProjectsTab> {
|
||||||
|
List<dynamic> _projects = [];
|
||||||
|
bool _loading = false;
|
||||||
|
bool _creatingProject = false;
|
||||||
|
final Api api = Api();
|
||||||
|
|
||||||
|
@override
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
getProjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void getProjects() async {
|
||||||
|
setState(() {
|
||||||
|
_loading = true;
|
||||||
|
});
|
||||||
|
var data = await api.request('GET', '/users/me/projects');
|
||||||
|
if (data['success'] == true) {
|
||||||
|
setState(() {
|
||||||
|
_projects = data['payload']['projects'];
|
||||||
|
_loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCreatingProject() {
|
||||||
|
setState(() {
|
||||||
|
_creatingProject = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void _onCreateProject(newProject) {
|
||||||
|
List<dynamic> _newProjects = _projects;
|
||||||
|
_newProjects.insert(0, newProject);
|
||||||
|
setState(() {
|
||||||
|
_projects = _newProjects;
|
||||||
|
_creatingProject = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onDeleteProject(String id) {
|
||||||
|
List<dynamic> _newProjects = _projects.where((p) => p['_id'] != id).toList();
|
||||||
|
setState(() {
|
||||||
|
_projects = _newProjects;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void showNewProjectDialog() async {
|
||||||
|
Widget simpleDialog = new _NewProjectDialog(_onCreatingProject, _onCreateProject);
|
||||||
|
showDialog(context: context, builder: (BuildContext context) => simpleDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildProjectCard(Map<String,dynamic> project) {
|
||||||
|
String description = project['description'] != null ? project['description'] : '';
|
||||||
|
if (description != null && description.length > 80) {
|
||||||
|
description = description.substring(0, 77) + '...';
|
||||||
|
}
|
||||||
|
return new Card(
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ProjectScreen(project, _onDeleteProject),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
new ListTile(
|
||||||
|
leading: Icon(Icons.folder_open),
|
||||||
|
trailing: Icon(Icons.keyboard_arrow_right),
|
||||||
|
title: Text(project['name'] != null ? project['name'] : 'Untitled project'),
|
||||||
|
subtitle: Text(description.replaceAll("\n", " ")),
|
||||||
|
),
|
||||||
|
/*ButtonBar(
|
||||||
|
children: <Widget>[
|
||||||
|
FlatButton(
|
||||||
|
child: const Text('VIEW'),
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),*/
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('Your Projects'),
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.info_outline),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SettingsScreen(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
body: _loading ?
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.all(10.0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: CircularProgressIndicator()
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
margin: const EdgeInsets.all(10.0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: (_projects != null && _projects.length > 0) ?
|
||||||
|
ListView.builder(
|
||||||
|
itemCount: _projects.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return buildProjectCard(_projects[index]);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
:
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('Create your first project', style: TextStyle(fontSize: 20), textAlign: TextAlign.center),
|
||||||
|
Image(image: AssetImage('assets/reading.png'), width: 300),
|
||||||
|
Text('Projects contain all the files and patterns that make up a piece of work. Create one using the + button below.', textAlign: TextAlign.center),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: showNewProjectDialog,
|
||||||
|
child: _creatingProject ? CircularProgressIndicator(backgroundColor: Colors.white) : Icon(Icons.add),
|
||||||
|
backgroundColor: Colors.pink[500],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProjectsTab extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ProjectsTabState createState() => _ProjectsTabState();
|
||||||
|
}
|
||||||
|
@ -97,9 +97,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
onPressed: () => _submit(context),
|
onPressed: () => _submit(context),
|
||||||
//color: Colors.pink,
|
color: Colors.pink,
|
||||||
child: _registering ? SizedBox(height: 20, width: 20, child:CircularProgressIndicator(backgroundColor: Colors.white)) : Text("Register",
|
child: _registering ? SizedBox(height: 20, width: 20, child:CircularProgressIndicator(backgroundColor: Colors.white)) : Text("Register",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(color: Colors.white, fontSize: 15)
|
style: TextStyle(color: Colors.white, fontSize: 15)
|
||||||
|
@ -31,11 +31,11 @@ class SettingsScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
FlatButton(
|
||||||
child: Text('Cancel'),
|
child: Text('Cancel'),
|
||||||
onPressed: () { Navigator.of(context).pop(); }
|
onPressed: () { Navigator.of(context).pop(); }
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
RaisedButton(
|
||||||
child: Text('Delete Account'),
|
child: Text('Delete Account'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Api api = Api();
|
Api api = Api();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class Store extends ChangeNotifier {
|
class Store extends ChangeNotifier {
|
||||||
String? apiToken;
|
String apiToken;
|
||||||
|
|
||||||
void setToken(String? newToken) {
|
void setToken(String newToken) {
|
||||||
apiToken = newToken;
|
apiToken = newToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class _UserScreenState extends State<UserScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String? created;
|
String created;
|
||||||
if (_user['createdAt'] != null) {
|
if (_user['createdAt'] != null) {
|
||||||
DateTime createdAt = DateTime.parse(_user['createdAt']);
|
DateTime createdAt = DateTime.parse(_user['createdAt']);
|
||||||
created = DateFormat('MMMM y').format(createdAt);
|
created = DateFormat('MMMM y').format(createdAt);
|
||||||
@ -68,7 +68,7 @@ class _UserScreenState extends State<UserScreen> {
|
|||||||
Text(_user['location'])
|
Text(_user['location'])
|
||||||
]) : SizedBox(height: 1),
|
]) : SizedBox(height: 1),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text('Member' + (created != null ? (' since ' + created!) : ''),
|
Text('Member' + (created != null ? (' since ' + created) : ''),
|
||||||
style: TextStyle(color: Colors.grey[500])
|
style: TextStyle(color: Colors.grey[500])
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
|
@ -1,182 +1,167 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
_flutterfire_internals:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: _flutterfire_internals
|
|
||||||
sha256: "9ebe81588e666f7e2b21309f2b5653bd9642d7f27fd0a6894278d2ff40cb9481"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.2"
|
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.7"
|
version: "3.2.1"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.3.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.10.0"
|
version: "2.8.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.0"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.0"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
|
chewie:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: chewie
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
chewie_audio:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: chewie_audio
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.0"
|
version: "1.15.0"
|
||||||
convert:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: convert
|
|
||||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.1"
|
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cross_file
|
name: cross_file
|
||||||
sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.3+4"
|
version: "0.3.2"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.1"
|
||||||
csslib:
|
csslib:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: csslib
|
name: csslib
|
||||||
sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.17.3"
|
version: "0.17.1"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.4"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.2.0"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "1.1.2"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file
|
name: file
|
||||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.4"
|
version: "6.1.2"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: e9b36b391690cf329c6fb1de220045e97c13784c303820cd33962319580a56c6
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.13.1"
|
version: "1.13.1"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_platform_interface
|
name: firebase_core_platform_interface
|
||||||
sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.0"
|
version: "4.2.5"
|
||||||
firebase_core_web:
|
firebase_core_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: "8c0f4c87d20e2d001a5915df238c1f9c88704231f591324205f5a5d2a7740a45"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0"
|
version: "1.6.1"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging
|
name: firebase_messaging
|
||||||
sha256: a01d7b9eb43a4bad54a411edb2b4124089d88eab029191893e83c39e18ab19f7
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.6.2"
|
version: "11.2.8"
|
||||||
firebase_messaging_platform_interface:
|
firebase_messaging_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_platform_interface
|
name: firebase_messaging_platform_interface
|
||||||
sha256: c2fef3e30fbfa3a71d74477df102d1c2f5aad860bb68bb4086b0af3b12abedf3
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.5.2"
|
version: "3.2.1"
|
||||||
firebase_messaging_web:
|
firebase_messaging_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_web
|
name: firebase_messaging_web
|
||||||
sha256: "8d280f0110ca4946b9863e578b9879874066ac486ffa596a609aab329fb6fa7e"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.2"
|
version: "2.2.9"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -186,26 +171,44 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_html
|
name: flutter_html
|
||||||
sha256: "02ad69e813ecfc0728a455e4bf892b9379983e050722b1dce00192ee2e41d1ee"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0-beta.2"
|
version: "2.2.1"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_launcher_icons
|
name: flutter_launcher_icons
|
||||||
sha256: "559c600f056e7c704bd843723c21e01b5fba47e8824bd02422165bcc02a5de1d"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.3"
|
version: "0.9.2"
|
||||||
|
flutter_layout_grid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_layout_grid
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
flutter_math_fork:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_math_fork
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.15"
|
version: "2.0.5"
|
||||||
|
flutter_svg:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_svg
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.23.0+1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -216,270 +219,251 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
fluttertoast:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fluttertoast
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "8.0.9"
|
||||||
html:
|
html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: html
|
name: html
|
||||||
sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.15.3"
|
version: "0.15.0"
|
||||||
http:
|
http:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.6"
|
version: "0.13.4"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.0"
|
||||||
image:
|
image:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "02bafd3b4f399bfeb10034deba9753d93b55ce41cd0c4d3d8b355626f80e5b32"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
image_picker:
|
image_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker
|
name: image_picker
|
||||||
sha256: "9978d3510af4e6a902e545ce19229b926e6de6a1828d6134d3aab2e129a4d270"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.7+5"
|
version: "0.8.4+10"
|
||||||
image_picker_android:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: image_picker_android
|
|
||||||
sha256: "3083c3a3245adf9f3eb7bacf0eaa6a1f087dd538fab73a13a2f7907602601692"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.8.6+19"
|
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_for_web
|
name: image_picker_for_web
|
||||||
sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.12"
|
version: "2.1.6"
|
||||||
image_picker_ios:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: image_picker_ios
|
|
||||||
sha256: d779210bda268a03b57e923fb1e410f32f5c5e708ad256348bcbf1f44f558fd0
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.8.7+4"
|
|
||||||
image_picker_platform_interface:
|
image_picker_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_platform_interface
|
name: image_picker_platform_interface
|
||||||
sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.6.3"
|
version: "2.4.4"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.17.0"
|
version: "0.17.0"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.5"
|
version: "0.6.3"
|
||||||
list_counter:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: list_counter
|
|
||||||
sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.13"
|
version: "0.12.11"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.1.3"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.7.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: nested
|
name: nested
|
||||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
numerus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: numerus
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.8.0"
|
||||||
|
path_drawing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_drawing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.1+1"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.11"
|
version: "2.1.5"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.0.3"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.7"
|
version: "2.0.5"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: petitparser
|
name: petitparser
|
||||||
sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.0"
|
version: "4.4.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: platform
|
name: platform
|
||||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: plugin_platform_interface
|
name: plugin_platform_interface
|
||||||
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.2"
|
||||||
pointycastle:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pointycastle
|
|
||||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.7.3"
|
|
||||||
process:
|
process:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: process
|
name: process
|
||||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.4"
|
version: "4.2.4"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.5"
|
version: "6.0.2"
|
||||||
|
quiver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quiver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1+1"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.0.13"
|
||||||
shared_preferences_android:
|
shared_preferences_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.0.11"
|
||||||
shared_preferences_foundation:
|
shared_preferences_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_ios
|
||||||
sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.1.0"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_linux
|
name: shared_preferences_linux
|
||||||
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.1.0"
|
||||||
|
shared_preferences_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
shared_preferences_platform_interface:
|
shared_preferences_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_platform_interface
|
name: shared_preferences_platform_interface
|
||||||
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.0.0"
|
||||||
shared_preferences_web:
|
shared_preferences_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_web
|
name: shared_preferences_web
|
||||||
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.0.3"
|
||||||
shared_preferences_windows:
|
shared_preferences_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_windows
|
name: shared_preferences_windows
|
||||||
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.1.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -489,162 +473,254 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.8.1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.0"
|
version: "1.10.0"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.0"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.1.0"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.0"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.16"
|
version: "0.4.8"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.0"
|
||||||
url_launcher:
|
url_launcher:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.11"
|
version: "6.0.20"
|
||||||
url_launcher_android:
|
url_launcher_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.35"
|
version: "6.0.15"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_ios
|
name: url_launcher_ios
|
||||||
sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.4"
|
version: "6.0.15"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_linux
|
name: url_launcher_linux
|
||||||
sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.0"
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_macos
|
name: url_launcher_macos
|
||||||
sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.0"
|
||||||
url_launcher_platform_interface:
|
url_launcher_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_platform_interface
|
name: url_launcher_platform_interface
|
||||||
sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.0.5"
|
||||||
url_launcher_web:
|
url_launcher_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_web
|
name: url_launcher_web
|
||||||
sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.17"
|
version: "2.0.9"
|
||||||
url_launcher_windows:
|
url_launcher_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_windows
|
name: url_launcher_windows
|
||||||
sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.6"
|
version: "3.0.0"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.1"
|
||||||
|
very_good_analysis:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: very_good_analysis
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
|
video_player:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: video_player
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.19"
|
||||||
|
video_player_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: video_player_android
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
|
video_player_avfoundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: video_player_avfoundation
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
|
video_player_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: video_player_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.0"
|
||||||
|
video_player_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: video_player_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.7"
|
||||||
|
wakelock:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.1+1"
|
||||||
|
wakelock_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.0"
|
||||||
|
wakelock_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0"
|
||||||
|
wakelock_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.0"
|
||||||
|
wakelock_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: wakelock_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
|
webview_flutter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.8.0"
|
||||||
|
webview_flutter_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_android
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.8.3"
|
||||||
|
webview_flutter_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.1"
|
||||||
|
webview_flutter_wkwebview:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_wkwebview
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.1"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.4"
|
version: "2.4.1"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "0.2.0+1"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xml
|
name: xml
|
||||||
sha256: "80d494c09849dc3f899d227a78c30c5b949b985ededf884cb3f3bcd39f4b447a"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.4.1"
|
version: "5.3.1"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.19.0 <3.0.0"
|
dart: ">=2.16.0 <3.0.0"
|
||||||
flutter: ">=3.3.0"
|
flutter: ">=2.10.0"
|
||||||
|
@ -15,25 +15,25 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.1.0+8
|
version: 1.0.2+7
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cupertino_icons: ^1.0.4
|
cupertino_icons: ^1.0.3
|
||||||
http: ^0.13.4
|
http: ^0.13.3
|
||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.11
|
||||||
provider: ^6.0.3
|
provider: ^6.0.1
|
||||||
url_launcher: ^6.1.2
|
url_launcher: ^6.0.17
|
||||||
flutter_html: ^3.0.0-alpha.3
|
flutter_html: ^2.2.1
|
||||||
intl: ^0.17.0
|
intl: ^0.17.0
|
||||||
image_picker: ^0.8.5+3
|
image_picker: ^0.8.4
|
||||||
flutter_launcher_icons: ^0.9.0
|
flutter_launcher_icons: ^0.9.0
|
||||||
firebase_messaging: ^14.4.0
|
firebase_messaging: ^11.2.3
|
||||||
#fluttertoast: ^8.0.9
|
fluttertoast: ^8.0.9
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -6,26 +6,4 @@ export const uploads = {
|
|||||||
}, success, fail) {
|
}, success, fail) {
|
||||||
api.authenticatedRequest('GET', `/uploads/file/request?name=${name}&size=${size}&type=${type}&forType=${forType}&forId=${forId}`, null, success, fail);
|
api.authenticatedRequest('GET', `/uploads/file/request?name=${name}&size=${size}&type=${type}&forType=${forType}&forId=${forId}`, null, success, fail);
|
||||||
},
|
},
|
||||||
uploadFile(forType, forId, name, file, success, fail) {
|
|
||||||
uploads.generateFileUploadRequest({
|
|
||||||
forType, forId, name, size: file.size, type: file.type || 'image/png',
|
|
||||||
}, (response) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('PUT', response.signedRequest);
|
|
||||||
xhr.setRequestHeader('Content-Type', file.type);
|
|
||||||
xhr.onreadystatechange = () => {
|
|
||||||
if (xhr.readyState === 4) {
|
|
||||||
if (xhr.status === 200) {
|
|
||||||
// We pass back the original file name so it can be displayed nicely
|
|
||||||
success && success({ storedName: response.fileName, name: file.name, type: 'file' });
|
|
||||||
} else if (onError) {
|
|
||||||
fail && fail({ message: 'Unable to upload file' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.send(file);
|
|
||||||
}, (err) => {
|
|
||||||
fail && fail(err);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ export default function PatternCard({ object, project, user }) {
|
|||||||
if (!object) return null;
|
if (!object) return null;
|
||||||
return (
|
return (
|
||||||
<Card raised key={object._id} style={{ cursor: 'pointer' }} as={Link} to={`/${user?.username}/${project?.path}/${object._id}`}>
|
<Card raised key={object._id} style={{ cursor: 'pointer' }} as={Link} to={`/${user?.username}/${project?.path}/${object._id}`}>
|
||||||
<div style={{ height: 200, backgroundImage: `url(${object.previewUrl})`, backgroundSize: 'cover', backgroundPosition: 'top right', position: 'relative' }}>
|
<div style={{ height: 200, backgroundImage: `url(${object.preview})`, backgroundSize: 'cover', backgroundPosition: 'top right', position: 'relative' }}>
|
||||||
{user &&
|
{user &&
|
||||||
<div style={{position: 'absolute', top: 5, left: 5, padding: '3px 6px', background: 'rgba(250,250,250,0.8)', borderRadius: 5}}>
|
<div style={{position: 'absolute', top: 5, left: 5, padding: '3px 6px', background: 'rgba(250,250,250,0.8)', borderRadius: 5}}>
|
||||||
<UserChip user={user} />
|
<UserChip user={user} />
|
||||||
|
@ -8,6 +8,7 @@ import utils from '../../../utils/utils.js';
|
|||||||
import DiscoverCard from '../../includes/DiscoverCard';
|
import DiscoverCard from '../../includes/DiscoverCard';
|
||||||
import PatternCard from '../../includes/PatternCard';
|
import PatternCard from '../../includes/PatternCard';
|
||||||
import PatternLoader from '../../includes/PatternLoader';
|
import PatternLoader from '../../includes/PatternLoader';
|
||||||
|
import DraftPreview from '../projects/objects/DraftPreview';
|
||||||
|
|
||||||
export default function Explore() {
|
export default function Explore() {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
@ -104,9 +104,9 @@ function ObjectList({ compact }) {
|
|||||||
{object.isImage &&
|
{object.isImage &&
|
||||||
<div style={{width:40, height:40, backgroundImage:`url(${utils.resizeUrl(object.url, 50)})`, backgroundSize:'cover', backgroundPosition:'center center'}} />
|
<div style={{width:40, height:40, backgroundImage:`url(${utils.resizeUrl(object.url, 50)})`, backgroundSize:'cover', backgroundPosition:'center center'}} />
|
||||||
}
|
}
|
||||||
{object.type === 'pattern' && (object.previewUrl
|
{object.type === 'pattern' && (object.preview
|
||||||
? (
|
? (
|
||||||
<div style={{ height: 40, width:40, backgroundImage: `url(${object.previewUrl})`, backgroundSize: 'cover', backgroundPosition: 'top right' }}
|
<div style={{ height: 40, width:40, backgroundImage: `url(${object.preview})`, backgroundSize: 'cover', backgroundPosition: 'top right' }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: <div style={{ height: 40, width:40, backgroundImage: `url(${logoGreyShort})`, backgroundSize: '50px' }} />
|
: <div style={{ height: 40, width:40, backgroundImage: `url(${logoGreyShort})`, backgroundSize: '50px' }} />
|
||||||
@ -145,9 +145,9 @@ function ObjectList({ compact }) {
|
|||||||
{filteredObjects.map((object, index) => (
|
{filteredObjects.map((object, index) => (
|
||||||
<Card raised key={object._id} style={{ cursor: 'pointer' }} as={Link} to={`/${fullProjectPath}/${object._id}`}>
|
<Card raised key={object._id} style={{ cursor: 'pointer' }} as={Link} to={`/${fullProjectPath}/${object._id}`}>
|
||||||
{object.type === 'pattern'
|
{object.type === 'pattern'
|
||||||
&& (object.previewUrl
|
&& (object.preview
|
||||||
? (
|
? (
|
||||||
<div style={{ height: 200, backgroundImage: `url(${object.previewUrl})`, backgroundSize: 'cover', backgroundPosition: 'top right' }}
|
<div style={{ height: 200, backgroundImage: `url(${object.preview})`, backgroundSize: 'cover', backgroundPosition: 'top right' }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: <div style={{ height: 200, backgroundImage: `url(${logoGreyShort})`, backgroundSize: '50px' }} />
|
: <div style={{ height: 200, backgroundImage: `url(${logoGreyShort})`, backgroundSize: '50px' }} />
|
||||||
|
@ -85,7 +85,7 @@ function ObjectViewer() {
|
|||||||
|
|
||||||
const downloadDrawdownImage = (object) => {
|
const downloadDrawdownImage = (object) => {
|
||||||
const element = document.createElement('a');
|
const element = document.createElement('a');
|
||||||
element.setAttribute('href', object.previewUrl);
|
element.setAttribute('href', object.preview);
|
||||||
element.setAttribute('download', `${object.name.replace(/ /g, '_')}-drawdown.png`);
|
element.setAttribute('download', `${object.name.replace(/ /g, '_')}-drawdown.png`);
|
||||||
element.style.display = 'none';
|
element.style.display = 'none';
|
||||||
document.body.appendChild(element);
|
document.body.appendChild(element);
|
||||||
@ -118,10 +118,10 @@ function ObjectViewer() {
|
|||||||
<Helmet title={`${object.name || 'Project Item'} | ${project?.name || 'Project'}`} />
|
<Helmet title={`${object.name || 'Project Item'} | ${project?.name || 'Project'}`} />
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'end' }}>
|
<div style={{ display: 'flex', justifyContent: 'end' }}>
|
||||||
{object.type === 'pattern' && (project.user === (user && user._id) || project.openSource || object.previewUrl) && <>
|
{object.type === 'pattern' && (project.user === (user && user._id) || project.openSource || object.preview) && <>
|
||||||
<Dropdown direction='left' icon={null} trigger={<Button size='small' secondary icon='download' content='Download pattern' loading={downloading} disabled={downloading}/>}>
|
<Dropdown direction='left' icon={null} trigger={<Button size='small' secondary icon='download' content='Download pattern' loading={downloading} disabled={downloading}/>}>
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
{object.previewUrl &&
|
{object.preview &&
|
||||||
<Dropdown.Item onClick={e => downloadDrawdownImage(object)} content='Download drawdown as an image' icon='file outline' />
|
<Dropdown.Item onClick={e => downloadDrawdownImage(object)} content='Download drawdown as an image' icon='file outline' />
|
||||||
}
|
}
|
||||||
{(project.user === (user && user._id) || project.openSource) &&
|
{(project.user === (user && user._id) || project.openSource) &&
|
||||||
|
@ -7,7 +7,6 @@ import styled from 'styled-components';
|
|||||||
import ElementPan from '../../../includes/ElementPan';
|
import ElementPan from '../../../includes/ElementPan';
|
||||||
import HelpLink from '../../../includes/HelpLink';
|
import HelpLink from '../../../includes/HelpLink';
|
||||||
import Tour, { ReRunTour } from '../../../includes/Tour';
|
import Tour, { ReRunTour } from '../../../includes/Tour';
|
||||||
import util from '../../../../utils/utils.js';
|
|
||||||
|
|
||||||
import Warp from './Warp';
|
import Warp from './Warp';
|
||||||
import Weft from './Weft';
|
import Weft from './Weft';
|
||||||
@ -57,10 +56,9 @@ function Draft() {
|
|||||||
|
|
||||||
const saveObject = () => {
|
const saveObject = () => {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
util.generatePatternPreview(object, previewUrl => {
|
const canvas = document.getElementsByClassName('drawdown')[0];
|
||||||
dispatch(actions.objects.update(objectId, 'previewUrl', previewUrl));
|
|
||||||
});
|
|
||||||
const newObject = Object.assign({}, object);
|
const newObject = Object.assign({}, object);
|
||||||
|
newObject.preview = canvas.toDataURL();
|
||||||
newObject.pattern = pattern;
|
newObject.pattern = pattern;
|
||||||
api.objects.update(objectId, newObject, (o) => {
|
api.objects.update(objectId, newObject, (o) => {
|
||||||
toast.success('Pattern saved');
|
toast.success('Pattern saved');
|
||||||
|
@ -3,7 +3,6 @@ import { useDispatch } from 'react-redux';
|
|||||||
import { Loader } from 'semantic-ui-react';
|
import { Loader } from 'semantic-ui-react';
|
||||||
import actions from '../../../../actions';
|
import actions from '../../../../actions';
|
||||||
import api from '../../../../api';
|
import api from '../../../../api';
|
||||||
import util from '../../../../utils/utils.js';
|
|
||||||
|
|
||||||
import ElementPan from '../../../includes/ElementPan';
|
import ElementPan from '../../../includes/ElementPan';
|
||||||
import { StyledPattern } from '../../../main/projects/objects/Draft';
|
import { StyledPattern } from '../../../main/projects/objects/Draft';
|
||||||
@ -18,6 +17,18 @@ function DraftPreview({ object }) {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const objectId = object?._id;
|
const objectId = object?._id;
|
||||||
|
|
||||||
|
const generatePreview = useCallback(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const c = document.getElementsByClassName('drawdown')[0];
|
||||||
|
const preview = c?.toDataURL();
|
||||||
|
if (preview) {
|
||||||
|
api.objects.update(objectId, { preview }, () => {
|
||||||
|
dispatch(actions.objects.update(objectId, 'preview', preview));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}, [dispatch, objectId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(actions.objects.updateEditor({ tool: 'pan' }));
|
dispatch(actions.objects.updateEditor({ tool: 'pan' }));
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -25,17 +36,10 @@ function DraftPreview({ object }) {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
if (o.pattern && o.pattern.warp) {
|
if (o.pattern && o.pattern.warp) {
|
||||||
setPattern(o.pattern);
|
setPattern(o.pattern);
|
||||||
// Generate the preview if not yet set (e.g. if from uploaded WIF)
|
if (!o.preview) generatePreview();
|
||||||
if (!o.previewUrl) {
|
|
||||||
setTimeout(() => {
|
|
||||||
util.generatePatternPreview(object, previewUrl => {
|
|
||||||
dispatch(actions.objects.update(objectId, 'previewUrl', previewUrl));
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, err => setLoading(false));
|
}, err => setLoading(false));
|
||||||
}, [dispatch, objectId]);
|
}, [dispatch, objectId, generatePreview]);
|
||||||
|
|
||||||
const unifyCanvas = useCallback(() => {
|
const unifyCanvas = useCallback(() => {
|
||||||
if (!pattern) return;
|
if (!pattern) return;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { createConfirmation } from 'react-confirm';
|
import { createConfirmation } from 'react-confirm';
|
||||||
import ConfirmModal from '../components/includes/ConfirmModal';
|
import ConfirmModal from '../components/includes/ConfirmModal';
|
||||||
import api from '../api';
|
|
||||||
|
|
||||||
import avatar1 from '../images/avatars/1.png';
|
import avatar1 from '../images/avatars/1.png';
|
||||||
import avatar2 from '../images/avatars/2.png';
|
import avatar2 from '../images/avatars/2.png';
|
||||||
@ -104,18 +103,6 @@ const utils = {
|
|||||||
if (IMAGE_SERVER) return `${import.meta.env.VITE_IMAGINARY_URL}/resize?width=${width}&url=${url}`;
|
if (IMAGE_SERVER) return `${import.meta.env.VITE_IMAGINARY_URL}/resize?width=${width}&url=${url}`;
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
generatePatternPreview(object, callback) {
|
|
||||||
const c = document.getElementsByClassName('drawdown')[0];
|
|
||||||
c?.toBlob(blob => {
|
|
||||||
if (blob) {
|
|
||||||
api.uploads.uploadFile('project', object.project, `preview-${object._id}.png`, blob, response => {
|
|
||||||
api.objects.update(object._id, { preview: response.storedName }, ({ previewUrl }) => {
|
|
||||||
callback && callback(previewUrl);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
|
Loading…
Reference in New Issue
Block a user