aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2023-05-20 16:43:21 -0600
committerIván Ávalos <avalos@disroot.org>2023-05-20 16:43:21 -0600
commitcd8f22959e62c0b7b191e64f4ecfec53cba9f364 (patch)
tree9e40717d4e7b5c18694ab65558acda65875f817b
parent3a3af285a7460a7e2f6850b9a8dd7465492163f6 (diff)
downloadlinkchat-cd8f22959e62c0b7b191e64f4ecfec53cba9f364.tar.gz
linkchat-cd8f22959e62c0b7b191e64f4ecfec53cba9f364.tar.bz2
linkchat-cd8f22959e62c0b7b191e64f4ecfec53cba9f364.zip
Se añade autenticación y onboarding
-rw-r--r--assets/heart.json1
-rw-r--r--assets/loading.gifbin0 -> 126404 bytes
-rw-r--r--assets/logo.pngbin0 -> 27033 bytes
-rw-r--r--assets/logo.svg114
-rw-r--r--assets/share.json1
-rw-r--r--assets/star.json1
-rw-r--r--lib/firebase/auth.dart83
-rw-r--r--lib/firebase/storage.dart16
-rw-r--r--lib/main.dart67
-rw-r--r--lib/providers/theme_provider.dart25
-rw-r--r--lib/routes.dart15
-rw-r--r--lib/screens/dashboard_screen.dart100
-rw-r--r--lib/screens/login_screen.dart171
-rw-r--r--lib/screens/onboarding_screen.dart103
-rw-r--r--lib/screens/register_screen.dart178
-rw-r--r--lib/settings/preferences.dart35
-rw-r--r--lib/settings/themes.dart16
-rw-r--r--lib/widgets/avatar_picker.dart61
-rw-r--r--lib/widgets/loading_modal_widget.dart22
-rw-r--r--lib/widgets/responsive.dart34
-rw-r--r--pubspec.lock298
-rw-r--r--pubspec.yaml12
22 files changed, 1325 insertions, 28 deletions
diff --git a/assets/heart.json b/assets/heart.json
new file mode 100644
index 0000000..c6ab231
--- /dev/null
+++ b/assets/heart.json
@@ -0,0 +1 @@
+{"v":"5.6.5","fr":30,"ip":0,"op":10,"w":32,"h":32,"nm":"heart","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"heart","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.001,0.001],[2.148,-2.148],[0.001,0],[0,0],[0,0],[2.149,-2.148],[-2.148,-2.148],[0,0],[0,0],[0,0],[0,0],[2.147,2.148]],"o":[[-2.147,-2.148],[0,0],[0,0],[0,0],[-2.148,-2.148],[-2.148,2.148],[0,0],[0,0],[0,0],[0,0],[2.148,-2.147],[-0.001,-0.001]],"v":[[8.84,-7.236],[1.061,-7.237],[1.059,-7.236],[-0.001,-6.176],[-1.061,-7.236],[-8.84,-7.236],[-8.84,0.544],[-7.781,1.604],[-0.001,9.385],[7.779,1.604],[8.84,0.544],[8.842,-7.234]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[12,11.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":5,"s":[90,90]},{"t":10,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"heart Fill","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.001,0.001],[2.148,-2.148],[0.001,0],[0,0],[0,0],[2.149,-2.148],[-2.148,-2.148],[0,0],[0,0],[0,0],[0,0],[2.147,2.148]],"o":[[-2.147,-2.148],[0,0],[0,0],[0,0],[-2.148,-2.148],[-2.148,2.148],[0,0],[0,0],[0,0],[0,0],[2.148,-2.147],[-0.001,-0.001]],"v":[[8.84,-7.236],[1.061,-7.237],[1.059,-7.236],[-0.001,-6.176],[-1.061,-7.236],[-8.84,-7.236],[-8.84,0.544],[-7.781,1.604],[-0.001,9.385],[7.779,1.604],[8.84,0.544],[8.842,-7.234]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[12,11.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":2,"s":[50,50]},{"t":10,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[0]},{"t":7,"s":[100]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"fill","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/assets/loading.gif b/assets/loading.gif
new file mode 100644
index 0000000..bfbb814
--- /dev/null
+++ b/assets/loading.gif
Binary files differ
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..95ff20f
--- /dev/null
+++ b/assets/logo.png
Binary files differ
diff --git a/assets/logo.svg b/assets/logo.svg
new file mode 100644
index 0000000..8408237
--- /dev/null
+++ b/assets/logo.svg
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="1000"
+ height="500"
+ viewBox="0 0 1000 500"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="logo.svg"
+ inkscape:export-filename="logo.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="0.81"
+ inkscape:cx="610.49383"
+ inkscape:cy="297.53086"
+ inkscape:window-width="1920"
+ inkscape:window-height="1007"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="text788" />
+ <defs
+ id="defs2">
+ <rect
+ x="42.379542"
+ y="41.345895"
+ width="907.5424"
+ height="407.25707"
+ id="rect790" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ aria-label="LinkChat"
+ transform="translate(10.336473,118.86945)"
+ id="text788"
+ style="font-size:192px;font-family:'Space Mono';-inkscape-font-specification:'Space Mono';white-space:pre;shape-inside:url(#rect790);fill:#e1ccff;stroke:#e5d5ff;stroke-width:0.96;stroke-linecap:round;stroke-linejoin:round">
+ <rect
+ style="fill:#ffffff;stroke:#0000ff;stroke-width:0;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none"
+ id="rect2472"
+ width="1000"
+ height="500"
+ x="-10.336473"
+ y="-118.86945"
+ ry="100.61729" />
+ <rect
+ style="fill:#0000ff;stroke:#0000ff;stroke-width:0;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none"
+ id="rect2278"
+ width="115.88485"
+ height="258.42935"
+ x="229.36703"
+ y="55.198029"
+ ry="57.942425"
+ transform="rotate(3.169253)" />
+ <path
+ d="M 77.823572,197.33021 V 61.010216 H 109.11957 V 169.87421 h 58.944 l -1.92,27.456 z"
+ style="font-weight:bold;font-family:Livvic;-inkscape-font-specification:'Livvic Bold';fill:#000000;stroke-width:0;stroke-dasharray:none"
+ id="path1431" />
+ <path
+ d="m 207.80749,99.602214 v 97.727996 h -29.376 V 99.602214 Z m -14.784,-11.52 q -8.448,0 -13.44,-5.184 -4.992,-5.183999 -4.992,-12.287998 0,-7.104 4.8,-12.288 4.992,-5.184001 13.632,-5.184001 8.448,0 13.44,5.184001 4.992,5.184 4.992,12.288 0,7.103999 -4.992,12.287998 -4.992,5.184 -13.44,5.184 z"
+ style="font-weight:bold;font-family:Livvic;-inkscape-font-specification:'Livvic Bold';fill:#000000;stroke-width:0;stroke-dasharray:none"
+ id="path1433" />
+ <path
+ d="m 245.85039,183.18211 -0.78588,-73.20796 h 21.86484 l -1.00694,15.67938 c 2.97285,-5.37031 6.76084,-9.49393 11.36396,-12.37089 4.69903,-2.97285 9.92549,-4.45927 15.6794,-4.45927 8.72675,0 15.24785,2.97284 19.56327,8.91854 4.31543,5.8498 6.4252,14.28887 6.3293,25.31718 l -2.15607,47.84111 c -2.01242,24.4271 -28.39343,41.81942 -50.76684,25.7014 l 0.12177,-15.95577 c 18.01466,16.80944 32.17774,3.88606 31.02669,-10.0134 l -0.23425,-45.99102 c 0.0959,-4.98671 -0.67129,-8.77469 -2.30157,-11.36395 -1.53437,-2.68516 -4.02772,-4.02774 -7.48007,-4.02774 -2.87696,0 -5.51416,0.86309 -7.91162,2.58926 -2.39747,1.63027 -4.50723,4.45928 -6.32929,8.48701 -1.72617,4.02774 -3.11671,9.54189 -4.17159,16.54248 -1.05488,7.00057 -1.63027,5.2864 -1.72617,15.83522 -9.64592,0.26196 -16.14831,2.61962 -21.07894,10.47842 z"
+ style="font-weight:bold;font-size:192px;font-family:Livvic;-inkscape-font-specification:'Livvic Bold';white-space:pre;shape-inside:url(#rect790);fill:#ffffff;stroke:#e5d5ff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
+ id="path1435-6-2-8-2-7"
+ sodipodi:nodetypes="cccccsccccccccsccscc" />
+ <path
+ d="m 308.74435,218.84372 0.78588,73.20796 h -21.86484 l 1.00694,-15.67938 c -2.97285,5.37031 -6.76084,9.49394 -11.36396,12.3709 -4.69903,2.97284 -9.92549,4.45927 -15.6794,4.45927 -8.72675,0 -15.24785,-2.97285 -19.56327,-8.91854 -4.31543,-5.84982 -6.4252,-14.28888 -6.3293,-25.31718 l 2.15607,-47.84112 c 2.01242,-24.42711 28.39343,-41.81942 50.76683,-25.7014 L 288.53754,201.38 c -18.01466,-16.80944 -32.17774,-3.88606 -31.02669,10.01339 l 0.23425,45.99101 c -0.0959,4.98674 0.67129,8.77473 2.30156,11.36397 1.53437,2.68517 4.02773,4.02775 7.48008,4.02775 2.87696,0 5.51416,-0.86309 7.91162,-2.58927 2.39747,-1.63027 4.50722,-4.45927 6.32929,-8.48701 1.72617,-4.02774 3.11671,-9.54189 4.17158,-16.54247 1.05488,-7.00059 1.63028,-5.2864 1.72617,-15.83523 9.64592,-0.26196 16.14832,-2.61962 21.07895,-10.47842 z"
+ style="font-weight:bold;font-size:192px;font-family:Livvic;-inkscape-font-specification:'Livvic Bold';white-space:pre;shape-inside:url(#rect790);fill:#ffffff;stroke:#e5d5ff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
+ id="path1435-6-2-8-2-7-2"
+ sodipodi:nodetypes="cccccsccccccccsccscc" />
+ <path
+ d="M 349.88742,197.33021 V 55.250215 h 29.376 v 83.327995 l 36.288,-38.975996 h 34.944 l -44.16,47.231996 q 4.416,2.688 7.296,7.104 l 7.488,11.712 q 5.952,9.216 16.704,9.216 5.76,0 10.944,-2.88 l 6.336,21.696 q -5.376,3.072 -11.136,4.416 -5.568,1.344 -11.904,1.152 -12.48,-0.192 -20.736,-4.608 -8.064,-4.416 -14.592,-14.976 l -7.488,-11.712 q -2.688,-4.224 -4.992,-6.912 -2.304,-2.688 -4.992,-4.224 v 40.512 z"
+ style="font-weight:bold;font-family:Livvic;-inkscape-font-specification:'Livvic Bold';fill:#000000;stroke-width:0;stroke-dasharray:none"
+ id="path1437" />
+ <path
+ d="m 580.67157,170.64221 q -8.448,13.824 -23.232,21.312 -14.784,7.296 -32.832,7.296 -22.08,0 -37.824,-8.064 -15.552,-8.064 -24,-23.04 -8.256,-15.168 -8.256,-36.288 0,-21.696 9.216,-38.015996 9.216,-16.319999 25.536,-25.535998 16.512,-9.216 38.016,-9.216 18.816,0 31.68,6.912 13.056,6.912 21.888,20.927998 l -24,17.087996 q -4.608,-8.831996 -12.672,-12.863996 -8.064,-4.032 -17.28,-4.032 -12.096,0 -21.12,5.568 -9.024,5.568 -14.208,15.551996 -4.992,9.984 -4.992,23.04 0,19.008 9.984,29.568 9.984,10.56 28.224,10.56 9.792,0 18.432,-4.608 8.832,-4.8 14.208,-14.4 z"
+ style="fill:#0000ff;stroke-width:0;stroke-dasharray:none"
+ id="path1439" />
+ <path
+ d="M 589.50363,197.33021 V 55.250215 h 29.376 l 0.192,44.351999 -1.536,20.543996 q 5.952,-10.56 15.168,-16.32 9.408,-5.759996 20.736,-5.759996 17.472,0 26.112,11.903996 8.64,11.712 8.448,33.792 l -0.384,53.568 h -29.376 l 0.384,-51.456 q 0.192,-9.984 -3.072,-15.168 -3.072,-5.376 -9.984,-5.376 -5.76,0 -10.56,3.456 -4.8,3.264 -8.448,11.328 -3.456,8.064 -5.568,22.08 -2.112,14.016 -2.304,35.136 z"
+ style="fill:#0000ff;stroke-width:0;stroke-dasharray:none"
+ id="path1441" />
+ <path
+ d="m 805.11948,99.986214 v 97.343996 h -29.568 l 0.96,-14.592 q -10.56,16.512 -31.296,16.512 -13.056,0 -22.272,-5.952 -9.216,-5.952 -14.016,-16.512 -4.8,-10.56 -4.8,-24.192 0,-16.32 6.72,-28.608 6.72,-12.288 18.048,-19.008 11.328,-6.911996 25.344,-6.911996 9.216,0 16.32,3.839996 7.104,3.648 10.944,9.792 l 2.496,-11.711996 z m -48,23.615996 q -10.56,0 -16.704,7.872 -5.952,7.872 -5.952,20.16 0,10.56 4.608,16.32 4.8,5.76 12.864,5.76 9.792,0 16.704,-8.064 7.104,-8.064 7.104,-21.12 0,-9.792 -4.992,-15.36 -4.992,-5.568 -13.632,-5.568 z"
+ style="fill:#0000ff;stroke-width:0;stroke-dasharray:none"
+ id="path1443" />
+ <path
+ d="m 871.74348,199.25021 q -18.048,0 -28.608,-9.984 -10.56,-10.176 -10.368,-26.688 l 0.768,-38.592 h -16.128 V 99.602214 h 16.512 l 0.192,-19.968 h 29.184 l -0.192,19.968 h 30.528 v 24.383996 h -30.912 l -0.576,35.328 q 0,6.912 3.648,10.752 3.648,3.84 10.944,3.84 4.224,0 8.064,-0.96 4.032,-1.152 8.256,-4.224 l 8.448,22.464 q -9.792,8.064 -29.76,8.064 z"
+ style="fill:#0000ff;stroke-width:0;stroke-dasharray:none"
+ id="path1445" />
+ </g>
+ </g>
+</svg>
diff --git a/assets/share.json b/assets/share.json
new file mode 100644
index 0000000..80d845f
--- /dev/null
+++ b/assets/share.json
@@ -0,0 +1 @@
+{"v":"5.6.5","fr":30,"ip":0,"op":75,"w":32,"h":32,"nm":"share Final","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"share","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":30,"s":[16,16,0],"to":[-2,-1.167,0],"ti":[2,1.167,0]},{"t":44,"s":[4,9,0]}],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.657,0],[0,-1.657]],"o":[[0,-1.657],[1.657,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":15,"s":[87]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":15,"s":[86]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[6,10.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"t":15,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1 oval up","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.657,0],[0,1.657]],"o":[[0,1.657],[-1.657,0],[0,0]],"v":[[3,-1.5],[0,1.5],[-3,-1.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":15,"s":[13]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":15,"s":[13]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[6,13.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"t":15,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1 oval down","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.41,-1.99],[-3.41,1.99]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[100]},{"t":29,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[11.938,8.294],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1 line up","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.657,0],[0,-1.657],[1.656,0],[0.521,0.89],[0,0.551]],"o":[[1.656,0],[0,1.657],[-1.106,0],[-0.259,-0.444],[0,-1.657]],"v":[[0,-3],[3,0],[0,3],[-2.593,1.511],[-3,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"t":44,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[100]},{"t":44,"s":[50]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[18,4.747],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":-120,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2 up oval","np":3,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.415,-1.99],[3.415,1.99]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[0]},{"t":29,"s":[100]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[12.005,15.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1 line down","np":3,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.105,0],[0,-1.657],[1.657,0],[0,1.657],[-0.26,0.445]],"o":[[1.657,0],[0,1.657],[-1.657,0],[0,-0.551],[0.52,-0.889]],"v":[[0,-3],[3,0],[0,3],[-3,0],[-2.592,-1.512]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[18,19],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":-60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2 down oval","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.41,-1.99],[-3.41,1.99]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":44,"s":[100]},{"t":60,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[24,15.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"3 line up","np":3,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.415,-1.99],[3.415,1.99]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":44,"s":[0]},{"t":60,"s":[100]}],"ix":1},"e":{"a":0,"k":0,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[24.005,22.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"3 line down","np":3,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.657,0],[0,-1.657],[1.657,0],[0.521,0.89],[0,0.551]],"o":[[1.657,0],[0,1.657],[-1.106,0],[-0.259,-0.444],[0,-1.657]],"v":[[0,-3],[3,0],[0,3],[-2.593,1.511],[-3,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[50]},{"t":75,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[50]},{"t":75,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,11.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"3 oval up","np":3,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.106,0],[0,-1.657],[1.656,0],[0,1.657],[-0.259,0.444]],"o":[[1.656,0],[0,1.657],[-1.657,0],[0,-0.551],[0.521,-0.89]],"v":[[0,-3],[3,0],[0,3],[-3,0],[-2.593,-1.511]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[50]},{"t":75,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[50]},{"t":75,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30.031,26.028],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":120,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"3 oval down","np":3,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/assets/star.json b/assets/star.json
new file mode 100644
index 0000000..f95b2a5
--- /dev/null
+++ b/assets/star.json
@@ -0,0 +1 @@
+{"v":"5.6.5","fr":30,"ip":0,"op":10,"w":32,"h":32,"nm":"star","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"star","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,-9.51],[3.09,-3.25],[10,-2.24],[5,2.63],[6.18,9.51],[0,6.26],[-6.18,9.51],[-5,2.63],[-10,-2.24],[-3.09,-3.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[12,11.51],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":5,"s":[90,90]},{"t":10,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"star","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"star fill","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,-9.51],[3.09,-3.25],[10,-2.24],[5,2.63],[6.18,9.51],[0,6.26],[-6.18,9.51],[-5,2.63],[-10,-2.24],[-3.09,-3.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[12,11.51],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":2,"s":[50,50]},{"t":10,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[0]},{"t":7,"s":[100]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"star","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/lib/firebase/auth.dart b/lib/firebase/auth.dart
new file mode 100644
index 0000000..a876d5b
--- /dev/null
+++ b/lib/firebase/auth.dart
@@ -0,0 +1,83 @@
+import 'dart:io';
+
+import 'package:firebase_auth/firebase_auth.dart';
+import 'package:flutter/foundation.dart';
+
+import 'storage.dart';
+
+class Auth {
+ final FirebaseAuth _auth = FirebaseAuth.instance;
+ final GithubAuthProvider _githubProvider = GithubAuthProvider();
+ final GoogleAuthProvider _googleAuthProvider = GoogleAuthProvider();
+
+ User? get currentUser => _auth.currentUser;
+
+ Future<bool> createUserWithEmailAndPassword({
+ required String email,
+ required String password,
+ required String displayName,
+ required File avatar,
+ }) async {
+ try {
+ UserCredential cred = await _auth.createUserWithEmailAndPassword(
+ email: email,
+ password: password,
+ );
+ User? user = cred.user;
+ if (user != null) {
+ user.updateDisplayName(displayName);
+ user.updatePhotoURL(await Storage().uploadAvatar(user.uid, avatar));
+ }
+ return true;
+ } catch (e) {
+ if (kDebugMode) print(e);
+ return false;
+ }
+ }
+
+ Future<bool> signInWithEmailAndPassword({
+ required String email,
+ required String password,
+ }) async {
+ try {
+ UserCredential cred = await _auth.signInWithEmailAndPassword(
+ email: email,
+ password: password,
+ );
+ return cred.user?.emailVerified == true;
+ } catch (e) {
+ if (kDebugMode) print(e);
+ return false;
+ }
+ }
+
+ Future<bool> signInWithGoogle() async {
+ try {
+ await _auth.signInWithProvider(_googleAuthProvider);
+ return true;
+ } catch (e) {
+ if (kDebugMode) print(e);
+ return false;
+ }
+ }
+
+ Future<bool> signInWithGithub() async {
+ try {
+ await _auth.signInWithProvider(_githubProvider);
+ return true;
+ } catch (e) {
+ if (kDebugMode) print(e);
+ return false;
+ }
+ }
+
+ Future<bool> signOut() async {
+ try {
+ await _auth.signOut();
+ return true;
+ } catch (e) {
+ if (kDebugMode) print(e);
+ return false;
+ }
+ }
+}
diff --git a/lib/firebase/storage.dart b/lib/firebase/storage.dart
new file mode 100644
index 0000000..3e0c629
--- /dev/null
+++ b/lib/firebase/storage.dart
@@ -0,0 +1,16 @@
+import 'dart:io';
+
+import 'package:firebase_storage/firebase_storage.dart';
+import 'package:path/path.dart';
+
+class Storage {
+ final FirebaseStorage _storage = FirebaseStorage.instance;
+
+ Future<String> uploadAvatar(String userId, File file) async {
+ String filename = basename(file.path);
+ Reference ref = _storage.ref().child(userId).child(filename);
+ UploadTask task = ref.putFile(file);
+ await task.whenComplete(() => {});
+ return await ref.getDownloadURL();
+ }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 0d97e25..a0ff04a 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,45 +1,58 @@
+import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
-void main() {
- runApp(const MyApp());
+import 'providers/theme_provider.dart';
+import 'routes.dart';
+import 'settings/themes.dart';
+
+void main(List<String> args) async {
+ WidgetsFlutterBinding.ensureInitialized();
+ await Firebase.initializeApp();
+ return runApp(const MainContent());
}
-class MyApp extends StatelessWidget {
- const MyApp({super.key});
+class MainContent extends StatefulWidget {
+ const MainContent({super.key});
@override
- Widget build(BuildContext context) {
- return MaterialApp(
- title: 'LinkChat',
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
- useMaterial3: true,
- ),
- home: const MyHomePage(title: 'LinkChat'),
- );
- }
+ State<MainContent> createState() => _MainContentState();
}
-class MyHomePage extends StatefulWidget {
- const MyHomePage({super.key, required this.title});
+class _MainContentState extends State<MainContent> {
+ int contador = 0;
- final String title;
+ @override
+ void initState() {
+ super.initState();
+ contador = 0;
+ }
@override
- State<MyHomePage> createState() => _MyHomePageState();
+ Widget build(BuildContext context) {
+ return MultiProvider(
+ providers: [
+ ChangeNotifierProvider(create: (_) => ThemeProvider()),
+ ],
+ child: const LinkChat(),
+ );
+ }
}
-class _MyHomePageState extends State<MyHomePage> {
+class LinkChat extends StatelessWidget {
+ const LinkChat({super.key});
+
@override
Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- backgroundColor: Theme.of(context).colorScheme.inversePrimary,
- title: Text(widget.title),
- ),
- body: Center(
- child: Text(widget.title),
- ),
+ final ThemeProvider provider = context.watch<ThemeProvider>();
+ final ThemeData? theme = provider.theme;
+ provider.syncFromPrefs();
+ return MaterialApp(
+ theme: theme ?? ThemeSettings.lightTheme,
+ darkTheme: theme ?? ThemeSettings.darkTheme,
+ themeMode: ThemeMode.system,
+ routes: getApplicationRoutes(),
+ initialRoute: '/login',
);
}
}
diff --git a/lib/providers/theme_provider.dart b/lib/providers/theme_provider.dart
new file mode 100644
index 0000000..3a65731
--- /dev/null
+++ b/lib/providers/theme_provider.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/material.dart';
+
+import '../settings/preferences.dart';
+
+class ThemeProvider with ChangeNotifier {
+ bool synced = false;
+ ThemeData? _theme;
+
+ void syncFromPrefs() {
+ if (synced) return;
+ Preferences.getTheme().then((t) {
+ synced = true;
+ _theme = t;
+ notifyListeners();
+ });
+ }
+
+ ThemeData? get theme => _theme;
+
+ set theme(ThemeData? theme) {
+ Preferences.setTheme(theme);
+ _theme = theme;
+ notifyListeners();
+ }
+}
diff --git a/lib/routes.dart b/lib/routes.dart
new file mode 100644
index 0000000..9446a01
--- /dev/null
+++ b/lib/routes.dart
@@ -0,0 +1,15 @@
+import 'package:flutter/material.dart';
+
+import 'screens/dashboard_screen.dart';
+import 'screens/login_screen.dart';
+import 'screens/onboarding_screen.dart';
+import 'screens/register_screen.dart';
+
+Map<String, WidgetBuilder> getApplicationRoutes() {
+ return <String, WidgetBuilder>{
+ '/login': (BuildContext context) => const LoginScreen(),
+ '/register': (BuildContext context) => const RegisterScreen(),
+ '/onboard': (BuildContext context) => const OnboardingScreen(),
+ '/dash': (BuildContext context) => const DashboardScreen()
+ };
+}
diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart
new file mode 100644
index 0000000..cb31a58
--- /dev/null
+++ b/lib/screens/dashboard_screen.dart
@@ -0,0 +1,100 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../firebase/auth.dart';
+import '../providers/theme_provider.dart';
+import '../settings/themes.dart';
+
+class DashboardScreen extends StatefulWidget {
+ const DashboardScreen({super.key});
+
+ @override
+ State<DashboardScreen> createState() => _DashboardScreenState();
+}
+
+class _DashboardScreenState extends State<DashboardScreen> {
+ late Auth _auth;
+
+ @override
+ void initState() {
+ super.initState();
+ _auth = Auth();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final ThemeProvider themeProvider = context.watch<ThemeProvider>();
+ return Scaffold(
+ body: CustomScrollView(
+ slivers: [
+ SliverAppBar.large(
+ title: const Text('Inicio'),
+ ),
+ const SliverFillRemaining(
+ child: Placeholder(),
+ ),
+ ],
+ ),
+ drawer: Drawer(
+ child: ListView(
+ children: [
+ UserAccountsDrawerHeader(
+ currentAccountPicture: CircleAvatar(
+ backgroundImage: _auth.currentUser?.photoURL != null
+ ? NetworkImage(_auth.currentUser!.photoURL!)
+ : null,
+ ),
+ accountName: Text(_auth.currentUser?.displayName ?? "Lincite"),
+ accountEmail: _auth.currentUser?.email != null
+ ? Text(_auth.currentUser!.email!)
+ : null,
+ ),
+ ListTile(
+ title: const Text('Tema'),
+ trailing: SegmentedButton<ThemeData?>(
+ segments: [
+ const ButtonSegment<ThemeData?>(
+ value: null,
+ icon: Icon(Icons.brightness_auto),
+ ),
+ ButtonSegment<ThemeData?>(
+ value: ThemeSettings.lightTheme,
+ icon: const Icon(Icons.light_mode),
+ ),
+ ButtonSegment<ThemeData?>(
+ value: ThemeSettings.darkTheme,
+ icon: const Icon(Icons.dark_mode)),
+ ],
+ selected: <ThemeData?>{themeProvider.theme},
+ onSelectionChanged: ((Set<ThemeData?> newSelection) {
+ themeProvider.theme = newSelection.first;
+ }),
+ ),
+ ),
+ const Divider(),
+ ListTile(
+ title: const Text('Cerrar sesión'),
+ leading: const Icon(Icons.logout),
+ onTap: () => signOut(context),
+ )
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton.extended(
+ label: const Text('Nuevo'),
+ icon: const Icon(Icons.create),
+ onPressed: () {
+ Navigator.of(context).pushNamed('/new');
+ },
+ ),
+ );
+ }
+
+ void signOut(BuildContext context) {
+ _auth.signOut().then((success) {
+ if (success) {
+ Navigator.of(context).popUntil(ModalRoute.withName('/login'));
+ }
+ });
+ }
+}
diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart
new file mode 100644
index 0000000..44cef6f
--- /dev/null
+++ b/lib/screens/login_screen.dart
@@ -0,0 +1,171 @@
+import 'package:flutter/material.dart';
+import 'package:social_login_buttons/social_login_buttons.dart';
+
+import '../firebase/auth.dart';
+import '../widgets/loading_modal_widget.dart';
+import '../widgets/responsive.dart';
+
+class LoginScreen extends StatefulWidget {
+ const LoginScreen({super.key});
+
+ @override
+ State<LoginScreen> createState() => _LoginScreenState();
+}
+
+class _LoginScreenState extends State<LoginScreen>
+ with SingleTickerProviderStateMixin {
+ late AnimationController _controller;
+
+ final Auth _auth = Auth();
+
+ bool isLoading = false;
+
+ final padding = 16.0;
+ final spacer = const SizedBox(height: 16.0);
+
+ // TextField controllers
+ late TextEditingController _emailController;
+ late TextEditingController _passwordController;
+
+ @override
+ void initState() {
+ super.initState();
+ _emailController = TextEditingController();
+ _passwordController = TextEditingController();
+ _controller = AnimationController(vsync: this);
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose();
+ super.dispose();
+ }
+
+ Widget logoItc() => Padding(
+ padding: EdgeInsets.all(padding * 2),
+ child: Image.asset('assets/logo.png', height: 120.0),
+ );
+
+ Widget loginForm() => Column(
+ children: [
+ spacer,
+ Container(
+ width: double.infinity,
+ alignment: Alignment.centerLeft,
+ padding: EdgeInsets.symmetric(horizontal: padding),
+ child: Text(
+ 'Iniciar sesión',
+ style: Theme.of(context).textTheme.displaySmall,
+ textAlign: TextAlign.left,
+ ),
+ ),
+ Card(
+ margin: EdgeInsets.all(padding),
+ child: Padding(
+ padding: EdgeInsets.all(padding),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ TextField(
+ controller: _emailController,
+ decoration: const InputDecoration(
+ border: OutlineInputBorder(),
+ labelText: 'Correo electrónico',
+ hintText: 'test@example.com',
+ ),
+ keyboardType: TextInputType.emailAddress,
+ ),
+ spacer,
+ TextField(
+ controller: _passwordController,
+ obscureText: true,
+ decoration: const InputDecoration(
+ border: OutlineInputBorder(),
+ labelText: 'Contraseña',
+ ),
+ ),
+ spacer,
+ SocialLoginButton(
+ buttonType: SocialLoginButtonType.generalLogin,
+ text: 'Iniciar sesión',
+ backgroundColor: Theme.of(context).colorScheme.primary,
+ onPressed: () => onLoginClicked(context),
+ ),
+ spacer,
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pushNamed('/register');
+ },
+ child: const Text('Crear cuenta'),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+
+ void onLoginClicked(BuildContext context) {
+ _auth
+ .signInWithEmailAndPassword(
+ email: _emailController.text,
+ password: _passwordController.text,
+ )
+ .then((success) {
+ setState(() {
+ isLoading = false;
+ });
+ // TODO: checar si el resultado es true
+ Navigator.of(context).pushNamed('/dash');
+ });
+ }
+
+ void onGoogleLoginClicked(BuildContext context) {
+ _auth.signInWithGoogle().then((success) {
+ setState(() {
+ isLoading = false;
+ });
+ if (success) {
+ Navigator.of(context).pushNamed('/dash');
+ }
+ });
+ }
+
+ void onGithubLoginClicked(BuildContext context) {
+ _auth.signInWithGithub().then((success) {
+ setState(() {
+ isLoading = false;
+ });
+ if (success) {
+ Navigator.of(context).pushNamed('/dash');
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Stack(
+ children: [
+ SingleChildScrollView(
+ child: SafeArea(
+ child: Responsive(
+ mobile: Column(
+ children: [logoItc(), loginForm()],
+ ),
+ desktop: Row(
+ children: [
+ Expanded(child: logoItc()),
+ Expanded(child: loginForm()),
+ ],
+ ),
+ ),
+ ),
+ ),
+ isLoading ? const LoadingModal() : const SizedBox.shrink(),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/screens/onboarding_screen.dart b/lib/screens/onboarding_screen.dart
new file mode 100644
index 0000000..e1755c4
--- /dev/null
+++ b/lib/screens/onboarding_screen.dart
@@ -0,0 +1,103 @@
+import 'package:concentric_transition/concentric_transition.dart';
+import 'package:flutter/material.dart';
+import 'package:lottie/lottie.dart';
+
+import '../widgets/responsive.dart';
+
+class PageData {
+ final String title;
+ final String icon;
+ final MaterialColor bgColor;
+ final Color textColor;
+
+ const PageData({
+ required this.title,
+ required this.icon,
+ required this.bgColor,
+ required this.textColor,
+ });
+}
+
+class OnboardingScreen extends StatelessWidget {
+ const OnboardingScreen({super.key});
+
+ static const pages = [
+ PageData(
+ title: '¡Bienvenidx a LinkChat!',
+ icon: 'assets/star.json',
+ bgColor: Colors.deepPurple,
+ textColor: Colors.white,
+ ),
+ PageData(
+ title:
+ 'Una nueva experiencia de chat donde solo puedes compartir enlaces',
+ icon: 'assets/share.json',
+ bgColor: Colors.red,
+ textColor: Colors.white,
+ ),
+ PageData(
+ title: 'Guarda tus enlaces favoritos para verlos más tarde',
+ icon: 'assets/heart.json',
+ bgColor: Colors.green,
+ textColor: Colors.black,
+ ),
+ ];
+
+ Widget icon(PageData data) => CircleAvatar(
+ radius: 100.0,
+ backgroundColor: data.bgColor.shade200,
+ child: Lottie.asset(
+ data.icon,
+ height: 100.0,
+ fit: BoxFit.fill,
+ ),
+ );
+
+ Widget text(BuildContext context, PageData data) => Text(
+ data.title,
+ textAlign: TextAlign.center,
+ style: Theme.of(context)
+ .typography
+ .englishLike
+ .headlineMedium!
+ .copyWith(color: data.textColor),
+ );
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: ConcentricPageView(
+ colors: pages.map((PageData p) => p.bgColor).toList(),
+ itemCount: pages.length,
+ physics: const NeverScrollableScrollPhysics(),
+ itemBuilder: (int index) {
+ PageData data = pages[index];
+ return Center(
+ child: Padding(
+ padding: const EdgeInsets.all(15.0),
+ child: Responsive(
+ mobile: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ icon(data),
+ const SizedBox(height: 50.0),
+ text(context, data),
+ ],
+ ),
+ desktop: Row(
+ children: [
+ Expanded(child: icon(data)),
+ Expanded(child: text(context, data)),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ onFinish: () {
+ Navigator.of(context).pushNamed('/dash');
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/screens/register_screen.dart b/lib/screens/register_screen.dart
new file mode 100644
index 0000000..349cac0
--- /dev/null
+++ b/lib/screens/register_screen.dart
@@ -0,0 +1,178 @@
+import 'dart:io';
+
+import 'package:email_validator/email_validator.dart';
+import 'package:flutter/material.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:social_login_buttons/social_login_buttons.dart';
+
+import '../firebase/auth.dart';
+import '../widgets/avatar_picker.dart';
+import '../widgets/loading_modal_widget.dart';
+
+class RegisterScreen extends StatefulWidget {
+ const RegisterScreen({super.key});
+
+ @override
+ State<RegisterScreen> createState() => _RegisterScreenState();
+}
+
+class _RegisterScreenState extends State<RegisterScreen> {
+ bool isLoading = false;
+
+ final padding = 16.0;
+ final spacer = const SizedBox(height: 16.0);
+
+ XFile? _avatar;
+
+ // TextField controllers
+ late TextEditingController _nameController;
+ late TextEditingController _emailController;
+ late TextEditingController _passwordController;
+
+ final _formKey = GlobalKey<FormState>();
+
+ @override
+ void initState() {
+ super.initState();
+ _nameController = TextEditingController();
+ _emailController = TextEditingController();
+ _passwordController = TextEditingController();
+ }
+
+ bool validateForm() {
+ if (_formKey.currentState!.validate() && _avatar != null) {
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: CustomScrollView(
+ slivers: [
+ SliverAppBar.large(
+ title: const Text('Crear cuenta'),
+ ),
+ SliverFillRemaining(
+ child: Stack(
+ children: [
+ SingleChildScrollView(
+ child: Column(
+ children: [
+ spacer,
+ Card(
+ margin:
+ EdgeInsets.fromLTRB(padding, 0, padding, padding),
+ child: Padding(
+ padding: EdgeInsets.all(padding),
+ child: Form(
+ key: _formKey,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ AvatarPicker(
+ avatar: _avatar,
+ onAvatarPicked: (avatar) {
+ setState(() {
+ _avatar = avatar;
+ });
+ },
+ ),
+ spacer,
+ TextFormField(
+ controller: _nameController,
+ decoration: const InputDecoration(
+ border: OutlineInputBorder(),
+ labelText: 'Nombre',
+ hintText: 'Juan Pérez',
+ ),
+ keyboardType: TextInputType.name,
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return 'El nombre no debe estar vacío';
+ }
+ return null;
+ },
+ ),
+ spacer,
+ TextFormField(
+ controller: _emailController,
+ decoration: const InputDecoration(
+ border: OutlineInputBorder(),
+ labelText: 'Correo electrónico',
+ hintText: 'test@example.com',
+ ),
+ keyboardType: TextInputType.emailAddress,
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return 'El correo no debe estar vacío';
+ } else if (!EmailValidator.validate(
+ value)) {
+ return 'El formato del correo es inválido';
+ }
+ return null;
+ },
+ ),
+ spacer,
+ TextFormField(
+ controller: _passwordController,
+ obscureText: true,
+ decoration: const InputDecoration(
+ border: OutlineInputBorder(),
+ labelText: 'Contraseña',
+ ),
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return 'La contraseña no debe estar vacía';
+ }
+ return null;
+ },
+ ),
+ spacer,
+ SocialLoginButton(
+ buttonType:
+ SocialLoginButtonType.generalLogin,
+ text: 'Crear cuenta',
+ backgroundColor:
+ Theme.of(context).colorScheme.primary,
+ onPressed: () => onRegisterClicked(context),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ isLoading ? const LoadingModal() : const SizedBox.shrink(),
+ ],
+ ),
+ )
+ ],
+ ),
+ );
+ }
+
+ void onRegisterClicked(BuildContext context) {
+ setState(() {
+ isLoading = false;
+ if (validateForm()) {
+ Auth()
+ .createUserWithEmailAndPassword(
+ email: _emailController.text,
+ password: _passwordController.text,
+ displayName: _nameController.text,
+ avatar: File(_avatar!.path),
+ )
+ .then((success) {
+ if (success) {
+ Navigator.of(context).pushNamed('/onboard');
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/lib/settings/preferences.dart b/lib/settings/preferences.dart
new file mode 100644
index 0000000..3c0ef5d
--- /dev/null
+++ b/lib/settings/preferences.dart
@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+import '../settings/themes.dart';
+
+class Preferences {
+ static SharedPreferences? _prefs;
+
+ static Future<SharedPreferences> get prefs async {
+ _prefs ??= await SharedPreferences.getInstance();
+ return _prefs!;
+ }
+
+ static Future<ThemeData?> getTheme() async {
+ switch ((await prefs).getString('theme')) {
+ case 'light':
+ return ThemeSettings.lightTheme;
+ case 'dark':
+ return ThemeSettings.darkTheme;
+ }
+ return null;
+ }
+
+ static void setTheme(ThemeData? theme) {
+ prefs.then((p) {
+ if (theme == ThemeSettings.lightTheme) {
+ p.setString('theme', 'light');
+ } else if (theme == ThemeSettings.darkTheme) {
+ p.setString('theme', 'dark');
+ } else {
+ p.remove('theme');
+ }
+ });
+ }
+}
diff --git a/lib/settings/themes.dart b/lib/settings/themes.dart
new file mode 100644
index 0000000..bc489b7
--- /dev/null
+++ b/lib/settings/themes.dart
@@ -0,0 +1,16 @@
+import 'package:flutter/material.dart';
+
+class ThemeSettings {
+ static ThemeData lightTheme = ThemeData(
+ useMaterial3: true,
+ primaryColor: Colors.purple,
+ );
+
+ static ThemeData darkTheme = ThemeData.dark(
+ useMaterial3: true,
+ ).copyWith(
+ colorScheme: const ColorScheme.dark().copyWith(
+ primary: Colors.purple,
+ ),
+ );
+}
diff --git a/lib/widgets/avatar_picker.dart b/lib/widgets/avatar_picker.dart
new file mode 100644
index 0000000..bdfec6d
--- /dev/null
+++ b/lib/widgets/avatar_picker.dart
@@ -0,0 +1,61 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:image_picker/image_picker.dart';
+
+class AvatarPicker extends StatelessWidget {
+ final ImagePicker picker = ImagePicker();
+ final XFile? avatar;
+ final Function(XFile? avatar) onAvatarPicked;
+
+ AvatarPicker({
+ super.key,
+ required this.avatar,
+ required this.onAvatarPicked,
+ });
+
+ File? _getAvatarFile() {
+ return avatar == null ? null : File(avatar!.path);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ CircleAvatar(
+ radius: 50.0,
+ backgroundImage:
+ _getAvatarFile() == null ? null : FileImage(_getAvatarFile()!),
+ child: _getAvatarFile() == null
+ ? const Icon(Icons.person, size: 50.0)
+ : null,
+ ),
+ const SizedBox(width: 18.0),
+ Column(
+ children: [
+ FilledButton.icon(
+ icon: const Icon(Icons.camera_alt),
+ label: const Text('Cámara'),
+ onPressed: () {
+ picker.pickImage(source: ImageSource.camera).then((image) {
+ onAvatarPicked(image);
+ });
+ },
+ ),
+ const SizedBox(height: 16.0),
+ FilledButton.icon(
+ icon: const Icon(Icons.collections),
+ label: const Text('Galería'),
+ onPressed: () {
+ picker.pickImage(source: ImageSource.gallery).then((image) {
+ onAvatarPicked(image);
+ });
+ },
+ )
+ ],
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/widgets/loading_modal_widget.dart b/lib/widgets/loading_modal_widget.dart
new file mode 100644
index 0000000..c19a411
--- /dev/null
+++ b/lib/widgets/loading_modal_widget.dart
@@ -0,0 +1,22 @@
+import 'package:flutter/material.dart';
+
+class LoadingModal extends StatelessWidget {
+ const LoadingModal({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return const Center(
+ child: Card(
+ shape: CircleBorder(),
+ child: Padding(
+ padding: EdgeInsets.all(20.0),
+ child: SizedBox(
+ width: 200,
+ height: 200,
+ child: CircularProgressIndicator(value: null),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widgets/responsive.dart b/lib/widgets/responsive.dart
new file mode 100644
index 0000000..f5f2739
--- /dev/null
+++ b/lib/widgets/responsive.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+
+class Responsive extends StatelessWidget {
+ final Widget mobile;
+ final Widget? tablet;
+ final Widget desktop;
+
+ const Responsive({
+ super.key,
+ required this.mobile,
+ this.tablet,
+ required this.desktop,
+ });
+
+ static bool isMobile(BuildContext context) =>
+ MediaQuery.of(context).size.width < 576;
+
+ static bool isTablet(BuildContext context) =>
+ MediaQuery.of(context).size.width >= 576 &&
+ MediaQuery.of(context).size.width <= 992;
+
+ static bool isDesktop(BuildContext context) =>
+ MediaQuery.of(context).size.width > 992;
+
+ @override
+ Widget build(BuildContext context) {
+ if (isDesktop(context)) {
+ return desktop;
+ } else if (tablet != null && isTablet(context)) {
+ return tablet!;
+ }
+ return mobile;
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 5e79557..28080bd 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
+ archive:
+ dependency: transitive
+ description:
+ name: archive
+ sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.3.7"
async:
dependency: transitive
description:
@@ -73,6 +81,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.1"
+ concentric_transition:
+ dependency: "direct main"
+ description:
+ name: concentric_transition
+ sha256: "825191221e4bc6a0cfaf00adbc5cd2cc1333970f61311bce52021f1f68e0a891"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.3"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.1"
+ cross_file:
+ dependency: transitive
+ description:
+ name: cross_file
+ sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.3+4"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.3"
+ email_validator:
+ dependency: "direct main"
+ description:
+ name: email_validator
+ sha256: e9a90f27ab2b915a27d7f9c2a7ddda5dd752d6942616ee83529b686fc086221b
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.17"
fake_async:
dependency: transitive
description:
@@ -81,6 +129,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.2"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.4"
firebase_auth:
dependency: "direct main"
description:
@@ -153,6 +217,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.5.1"
+ firebase_storage:
+ dependency: "direct main"
+ description:
+ name: firebase_storage
+ sha256: "89ff2dfd353f953fb2bbbe04359ea1a46d643944f310cfed22dadf352fc16976"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.2.1"
+ firebase_storage_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_storage_platform_interface
+ sha256: c06ccd21c3ed20da6128629ab7d525f7b613caddfcd5466ba4a1ff58655261ac
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.4.1"
+ firebase_storage_web:
+ dependency: transitive
+ description:
+ name: firebase_storage_web
+ sha256: "26a039f211b226fc216f9f06f13402bdf08661edb7c42cb1de3bd236afbbbf75"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.6.1"
flutter:
dependency: "direct main"
description: flutter
@@ -166,6 +254,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
+ flutter_plugin_android_lifecycle:
+ dependency: transitive
+ description:
+ name: flutter_plugin_android_lifecycle
+ sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.15"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -176,6 +272,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.13.6"
http_parser:
dependency: transitive
description:
@@ -184,6 +288,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
+ image_picker:
+ dependency: "direct main"
+ description:
+ name: image_picker
+ sha256: "9978d3510af4e6a902e545ce19229b926e6de6a1828d6134d3aab2e129a4d270"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.8.7+5"
+ image_picker_android:
+ dependency: transitive
+ description:
+ name: image_picker_android
+ sha256: c2f3c66400649bd132f721c88218945d6406f693092b2f741b79ae9cdb046e59
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.8.6+16"
+ image_picker_for_web:
+ dependency: transitive
+ description:
+ name: image_picker_for_web
+ sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.12"
+ 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:
+ dependency: transitive
+ description:
+ name: image_picker_platform_interface
+ sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.6.3"
js:
dependency: transitive
description:
@@ -200,6 +344,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
+ lottie:
+ dependency: "direct main"
+ description:
+ name: lottie
+ sha256: "23522951540d20a57a60202ed7022e6376bed206a4eee1c347a91f58bd57eb9f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
matcher:
dependency: transitive
description:
@@ -224,14 +376,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
- path:
+ nested:
dependency: transitive
description:
+ name: nested
+ sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ path:
+ dependency: "direct main"
+ description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.10"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.6"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.6"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
@@ -240,11 +432,99 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
+ pointycastle:
+ dependency: transitive
+ description:
+ name: pointycastle
+ sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.7.3"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.4"
+ provider:
+ dependency: "direct main"
+ description:
+ name: provider
+ sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.5"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.2"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
+ social_login_buttons:
+ dependency: "direct main"
+ description:
+ name: social_login_buttons
+ sha256: "052b88f1a9fed69430097093c02ed738a0fbf4c5fa4b0ed0ce4e8aa3caf592de"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.7"
source_span:
dependency: transitive
description:
@@ -309,6 +589,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
+ win32:
+ dependency: transitive
+ description:
+ name: win32
+ sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.4"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
sdks:
dart: ">=3.0.1 <4.0.0"
flutter: ">=3.3.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 4fac976..1f079b3 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,9 +10,18 @@ dependencies:
flutter:
sdk: flutter
+ provider: ^6.0.5
+ shared_preferences: ^2.1.1
+ lottie: ^2.3.2
+ concentric_transition: ^1.0.3
+ social_login_buttons: ^1.0.7
+ image_picker: ^0.8.7
+ path: ^1.8.3
+ email_validator: ^2.1.17
firebase_core: ^2.13.0
firebase_auth: ^4.6.1
firebase_messaging: ^14.6.1
+ firebase_storage: ^11.2.1
cloud_firestore: ^4.7.1
dev_dependencies:
@@ -22,3 +31,6 @@ dev_dependencies:
flutter:
uses-material-design: true
+
+ assets:
+ - assets/