diff --git a/apps/mobile_app/android/build/reports/problems/problems-report.html b/apps/mobile_app/android/build/reports/problems/problems-report.html
index e302409b..b6d599f6 100644
--- a/apps/mobile_app/android/build/reports/problems/problems-report.html
+++ b/apps/mobile_app/android/build/reports/problems/problems-report.html
@@ -650,7 +650,7 @@ code + .copy-button {
diff --git a/apps/mobile_app/assets/shared/animations/shooting_photo.json b/apps/mobile_app/assets/shared/animations/shooting_photo.json
new file mode 100644
index 00000000..8cef6b7e
--- /dev/null
+++ b/apps/mobile_app/assets/shared/animations/shooting_photo.json
@@ -0,0 +1 @@
+{"v":"5.7.6","fr":25,"ip":0,"op":75,"w":320,"h":200,"nm":"02_Photos","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Camera null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":45,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[0]},{"t":61,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":3,"s":[160,264,0],"to":[0,-30,0],"ti":[0,25.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[160,84,0],"to":[0,-25.667,0],"ti":[0,-4.333,0]},{"t":25,"s":[160,110,0]}],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Flash","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":27,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":45,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":51,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":59,"s":[100]},{"t":61,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[76,2,0],"ix":2,"l":2},"a":{"a":0,"k":[186,52,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":25,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29,"s":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":33,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":37,"s":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":41,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":45,"s":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":49,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":53,"s":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":57,"s":[0,0,100]},{"t":61,"s":[200,200,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,8.284],[8.284,0],[0,-8.284]],"o":[[-8.284,0],[0,8.284],[8.284,0],[0,-8.284]],"v":[[201,52],[186,37],[171,52],[186,67]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":25,"op":75,"st":25,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Lens mask","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,87,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,87,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[300,200],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.768626972273,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,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":[0,0],"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":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Lens","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-14.912],[14.912,0],[0,14.912],[-14.912,0]],"o":[[0,14.912],[-14.912,0],[0,-14.912],[14.912,0]],"v":[[27,0],[0,27],[-27,0],[0,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[160,100],"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":"Lens small stroke","np":2,"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,-9.389],[9.389,0],[0,9.389],[-9.389,0]],"o":[[0,9.389],[-9.389,0],[0,-9.389],[9.389,0]],"v":[[17,0],[0,17],[-17,0],[0,-17]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[160,100],"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":"Lens small bg","np":2,"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,-22.091],[22.092,0],[0,22.092],[-22.091,0]],"o":[[0,22.092],[-22.091,0],[0,-22.091],[22.092,0]],"v":[[40,0],[0,40],[-40,0],[0,-40]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[160,100],"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":"Lens big stroke","np":2,"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":[[0,-14.912],[14.912,0],[0,14.912],[-14.912,0]],"o":[[0,14.912],[-14.912,0],[0,-14.912],[14.912,0]],"v":[[27,0],[0,27],[-27,0],[0,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[160,100],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":25,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":27,"s":[50,50]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":29,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":33,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":35,"s":[50,50]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":37,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":41,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":43,"s":[50,50]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":45,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":49,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":51,"s":[50,50]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":53,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":57,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":59,"s":[50,50]},{"t":61,"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":"Lens medium blue bg","np":2,"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,-14.912],[14.912,0],[0,14.912],[-14.912,0]],"o":[[0,14.912],[-14.912,0],[0,-14.912],[14.912,0]],"v":[[27,0],[0,27],[-27,0],[0,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.188235297799,0.188235297799,0.188235297799,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":[160,100],"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":"Lens medium grey bg","np":2,"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":[[0,20.396],[-19.729,2.462],[1.694,0],[0,-22.091],[-22.091,0],[-1.64,0.205]],"o":[[0,-20.397],[-1.64,-0.204],[-22.091,0],[0,22.092],[1.694,0],[-19.729,-2.462]],"v":[[-12.5,0],[22.5,-39.678],[17.5,-40],[-22.5,0],[17.5,40],[22.5,39.678]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.847000002394,0.847000002394,0.847000002394,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":[142.5,100],"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":"Lens shadow","np":2,"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,-22.091],[22.092,0],[0,22.092],[-22.091,0]],"o":[[0,22.092],[-22.091,0],[0,-22.091],[22.092,0]],"v":[[40,0],[0,40],[-40,0],[0,-40]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.917999985639,0.917999985639,0.917999985639,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":[160,100],"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":"Lens bg","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Camera Mask","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,87,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,87,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[300,200],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.768626972273,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,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":[0,0],"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":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Camera","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[182,52],[190,52]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"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":"Line","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.522,0],[0,0],[0,5.522],[0,0],[-5.523,0],[0,0],[0,-5.523],[0,0]],"o":[[0,0],[-5.523,0],[0,0],[0,-5.523],[0,0],[5.522,0],[0,0],[0,5.522]],"v":[[50,40],[-50,40],[-60,30],[-60,-30],[-50,-40],[50,-40],[60,-30],[60,30]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[160,100],"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":"Camera stroke","np":2,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,5.522],[0,0],[-5.523,0],[0,0],[0,-5.523],[0,0],[-5.523,0],[0,0]],"o":[[0,0],[0,-5.523],[0,0],[-5.523,0],[0,0],[0,5.522],[0,0],[-5.523,0]],"v":[[2,30],[2,-30],[12,-40],[-2,-40],[-12,-30],[-12,30],[-2,40],[12,40]],"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":20,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[112,100],"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":"Camera shadow","np":2,"cix":2,"bm":0,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.522,0],[0,0],[0,5.522],[0,0],[0,0],[0,0]],"o":[[0,0],[-5.523,0],[0,0],[0,0],[0,0],[0,5.522]],"v":[[50,13.715],[-50,13.715],[-60,3.715],[-60,-13.715],[60,-13.715],[60,3.715]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[160,126.285],"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":"Camera bottom stroke","np":2,"cix":2,"bm":0,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.522,0],[0,0],[0,5.522],[0,0],[0,0],[0,0]],"o":[[0,0],[-5.523,0],[0,0],[0,0],[0,0],[0,5.522]],"v":[[50,13.715],[-50,13.715],[-60,3.715],[-60,-13.715],[60,-13.715],[60,3.715]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211999990426,0.211999990426,0.26699999641,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":[160,126.285],"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":"Camera bottom bg","np":2,"cix":2,"bm":0,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.522,0],[0,0],[0,5.522],[0,0],[-5.523,0],[0,0],[0,-5.523],[0,0]],"o":[[0,0],[-5.523,0],[0,0],[0,-5.523],[0,0],[5.522,0],[0,0],[0,5.522]],"v":[[50,40],[-50,40],[-60,30],[-60,-30],[-50,-40],[50,-40],[60,-30],[60,30]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.26699999641,0.26699999641,0.317999985639,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":[160,100],"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":"Camera bg","np":2,"cix":2,"bm":0,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.36,0],[0,0],[-0.969,-2.153]],"o":[[0,0],[0,0],[0.969,-2.153],[0,0],[2.36,0],[0,0]],"v":[[22,8],[-22,8],[-16.392,-4.462],[-10.921,-8],[10.921,-8],[16.392,-4.462]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[186,52],"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":"Flash stroke","np":2,"cix":2,"bm":0,"ix":17,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.36,0],[0,0],[0.969,-2.153],[0,0],[0,0],[0,0]],"o":[[0,0],[-2.36,0],[0,0],[0,0],[0,0],[0.969,-2.153]],"v":[[10.54,-8],[0.54,-8],[-4.932,-4.462],[-10.54,8],[-0.54,8],[5.068,-4.462]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.847000002394,0.847000002394,0.847000002394,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":[174.54,52],"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":"Flash shadow","np":2,"cix":2,"bm":0,"ix":18,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.36,0],[0,0],[-0.969,-2.153]],"o":[[0,0],[0,0],[0.969,-2.153],[0,0],[2.36,0],[0,0]],"v":[[22,8],[-22,8],[-16.392,-4.462],[-10.921,-8],[10.921,-8],[16.392,-4.462]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.917999985639,0.917999985639,0.917999985639,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":[186,52],"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":"Flash bg","np":2,"cix":2,"bm":0,"ix":19,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Button Mask","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,87,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,87,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[300,200],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.768626972273,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,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":[0,0],"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":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Button","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":25,"s":[13,6,0],"to":[0,1.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":27,"s":[13,14,0],"to":[0,0,0],"ti":[0,1.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":29,"s":[13,6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":33,"s":[13,6,0],"to":[0,1.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[13,14,0],"to":[0,0,0],"ti":[0,1.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":37,"s":[13,6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":41,"s":[13,6,0],"to":[0,1.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":43,"s":[13,14,0],"to":[0,0,0],"ti":[0,1.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":45,"s":[13,6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":49,"s":[13,6,0],"to":[0,1.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":51,"s":[13,14,0],"to":[0,0,0],"ti":[0,1.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":53,"s":[13,6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":57,"s":[13,6,0],"to":[0,1.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":59,"s":[13,14,0],"to":[0,0,0],"ti":[0,1.333,0]},{"t":61,"s":[13,6,0]}],"ix":2,"l":2},"a":{"a":0,"k":[123,56,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-1.104,0],[0,0],[0,-1.104]],"o":[[0,0],[0,0],[0,-1.104],[0,0],[1.104,0],[0,0]],"v":[[11,4],[-11,4],[-11,-2],[-9,-4],[9,-4],[11,-2]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[123,56],"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":"Button stroke","np":2,"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":[[-1.104,0],[0,0],[0,-1.104],[0,0],[0,0],[0,0]],"o":[[0,0],[-1.104,0],[0,0],[0,0],[0,0],[0,-1.104]],"v":[[4,-4],[-2,-4],[-4,-2],[-4,4],[2,4],[2,-2]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.156999999402,0.156999999402,0.156999999402,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":[116,56],"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":"Button shadow","np":2,"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],[0,0],[-1.104,0],[0,0],[0,-1.104]],"o":[[0,0],[0,0],[0,-1.104],[0,0],[1.104,0],[0,0]],"v":[[11,4],[-11,4],[-11,-2],[-9,-4],[9,-4],[11,-2]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.187999994615,0.187999994615,0.187999994615,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":[123,56],"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":"Button bg","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":3,"op":75,"st":3,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Picture 05","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.215],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":59,"s":[0]},{"t":69,"s":[-40]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.215,"y":1},"o":{"x":0.333,"y":0},"t":59,"s":[160,100,0],"to":[-11.917,-6.667,0],"ti":[11.917,6.667,0]},{"t":69,"s":[88.5,60,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"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]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[28,27],[-28,27],[-28,-27],[28,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[158,100],"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":"Photo","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":[[3.313,0],[0,0],[0,3.313],[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0]],"o":[[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0],[3.313,0],[0,0],[0,3.313]],"v":[[32,42],[-32,42],[-38,36],[-38,-36],[-32,-42],[32,-42],[38,-36],[38,36]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,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":[158,105],"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":"Bg","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":59,"op":75,"st":59,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Picture 04","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.215],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":51,"s":[0]},{"t":61,"s":[-10]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.215,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[160,100,0],"to":[-13.5,3.333,0],"ti":[13.5,-3.333,0]},{"t":61,"s":[79,120,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"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]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[28,27],[-28,27],[-28,-27],[28,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[158,100],"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":"Photo","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":[[3.313,0],[0,0],[0,3.313],[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0]],"o":[[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0],[3.313,0],[0,0],[0,3.313]],"v":[[32,42],[-32,42],[-38,36],[-38,-36],[-32,-42],[32,-42],[38,-36],[38,36]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,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":[158,105],"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":"Bg","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":51,"op":75,"st":51,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Picture 03","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.215],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":43,"s":[0]},{"t":53,"s":[20]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.215,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[160,100,0],"to":[9.333,-4.833,0],"ti":[-9.333,4.833,0]},{"t":53,"s":[216,71,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"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]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[28,27],[-28,27],[-28,-27],[28,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[158,100],"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":"Photo","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":[[3.313,0],[0,0],[0,3.313],[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0]],"o":[[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0],[3.313,0],[0,0],[0,3.313]],"v":[[32,42],[-32,42],[-38,36],[-38,-36],[-32,-42],[32,-42],[38,-36],[38,36]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,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":[158,105],"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":"Bg","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":43,"op":75,"st":43,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Picture 02","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.215],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":35,"s":[0]},{"t":45,"s":[-10]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.215,"y":1},"o":{"x":0.333,"y":0},"t":35,"s":[160,100,0],"to":[-3.5,-7.667,0],"ti":[3.5,7.667,0]},{"t":45,"s":[139,54,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"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]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[28,27],[-28,27],[-28,-27],[28,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[158,100],"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":"Photo","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":[[3.313,0],[0,0],[0,3.313],[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0]],"o":[[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0],[3.313,0],[0,0],[0,3.313]],"v":[[32,42],[-32,42],[-38,36],[-38,-36],[-32,-42],[32,-42],[38,-36],[38,36]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,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":[158,105],"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":"Bg","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":35,"op":75,"st":35,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Picture 01","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.215],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[0]},{"t":37,"s":[20]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.215,"y":1},"o":{"x":0.333,"y":0},"t":27,"s":[160,100,0],"to":[13.667,5.167,0],"ti":[-13.667,-5.167,0]},{"t":37,"s":[242,131,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160,100,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"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]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[28,27],[-28,27],[-28,-27],[28,-27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.788000009574,0.905999995213,0.972999961703,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":[158,100],"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":"Photo","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":[[3.313,0],[0,0],[0,3.313],[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0]],"o":[[0,0],[-3.313,0],[0,0],[0,-3.313],[0,0],[3.313,0],[0,0],[0,3.313]],"v":[[32,42],[-32,42],[-38,36],[-38,-36],[-32,-42],[32,-42],[38,-36],[38,36]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125,0.113999998803,0.113999998803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,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":[158,105],"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":"Bg","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":27,"op":75,"st":27,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Line + Shadow","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":1,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,176.042,0],"ix":2,"l":2},"a":{"a":0,"k":[150,176.042,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[149.875,176.042],[150.125,176.042]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[78,176.042],[222,176.042]],"c":false}]},{"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[128,176.042],[172,176.042]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0.125,0.113999998803,0.113999998803,1]},{"t":20,"s":[0.917647063732,0.917647063732,0.917647063732,1]}],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/apps/mobile_app/ios/Podfile.lock b/apps/mobile_app/ios/Podfile.lock
index a379860c..9f54f47f 100644
--- a/apps/mobile_app/ios/Podfile.lock
+++ b/apps/mobile_app/ios/Podfile.lock
@@ -6,6 +6,8 @@ PODS:
- Flutter
- flutter_treezor_entrust_sdk_bridge (0.0.1):
- Flutter
+ - image_picker_ios (0.0.1):
+ - Flutter
- mobile_scanner (7.0.0):
- Flutter
- FlutterMacOS
@@ -14,6 +16,8 @@ PODS:
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
+ - share_plus (0.0.1):
+ - Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
@@ -28,9 +32,11 @@ DEPENDENCIES:
- flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_treezor_entrust_sdk_bridge (from `.symlinks/plugins/flutter_treezor_entrust_sdk_bridge/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
+ - share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
@@ -44,12 +50,16 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_treezor_entrust_sdk_bridge:
:path: ".symlinks/plugins/flutter_treezor_entrust_sdk_bridge/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
mobile_scanner:
:path: ".symlinks/plugins/mobile_scanner/darwin"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
+ share_plus:
+ :path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
url_launcher_ios:
@@ -62,9 +72,11 @@ SPEC CHECKSUMS:
flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
flutter_treezor_entrust_sdk_bridge: 4c2c94fb74ab57576e8d49f5f2a4b214e41141fe
+ image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
+ share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4
diff --git a/apps/mobile_app/pubspec.lock b/apps/mobile_app/pubspec.lock
index 9ff4eb33..eefabc78 100644
--- a/apps/mobile_app/pubspec.lock
+++ b/apps/mobile_app/pubspec.lock
@@ -1457,14 +1457,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.11"
- timezone:
- dependency: transitive
- description:
- name: timezone
- sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
- url: "https://pub.dev"
- source: hosted
- version: "0.9.4"
timing:
dependency: transitive
description:
diff --git a/apps/mobile_app/pubspec.yaml b/apps/mobile_app/pubspec.yaml
index f65a7e8c..c50af0cf 100644
--- a/apps/mobile_app/pubspec.yaml
+++ b/apps/mobile_app/pubspec.yaml
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
-version: 1.0.0+5
+version: 1.0.0+6
environment:
sdk: ^3.9.2
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource.dart
index b2af4015..c33d370b 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource.dart
@@ -1,9 +1,7 @@
import '../models/get_background_image_response_model.dart';
abstract class BackgroundImageRemoteDatasource {
- Future getBackgroundImage({
- required String deviceId,
- });
+ Future getBackgroundImage();
Future uploadImage({
required String path,
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource_impl.dart
index 55d4b0a9..60182d8c 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource_impl.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/background_image_remote_datasource_impl.dart
@@ -6,17 +6,16 @@ import 'package:sf_infrastructure/configure_dependencies.dart';
import '../models/get_background_image_response_model.dart';
import 'background_image_remote_datasource.dart';
-class BackgroundImageRemoteDatasourceImpl implements BackgroundImageRemoteDatasource {
+class BackgroundImageRemoteDatasourceImpl
+ implements BackgroundImageRemoteDatasource {
BackgroundImageRemoteDatasourceImpl(this._repository);
final QuestiaRepository _repository;
@override
- Future getBackgroundImage({required String deviceId}) async {
+ Future getBackgroundImage() async {
final response = await safeCall(
- () => _repository.get(
- '/devices/identificator/$deviceId/photos/files',
- ),
+ () => _repository.get('/photos/files'),
'Error getting background image',
);
@@ -39,10 +38,7 @@ class BackgroundImageRemoteDatasourceImpl implements BackgroundImageRemoteDataso
final dio = GetIt.I();
dio.options.headers.remove('content-type');
try {
- final response = await dio.post(
- '/photos',
- data: formData,
- );
+ final response = await dio.post('/photos', data: formData);
final data = response.data;
if (data == null) {
@@ -74,4 +70,4 @@ class BackgroundImageRemoteDatasourceImpl implements BackgroundImageRemoteDataso
'Error setting background image',
);
}
-}
\ No newline at end of file
+}
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.dart
index ad4be8f3..900831a6 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.dart
@@ -22,13 +22,13 @@ abstract class GetPicturesItemResponseModel
with _$GetPicturesItemResponseModel {
const factory GetPicturesItemResponseModel({
required String id,
- required String deviceIdentificator,
+ @Default('') String deviceIdentificator,
String? imgType,
String? timestamp,
- required String fileId,
+ @Default('') String fileId,
String? fileName,
String? contentType,
- required int createdAt,
+ @Default(0) int createdAt,
Map? file,
}) = _GetPicturesItemResponseModel;
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.freezed.dart
index 5400f194..8837ea30 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.freezed.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.freezed.dart
@@ -486,17 +486,17 @@ return $default(_that.id,_that.deviceIdentificator,_that.imgType,_that.timestamp
@JsonSerializable()
class _GetPicturesItemResponseModel implements GetPicturesItemResponseModel {
- const _GetPicturesItemResponseModel({required this.id, required this.deviceIdentificator, this.imgType, this.timestamp, required this.fileId, this.fileName, this.contentType, required this.createdAt, final Map? file}): _file = file;
+ const _GetPicturesItemResponseModel({required this.id, this.deviceIdentificator = '', this.imgType, this.timestamp, this.fileId = '', this.fileName, this.contentType, this.createdAt = 0, final Map? file}): _file = file;
factory _GetPicturesItemResponseModel.fromJson(Map json) => _$GetPicturesItemResponseModelFromJson(json);
@override final String id;
-@override final String deviceIdentificator;
+@override@JsonKey() final String deviceIdentificator;
@override final String? imgType;
@override final String? timestamp;
-@override final String fileId;
+@override@JsonKey() final String fileId;
@override final String? fileName;
@override final String? contentType;
-@override final int createdAt;
+@override@JsonKey() final int createdAt;
final Map? _file;
@override Map? get file {
final value = _file;
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.g.dart
index fc37e1d1..d2ca84d2 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.g.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_pictures_response_model.g.dart
@@ -24,13 +24,13 @@ _GetPicturesItemResponseModel _$GetPicturesItemResponseModelFromJson(
Map json,
) => _GetPicturesItemResponseModel(
id: json['id'] as String,
- deviceIdentificator: json['deviceIdentificator'] as String,
+ deviceIdentificator: json['deviceIdentificator'] as String? ?? '',
imgType: json['imgType'] as String?,
timestamp: json['timestamp'] as String?,
- fileId: json['fileId'] as String,
+ fileId: json['fileId'] as String? ?? '',
fileName: json['fileName'] as String?,
contentType: json['contentType'] as String?,
- createdAt: (json['createdAt'] as num).toInt(),
+ createdAt: (json['createdAt'] as num?)?.toInt() ?? 0,
file: json['file'] as Map?,
);
diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/background_image_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/background_image_repository_impl.dart
index cfc56675..d3d8aa8b 100644
--- a/modules/legacy/modules/device_management/lib/src/core/data/repositories/background_image_repository_impl.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/background_image_repository_impl.dart
@@ -11,8 +11,8 @@ class BackgroundImageRepositoryImpl implements BackgroundImageRepository {
final BackgroundImageRemoteDatasource _remote;
@override
- Future> getPhotos({required String deviceId}) async {
- final model = await _remote.getBackgroundImage(deviceId: deviceId);
+ Future> getPhotos() async {
+ final model = await _remote.getBackgroundImage();
return model.toEntities();
}
diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/background_image_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/background_image_repository.dart
index 40da5f3c..6f6fde97 100644
--- a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/background_image_repository.dart
+++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/background_image_repository.dart
@@ -2,7 +2,7 @@
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
abstract class BackgroundImageRepository {
- Future> getPhotos({required String deviceId});
+ Future> getPhotos();
Future uploadImage({required String path});
Future setBackgroundImage({required String deviceId, required String photoId});
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart
index b29c985a..aa55864f 100644
--- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart
@@ -255,6 +255,7 @@ class ActivityMeterViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return false;
+ ref.syncDeviceSettings(device, updatedSettings);
return true;
} catch (e) {
if (!ref.mounted) return false;
diff --git a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/background_image_screen.dart b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/background_image_screen.dart
index 9017eb7d..561bbeb9 100644
--- a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/background_image_screen.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/background_image_screen.dart
@@ -113,7 +113,7 @@ class BackgroundImageScreen extends ConsumerWidget {
)
: _PhotoGrid(
state: state,
- vm: vm,
+ onPhotoTap: vm.setAsBackground,
primaryColor: primaryColor,
),
),
@@ -160,12 +160,12 @@ class _EmptyState extends StatelessWidget {
class _PhotoGrid extends StatelessWidget {
final BackgroundImageViewState state;
- final BackgroundImageViewModel vm;
+ final ValueChanged onPhotoTap;
final Color primaryColor;
const _PhotoGrid({
required this.state,
- required this.vm,
+ required this.onPhotoTap,
required this.primaryColor,
});
@@ -192,28 +192,53 @@ class _PhotoGrid extends StatelessWidget {
itemCount: state.photos.length,
itemBuilder: (context, index) {
final photo = state.photos[index];
+ final isActive = state.currentBackgroundId == photo.id;
return GestureDetector(
- onTap: () => vm.setAsBackground(photo.id),
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(12),
- border: Border.all(
- color: Colors.grey.shade300,
- ),
- ),
- clipBehavior: Clip.antiAlias,
- child: photo.fileBytes != null
- ? Image.memory(
- photo.fileBytes!,
- fit: BoxFit.cover,
- )
- : Center(
- child: Icon(
- Icons.image_outlined,
- size: 48,
- color: Colors.grey.shade400,
+ onTap: () => onPhotoTap(photo.id),
+ child: Stack(
+ children: [
+ Positioned.fill(
+ child: Container(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(12),
+ border: Border.all(
+ color: isActive ? primaryColor : Colors.grey.shade300,
+ width: isActive ? 3 : 1,
),
),
+ clipBehavior: Clip.antiAlias,
+ child: photo.fileBytes != null
+ ? Image.memory(
+ photo.fileBytes!,
+ fit: BoxFit.cover,
+ )
+ : Center(
+ child: Icon(
+ Icons.image_outlined,
+ size: 48,
+ color: Colors.grey.shade400,
+ ),
+ ),
+ ),
+ ),
+ if (isActive)
+ Positioned(
+ top: 8,
+ right: 8,
+ child: Container(
+ padding: const EdgeInsets.all(4),
+ decoration: BoxDecoration(
+ color: primaryColor,
+ shape: BoxShape.circle,
+ ),
+ child: const Icon(
+ Icons.check,
+ color: Colors.white,
+ size: 16,
+ ),
+ ),
+ ),
+ ],
),
);
},
diff --git a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_model.dart
index 3631fcdb..bb96fe85 100644
--- a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_model.dart
@@ -1,22 +1,26 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.dart';
import 'package:legacy_shared/legacy_shared.dart';
+import 'package:sf_shared/sf_shared.dart';
import '../../../../core/domain/repositories/background_image_repository.dart';
import '../../../../core/providers/background_image_repository_provider.dart';
import 'background_image_view_state.dart';
final backgroundImageViewModelProvider =
- NotifierProvider.autoDispose(
- BackgroundImageViewModel.new,
-);
+ NotifierProvider.autoDispose<
+ BackgroundImageViewModel,
+ BackgroundImageViewState
+ >(BackgroundImageViewModel.new);
class BackgroundImageViewModel extends Notifier {
late final BackgroundImageRepository _repository;
+ late final SharedDevicesRepository _devicesRepository;
@override
BackgroundImageViewState build() {
_repository = ref.read(backgroundImageRepositoryProvider);
+ _devicesRepository = ref.read(sharedDevicesRepositoryProvider);
Future.microtask(_load);
return const BackgroundImageViewState();
}
@@ -26,12 +30,14 @@ class BackgroundImageViewModel extends Notifier {
final device = ref.read(selectedDeviceProvider);
if (device == null) return;
- final photos = await _repository.getPhotos(
- deviceId: device.identificator,
- );
+ final photos = await _repository.getPhotos();
if (!ref.mounted) return;
- state = state.copyWith(photos: photos, isLoading: false);
+ state = state.copyWith(
+ photos: photos,
+ currentBackgroundId: device.backgroundImageId,
+ isLoading: false,
+ );
} catch (e) {
if (!ref.mounted) return;
state = state.copyWith(
@@ -57,10 +63,26 @@ class BackgroundImageViewModel extends Notifier {
);
if (image == null) return;
- state = state.copyWith(isSaving: true, errorEvent: null, successEvent: null);
+ final device = ref.read(selectedDeviceProvider);
+ if (device == null) return;
+
+ state = state.copyWith(
+ isSaving: true,
+ errorEvent: null,
+ successEvent: null,
+ );
try {
- await _repository.uploadImage(path: image.path);
+ final photoId = await _repository.uploadImage(path: image.path);
+ if (!ref.mounted) return;
+
+ await _repository.setBackgroundImage(
+ deviceId: device.id,
+ photoId: photoId,
+ );
+ if (!ref.mounted) return;
+
+ await _refreshDevice(device);
if (!ref.mounted) return;
state = state.copyWith(
@@ -82,7 +104,11 @@ class BackgroundImageViewModel extends Notifier {
final device = ref.read(selectedDeviceProvider);
if (device == null) return;
- state = state.copyWith(isSaving: true, errorEvent: null, successEvent: null);
+ state = state.copyWith(
+ isSaving: true,
+ errorEvent: null,
+ successEvent: null,
+ );
try {
await _repository.setBackgroundImage(
@@ -91,10 +117,15 @@ class BackgroundImageViewModel extends Notifier {
);
if (!ref.mounted) return;
+ await _refreshDevice(device);
+ if (!ref.mounted) return;
+
state = state.copyWith(
isSaving: false,
successEvent: BackgroundImageSuccessEvent.backgroundSet,
);
+
+ await reload();
} catch (e) {
if (!ref.mounted) return;
state = state.copyWith(
@@ -103,4 +134,15 @@ class BackgroundImageViewModel extends Notifier {
);
}
}
+
+ Future _refreshDevice(DeviceEntity currentDevice) async {
+ final devices = await _devicesRepository.getDevices();
+ if (!ref.mounted) return;
+
+ final updated = devices.firstWhere(
+ (d) => d.identificator == currentDevice.identificator,
+ orElse: () => currentDevice,
+ );
+ ref.read(selectedDeviceProvider.notifier).setSelectedDevice(updated);
+ }
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.dart
index 1e8a6e2f..ba8260ed 100644
--- a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.dart
@@ -12,6 +12,7 @@ abstract class BackgroundImageViewState with _$BackgroundImageViewState {
@Default([]) List photos,
@Default(true) bool isLoading,
@Default(false) bool isSaving,
+ String? currentBackgroundId,
BackgroundImageSuccessEvent? successEvent,
BackgroundImageErrorEvent? errorEvent,
}) = _BackgroundImageViewState;
diff --git a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.freezed.dart
index 7aa9c745..c9e86d30 100644
--- a/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.freezed.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/background_image/presentation/state/background_image_view_state.freezed.dart
@@ -14,7 +14,7 @@ T _$identity(T value) => value;
/// @nodoc
mixin _$BackgroundImageViewState {
- List get photos; bool get isLoading; bool get isSaving; BackgroundImageSuccessEvent? get successEvent; BackgroundImageErrorEvent? get errorEvent;
+ List get photos; bool get isLoading; bool get isSaving; String? get currentBackgroundId; BackgroundImageSuccessEvent? get successEvent; BackgroundImageErrorEvent? get errorEvent;
/// Create a copy of BackgroundImageViewState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $BackgroundImageViewStateCopyWith get copyWith => _$Ba
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is BackgroundImageViewState&&const DeepCollectionEquality().equals(other.photos, photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is BackgroundImageViewState&&const DeepCollectionEquality().equals(other.photos, photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.currentBackgroundId, currentBackgroundId) || other.currentBackgroundId == currentBackgroundId)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
}
@override
-int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(photos),isLoading,isSaving,successEvent,errorEvent);
+int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(photos),isLoading,isSaving,currentBackgroundId,successEvent,errorEvent);
@override
String toString() {
- return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, successEvent: $successEvent, errorEvent: $errorEvent)';
+ return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, currentBackgroundId: $currentBackgroundId, successEvent: $successEvent, errorEvent: $errorEvent)';
}
@@ -45,7 +45,7 @@ abstract mixin class $BackgroundImageViewStateCopyWith<$Res> {
factory $BackgroundImageViewStateCopyWith(BackgroundImageViewState value, $Res Function(BackgroundImageViewState) _then) = _$BackgroundImageViewStateCopyWithImpl;
@useResult
$Res call({
- List photos, bool isLoading, bool isSaving, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
+ List photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
});
@@ -62,12 +62,13 @@ class _$BackgroundImageViewStateCopyWithImpl<$Res>
/// Create a copy of BackgroundImageViewState
/// with the given fields replaced by the non-null parameter values.
-@pragma('vm:prefer-inline') @override $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
+@pragma('vm:prefer-inline') @override $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? currentBackgroundId = freezed,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
return _then(_self.copyWith(
photos: null == photos ? _self.photos : photos // ignore: cast_nullable_to_non_nullable
as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable
-as bool,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
+as bool,currentBackgroundId: freezed == currentBackgroundId ? _self.currentBackgroundId : currentBackgroundId // ignore: cast_nullable_to_non_nullable
+as String?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
as BackgroundImageSuccessEvent?,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
as BackgroundImageErrorEvent?,
));
@@ -154,10 +155,10 @@ return $default(_that);case _:
/// }
/// ```
-@optionalTypeArgs TResult maybeWhen(TResult Function( List photos, bool isLoading, bool isSaving, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,{required TResult orElse(),}) {final _that = this;
+@optionalTypeArgs TResult maybeWhen(TResult Function( List photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BackgroundImageViewState() when $default != null:
-return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_that.errorEvent);case _:
+return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
return orElse();
}
@@ -175,10 +176,10 @@ return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_
/// }
/// ```
-@optionalTypeArgs TResult when(TResult Function( List photos, bool isLoading, bool isSaving, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent) $default,) {final _that = this;
+@optionalTypeArgs TResult when(TResult Function( List photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent) $default,) {final _that = this;
switch (_that) {
case _BackgroundImageViewState():
-return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_that.errorEvent);case _:
+return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
throw StateError('Unexpected subclass');
}
@@ -195,10 +196,10 @@ return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_
/// }
/// ```
-@optionalTypeArgs TResult? whenOrNull(TResult? Function( List photos, bool isLoading, bool isSaving, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,) {final _that = this;
+@optionalTypeArgs TResult? whenOrNull(TResult? Function( List photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,) {final _that = this;
switch (_that) {
case _BackgroundImageViewState() when $default != null:
-return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_that.errorEvent);case _:
+return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
return null;
}
@@ -210,7 +211,7 @@ return $default(_that.photos,_that.isLoading,_that.isSaving,_that.successEvent,_
class _BackgroundImageViewState implements BackgroundImageViewState {
- const _BackgroundImageViewState({final List photos = const [], this.isLoading = true, this.isSaving = false, this.successEvent, this.errorEvent}): _photos = photos;
+ const _BackgroundImageViewState({final List photos = const [], this.isLoading = true, this.isSaving = false, this.currentBackgroundId, this.successEvent, this.errorEvent}): _photos = photos;
final List _photos;
@@ -222,6 +223,7 @@ class _BackgroundImageViewState implements BackgroundImageViewState {
@override@JsonKey() final bool isLoading;
@override@JsonKey() final bool isSaving;
+@override final String? currentBackgroundId;
@override final BackgroundImageSuccessEvent? successEvent;
@override final BackgroundImageErrorEvent? errorEvent;
@@ -235,16 +237,16 @@ _$BackgroundImageViewStateCopyWith<_BackgroundImageViewState> get copyWith => __
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackgroundImageViewState&&const DeepCollectionEquality().equals(other._photos, _photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackgroundImageViewState&&const DeepCollectionEquality().equals(other._photos, _photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.currentBackgroundId, currentBackgroundId) || other.currentBackgroundId == currentBackgroundId)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
}
@override
-int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_photos),isLoading,isSaving,successEvent,errorEvent);
+int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_photos),isLoading,isSaving,currentBackgroundId,successEvent,errorEvent);
@override
String toString() {
- return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, successEvent: $successEvent, errorEvent: $errorEvent)';
+ return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, currentBackgroundId: $currentBackgroundId, successEvent: $successEvent, errorEvent: $errorEvent)';
}
@@ -255,7 +257,7 @@ abstract mixin class _$BackgroundImageViewStateCopyWith<$Res> implements $Backgr
factory _$BackgroundImageViewStateCopyWith(_BackgroundImageViewState value, $Res Function(_BackgroundImageViewState) _then) = __$BackgroundImageViewStateCopyWithImpl;
@override @useResult
$Res call({
- List photos, bool isLoading, bool isSaving, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
+ List photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
});
@@ -272,12 +274,13 @@ class __$BackgroundImageViewStateCopyWithImpl<$Res>
/// Create a copy of BackgroundImageViewState
/// with the given fields replaced by the non-null parameter values.
-@override @pragma('vm:prefer-inline') $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
+@override @pragma('vm:prefer-inline') $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? currentBackgroundId = freezed,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
return _then(_BackgroundImageViewState(
photos: null == photos ? _self._photos : photos // ignore: cast_nullable_to_non_nullable
as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable
-as bool,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
+as bool,currentBackgroundId: freezed == currentBackgroundId ? _self.currentBackgroundId : currentBackgroundId // ignore: cast_nullable_to_non_nullable
+as String?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
as BackgroundImageSuccessEvent?,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
as BackgroundImageErrorEvent?,
));
diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart
index 9c88db4c..5eaee001 100644
--- a/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart
@@ -32,7 +32,7 @@ class HealthViewModel extends Notifier {
Timer? _measureTimer;
static const int _historyPageSize = 20;
- static const int _measureDurationSeconds = 35;
+ static const int _measureDurationSeconds = 60;
@override
HealthViewState build() {
@@ -295,6 +295,7 @@ class HealthViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return false;
+ ref.syncDeviceSettings(device, updatedSettings);
return true;
} catch (e) {
if (!ref.mounted) return false;
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.dart
index 85895122..84be2daf 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.dart
@@ -8,13 +8,13 @@ part 'picture_entity.freezed.dart';
abstract class PictureEntity with _$PictureEntity {
const factory PictureEntity({
required String id,
- required String deviceIdentificator,
+ @Default('') String deviceIdentificator,
String? imgType,
String? timestamp,
- required String fileId,
+ @Default('') String fileId,
String? fileName,
String? contentType,
- required int createdAt,
+ @Default(0) int createdAt,
Uint8List? fileBytes,
}) = _PictureEntity;
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart
index 077e7d94..5ca9dd67 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart
@@ -214,17 +214,17 @@ return $default(_that.id,_that.deviceIdentificator,_that.imgType,_that.timestamp
class _PictureEntity implements PictureEntity {
- const _PictureEntity({required this.id, required this.deviceIdentificator, this.imgType, this.timestamp, required this.fileId, this.fileName, this.contentType, required this.createdAt, this.fileBytes});
+ const _PictureEntity({required this.id, this.deviceIdentificator = '', this.imgType, this.timestamp, this.fileId = '', this.fileName, this.contentType, this.createdAt = 0, this.fileBytes});
@override final String id;
-@override final String deviceIdentificator;
+@override@JsonKey() final String deviceIdentificator;
@override final String? imgType;
@override final String? timestamp;
-@override final String fileId;
+@override@JsonKey() final String fileId;
@override final String? fileName;
@override final String? contentType;
-@override final int createdAt;
+@override@JsonKey() final int createdAt;
@override final Uint8List? fileBytes;
/// Create a copy of PictureEntity
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart
index 5830acb9..5127275c 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart
@@ -1,7 +1,9 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:lottie/lottie.dart';
import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_model.dart';
+import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_state.dart';
import 'package:device_management/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart';
import 'package:navigation/navigation.dart';
import 'package:sf_localizations/sf_localizations.dart';
@@ -17,10 +19,33 @@ class RemoteCameraScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
ref.listen(
- remoteConnectionViewModelProvider.select((s) => s.successMessage),
- (_, successMessage) {
- if (successMessage.isNotEmpty) {
- showTopSnackbar(context, message: context.translate(successMessage), type: MessageType.success);
+ remoteConnectionViewModelProvider.select((s) => s.errorEvent),
+ (_, next) {
+ if (next != null) {
+ final message = switch (next) {
+ RemoteConnectionErrorEvent.takePicture =>
+ context.translate(I18n.errorTakePicture),
+ RemoteConnectionErrorEvent.fetchPhotos =>
+ context.translate(I18n.errorFetchPhotos),
+ RemoteConnectionErrorEvent.call =>
+ context.translate(I18n.errorCall),
+ RemoteConnectionErrorEvent.invalidPhone =>
+ context.translate(I18n.errorMessagePhoneIsInvalid),
+ };
+ showTopSnackbar(context, message: message, type: MessageType.error);
+ }
+ },
+ );
+
+ ref.listen(
+ remoteConnectionViewModelProvider.select((s) => s.successEvent),
+ (_, next) {
+ if (next != null) {
+ final message = switch (next) {
+ RemoteConnectionSuccessEvent.photoTaken =>
+ context.translate(I18n.photoTaken),
+ };
+ showTopSnackbar(context, message: message, type: MessageType.success);
ref.read(remoteConnectionViewModelProvider.notifier).clearSuccess();
}
},
@@ -28,20 +53,38 @@ class RemoteCameraScreen extends ConsumerWidget {
final theme = ref.watch(themePortProvider);
- final isLoadingPictures = ref.watch(
- remoteConnectionViewModelProvider.select((s)=>s.isLoadingPictures)
+ final isLoading = ref.watch(
+ remoteConnectionViewModelProvider.select((s) => s.isLoadingPictures),
);
- final isTakingPicture = ref.watch(
- remoteConnectionViewModelProvider.select((s)=>s.isTakingPicture)
+ final isTaking = ref.watch(
+ remoteConnectionViewModelProvider.select((s) => s.isTakingPicture),
);
+ final isWaiting = ref.watch(
+ remoteConnectionViewModelProvider.select((s) => s.isWaitingForPhoto),
+ );
+ final countdown = ref.watch(
+ remoteConnectionViewModelProvider.select((s) => s.photoCountdown),
+ );
+
+ Widget body;
+ if (isLoading || isTaking) {
+ body = const Center(child: CircularProgressIndicator());
+ } else if (isWaiting) {
+ body = _WaitingForPhotoOverlay(
+ remainingSeconds: countdown,
+ theme: theme,
+ );
+ } else {
+ body = const _GallerySection();
+ }
return LegacyPageLayout(
theme: theme,
title: context.translate(I18n.remoteCamera),
- body: isLoadingPictures || isTakingPicture
- ? const Center(child: CircularProgressIndicator())
- : const _GallerySection(),
- footer: _TakePictureSection(),
+ body: body,
+ footer: isWaiting
+ ? const SizedBox.shrink()
+ : const _TakePictureSection(),
);
}
}
@@ -87,12 +130,12 @@ class _GallerySection extends ConsumerWidget {
color: theme.getColorFor(ThemeCode.textTertiary)
))
),
- child: Image.network(
- pictures[index].fileId,
- fit: BoxFit.cover,
- errorBuilder: (_, __, ___) =>
- const Icon(Icons.broken_image, color: Colors.grey),
- )
+ child: pictures[index].fileBytes != null
+ ? Image.memory(
+ pictures[index].fileBytes!,
+ fit: BoxFit.cover,
+ )
+ : const Icon(Icons.broken_image, color: Colors.grey),
)
)
),
@@ -124,5 +167,53 @@ class _TakePictureSection extends ConsumerWidget {
),
);
}
+}
+class _WaitingForPhotoOverlay extends StatelessWidget {
+ static const String _animationAsset =
+ 'assets/shared/animations/shooting_photo.json';
+
+ final int remainingSeconds;
+ final ThemePort theme;
+
+ const _WaitingForPhotoOverlay({
+ required this.remainingSeconds,
+ required this.theme,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary);
+
+ return Center(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Lottie.asset(
+ _animationAsset,
+ width: 200,
+ height: 200,
+ ),
+ const SizedBox(height: 24),
+ Text(
+ context.translate(I18n.takingPhoto),
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.w600,
+ color: primaryColor,
+ ),
+ ),
+ const SizedBox(height: 12),
+ Text(
+ '${remainingSeconds}s',
+ style: TextStyle(
+ fontSize: 32,
+ fontWeight: FontWeight.bold,
+ color: primaryColor,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
}
\ No newline at end of file
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart
index 3b746c12..0e06e5fd 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart
@@ -1,10 +1,11 @@
+import 'dart:async';
+
import 'package:device_management/src/core/providers/pictures_repository_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_state.dart';
import 'package:legacy_shared/legacy_shared.dart';
-import 'package:sf_localizations/sf_localizations.dart';
import '../../../../core/domain/repositories/pictures_repository.dart';
@@ -18,8 +19,10 @@ class RemoteConnectionViewModel extends Notifier {
late final TextEditingController phoneController;
late final CommandsRepository _commandsRepository;
late final PicturesRepository _picturesRepository;
+ Timer? _photoTimer;
static final RegExp _phoneRegex = RegExp(r'^\+?\d{6,15}$');
+ static const int _photoWaitSeconds = 5;
@override
RemoteConnectionViewState build() {
@@ -60,12 +63,12 @@ class RemoteConnectionViewModel extends Notifier {
final text = phoneController.text;
if (text == state.phone) return;
- state = state.copyWith(phone: text, errorMessage: '');
+ state = state.copyWith(phone: text, errorEvent: null);
}
void updateDialCode(String value) {
if (value == state.dialCode) return;
- state = state.copyWith(dialCode: value, errorMessage: '');
+ state = state.copyWith(dialCode: value, errorEvent: null);
}
void prevPicture() {
@@ -95,18 +98,17 @@ class RemoteConnectionViewModel extends Notifier {
}
void clearSuccess() {
- state = state.copyWith(
- successMessage: '',
- );
+ state = state.copyWith(successEvent: null);
}
Future takePicture() async {
try {
state = state.copyWith(
isTakingPicture: true,
- successMessage: '',
+ successEvent: null,
+ errorEvent: null,
);
-
+
final request = SendCommandRequestModel(
device: state.deviceId,
command: DeviceCommand.requestPhoto,
@@ -115,21 +117,59 @@ class RemoteConnectionViewModel extends Notifier {
await _commandsRepository.send(request: request);
if (!ref.mounted) return;
+ state = state.copyWith(
+ isTakingPicture: false,
+ isWaitingForPhoto: true,
+ photoCountdown: _photoWaitSeconds,
+ );
+
+ _startPhotoCountdown();
+ } catch (e) {
+ if (!ref.mounted) return;
+ state = state.copyWith(
+ isTakingPicture: false,
+ errorEvent: RemoteConnectionErrorEvent.takePicture,
+ );
+ }
+ }
+
+ void _startPhotoCountdown() {
+ _photoTimer?.cancel();
+ _photoTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
+ if (!ref.mounted) {
+ timer.cancel();
+ return;
+ }
+ final remaining = state.photoCountdown - 1;
+ if (remaining <= 0) {
+ timer.cancel();
+ _photoTimer = null;
+ _fetchPhotosAfterCapture();
+ } else {
+ state = state.copyWith(photoCountdown: remaining);
+ }
+ });
+ }
+
+ Future _fetchPhotosAfterCapture() async {
+ try {
final pictures = await _picturesRepository.getPictures(
deviceId: state.deviceId,
);
if (!ref.mounted) return;
state = state.copyWith(
- isTakingPicture: false,
+ isWaitingForPhoto: false,
+ photoCountdown: 0,
pictures: pictures,
- successMessage: I18n.photoTaken,
+ successEvent: RemoteConnectionSuccessEvent.photoTaken,
);
} catch (e) {
if (!ref.mounted) return;
state = state.copyWith(
- isTakingPicture: false,
- errorMessage: e.toString(),
+ isWaitingForPhoto: false,
+ photoCountdown: 0,
+ errorEvent: RemoteConnectionErrorEvent.fetchPhotos,
);
}
}
@@ -137,12 +177,8 @@ class RemoteConnectionViewModel extends Notifier {
Future call() async {
final phone = phoneController.text;
final dialCode = state.dialCode;
- if (phone.isEmpty){
- state = state.copyWith(errorMessage: I18n.errorMessagePhoneIsInvalid);
- return;
- }
- if (!_phoneRegex.hasMatch(phone)) {
- state = state.copyWith(errorMessage: I18n.errorMessagePhoneIsInvalid);
+ if (phone.isEmpty || !_phoneRegex.hasMatch(phone)) {
+ state = state.copyWith(errorEvent: RemoteConnectionErrorEvent.invalidPhone);
return;
}
@@ -163,7 +199,7 @@ class RemoteConnectionViewModel extends Notifier {
if (!ref.mounted) return;
state = state.copyWith(
isCalling: false,
- errorMessage: e.toString(),
+ errorEvent: RemoteConnectionErrorEvent.call,
);
}
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart
index 4d60b5c1..ccfe9a13 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart
@@ -3,6 +3,9 @@ import 'package:device_management/src/features/remote_connection/domain/entities
part 'remote_connection_view_state.freezed.dart';
+enum RemoteConnectionErrorEvent { takePicture, fetchPhotos, call, invalidPhone }
+enum RemoteConnectionSuccessEvent { photoTaken }
+
@freezed
abstract class RemoteConnectionViewState with _$RemoteConnectionViewState {
const factory RemoteConnectionViewState({
@@ -13,8 +16,10 @@ abstract class RemoteConnectionViewState with _$RemoteConnectionViewState {
@Default(0) int pictureIndex,
@Default(true) bool isLoadingPictures,
@Default(false) bool isTakingPicture,
+ @Default(false) bool isWaitingForPhoto,
+ @Default(0) int photoCountdown,
@Default(false) bool isCalling,
- @Default('') String errorMessage,
- @Default('') String successMessage
+ RemoteConnectionErrorEvent? errorEvent,
+ RemoteConnectionSuccessEvent? successEvent,
}) = _RemoteConnectionViewState;
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart
index 3c3b7f02..3421a474 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart
@@ -14,7 +14,7 @@ T _$identity(T value) => value;
/// @nodoc
mixin _$RemoteConnectionViewState {
- String get deviceId; String get dialCode; String get phone; List get pictures; int get pictureIndex; bool get isLoadingPictures; bool get isTakingPicture; bool get isCalling; String get errorMessage; String get successMessage;
+ String get deviceId; String get dialCode; String get phone; List get pictures; int get pictureIndex; bool get isLoadingPictures; bool get isTakingPicture; bool get isWaitingForPhoto; int get photoCountdown; bool get isCalling; RemoteConnectionErrorEvent? get errorEvent; RemoteConnectionSuccessEvent? get successEvent;
/// Create a copy of RemoteConnectionViewState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $RemoteConnectionViewStateCopyWith get copyWith => _$
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is RemoteConnectionViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other.pictures, pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is RemoteConnectionViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other.pictures, pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isWaitingForPhoto, isWaitingForPhoto) || other.isWaitingForPhoto == isWaitingForPhoto)&&(identical(other.photoCountdown, photoCountdown) || other.photoCountdown == photoCountdown)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent));
}
@override
-int get hashCode => Object.hash(runtimeType,deviceId,dialCode,phone,const DeepCollectionEquality().hash(pictures),pictureIndex,isLoadingPictures,isTakingPicture,isCalling,errorMessage,successMessage);
+int get hashCode => Object.hash(runtimeType,deviceId,dialCode,phone,const DeepCollectionEquality().hash(pictures),pictureIndex,isLoadingPictures,isTakingPicture,isWaitingForPhoto,photoCountdown,isCalling,errorEvent,successEvent);
@override
String toString() {
- return 'RemoteConnectionViewState(deviceId: $deviceId, dialCode: $dialCode, phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage, successMessage: $successMessage)';
+ return 'RemoteConnectionViewState(deviceId: $deviceId, dialCode: $dialCode, phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isWaitingForPhoto: $isWaitingForPhoto, photoCountdown: $photoCountdown, isCalling: $isCalling, errorEvent: $errorEvent, successEvent: $successEvent)';
}
@@ -45,7 +45,7 @@ abstract mixin class $RemoteConnectionViewStateCopyWith<$Res> {
factory $RemoteConnectionViewStateCopyWith(RemoteConnectionViewState value, $Res Function(RemoteConnectionViewState) _then) = _$RemoteConnectionViewStateCopyWithImpl;
@useResult
$Res call({
- String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage, String successMessage
+ String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isWaitingForPhoto, int photoCountdown, bool isCalling, RemoteConnectionErrorEvent? errorEvent, RemoteConnectionSuccessEvent? successEvent
});
@@ -62,7 +62,7 @@ class _$RemoteConnectionViewStateCopyWithImpl<$Res>
/// Create a copy of RemoteConnectionViewState
/// with the given fields replaced by the non-null parameter values.
-@pragma('vm:prefer-inline') @override $Res call({Object? deviceId = null,Object? dialCode = null,Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,Object? successMessage = null,}) {
+@pragma('vm:prefer-inline') @override $Res call({Object? deviceId = null,Object? dialCode = null,Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isWaitingForPhoto = null,Object? photoCountdown = null,Object? isCalling = null,Object? errorEvent = freezed,Object? successEvent = freezed,}) {
return _then(_self.copyWith(
deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
@@ -71,10 +71,12 @@ as String,pictures: null == pictures ? _self.pictures : pictures // ignore: cast
as List,pictureIndex: null == pictureIndex ? _self.pictureIndex : pictureIndex // ignore: cast_nullable_to_non_nullable
as int,isLoadingPictures: null == isLoadingPictures ? _self.isLoadingPictures : isLoadingPictures // ignore: cast_nullable_to_non_nullable
as bool,isTakingPicture: null == isTakingPicture ? _self.isTakingPicture : isTakingPicture // ignore: cast_nullable_to_non_nullable
-as bool,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable
-as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
-as String,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable
-as String,
+as bool,isWaitingForPhoto: null == isWaitingForPhoto ? _self.isWaitingForPhoto : isWaitingForPhoto // ignore: cast_nullable_to_non_nullable
+as bool,photoCountdown: null == photoCountdown ? _self.photoCountdown : photoCountdown // ignore: cast_nullable_to_non_nullable
+as int,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable
+as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
+as RemoteConnectionErrorEvent?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
+as RemoteConnectionSuccessEvent?,
));
}
@@ -159,10 +161,10 @@ return $default(_that);case _:
/// }
/// ```
-@optionalTypeArgs TResult maybeWhen(TResult Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage, String successMessage)? $default,{required TResult orElse(),}) {final _that = this;
+@optionalTypeArgs TResult maybeWhen(TResult Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isWaitingForPhoto, int photoCountdown, bool isCalling, RemoteConnectionErrorEvent? errorEvent, RemoteConnectionSuccessEvent? successEvent)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _RemoteConnectionViewState() when $default != null:
-return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage,_that.successMessage);case _:
+return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isWaitingForPhoto,_that.photoCountdown,_that.isCalling,_that.errorEvent,_that.successEvent);case _:
return orElse();
}
@@ -180,10 +182,10 @@ return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.p
/// }
/// ```
-@optionalTypeArgs TResult when(TResult Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage, String successMessage) $default,) {final _that = this;
+@optionalTypeArgs TResult when(TResult Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isWaitingForPhoto, int photoCountdown, bool isCalling, RemoteConnectionErrorEvent? errorEvent, RemoteConnectionSuccessEvent? successEvent) $default,) {final _that = this;
switch (_that) {
case _RemoteConnectionViewState():
-return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage,_that.successMessage);case _:
+return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isWaitingForPhoto,_that.photoCountdown,_that.isCalling,_that.errorEvent,_that.successEvent);case _:
throw StateError('Unexpected subclass');
}
@@ -200,10 +202,10 @@ return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.p
/// }
/// ```
-@optionalTypeArgs TResult? whenOrNull(TResult? Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage, String successMessage)? $default,) {final _that = this;
+@optionalTypeArgs TResult? whenOrNull(TResult? Function( String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isWaitingForPhoto, int photoCountdown, bool isCalling, RemoteConnectionErrorEvent? errorEvent, RemoteConnectionSuccessEvent? successEvent)? $default,) {final _that = this;
switch (_that) {
case _RemoteConnectionViewState() when $default != null:
-return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage,_that.successMessage);case _:
+return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isWaitingForPhoto,_that.photoCountdown,_that.isCalling,_that.errorEvent,_that.successEvent);case _:
return null;
}
@@ -215,7 +217,7 @@ return $default(_that.deviceId,_that.dialCode,_that.phone,_that.pictures,_that.p
class _RemoteConnectionViewState implements RemoteConnectionViewState {
- const _RemoteConnectionViewState({this.deviceId = '', this.dialCode = '+34', this.phone = '', final List pictures = const [], this.pictureIndex = 0, this.isLoadingPictures = true, this.isTakingPicture = false, this.isCalling = false, this.errorMessage = '', this.successMessage = ''}): _pictures = pictures;
+ const _RemoteConnectionViewState({this.deviceId = '', this.dialCode = '+34', this.phone = '', final List pictures = const [], this.pictureIndex = 0, this.isLoadingPictures = true, this.isTakingPicture = false, this.isWaitingForPhoto = false, this.photoCountdown = 0, this.isCalling = false, this.errorEvent, this.successEvent}): _pictures = pictures;
@override@JsonKey() final String deviceId;
@@ -231,9 +233,11 @@ class _RemoteConnectionViewState implements RemoteConnectionViewState {
@override@JsonKey() final int pictureIndex;
@override@JsonKey() final bool isLoadingPictures;
@override@JsonKey() final bool isTakingPicture;
+@override@JsonKey() final bool isWaitingForPhoto;
+@override@JsonKey() final int photoCountdown;
@override@JsonKey() final bool isCalling;
-@override@JsonKey() final String errorMessage;
-@override@JsonKey() final String successMessage;
+@override final RemoteConnectionErrorEvent? errorEvent;
+@override final RemoteConnectionSuccessEvent? successEvent;
/// Create a copy of RemoteConnectionViewState
/// with the given fields replaced by the non-null parameter values.
@@ -245,16 +249,16 @@ _$RemoteConnectionViewStateCopyWith<_RemoteConnectionViewState> get copyWith =>
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is _RemoteConnectionViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other._pictures, _pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _RemoteConnectionViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other._pictures, _pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isWaitingForPhoto, isWaitingForPhoto) || other.isWaitingForPhoto == isWaitingForPhoto)&&(identical(other.photoCountdown, photoCountdown) || other.photoCountdown == photoCountdown)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent));
}
@override
-int get hashCode => Object.hash(runtimeType,deviceId,dialCode,phone,const DeepCollectionEquality().hash(_pictures),pictureIndex,isLoadingPictures,isTakingPicture,isCalling,errorMessage,successMessage);
+int get hashCode => Object.hash(runtimeType,deviceId,dialCode,phone,const DeepCollectionEquality().hash(_pictures),pictureIndex,isLoadingPictures,isTakingPicture,isWaitingForPhoto,photoCountdown,isCalling,errorEvent,successEvent);
@override
String toString() {
- return 'RemoteConnectionViewState(deviceId: $deviceId, dialCode: $dialCode, phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage, successMessage: $successMessage)';
+ return 'RemoteConnectionViewState(deviceId: $deviceId, dialCode: $dialCode, phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isWaitingForPhoto: $isWaitingForPhoto, photoCountdown: $photoCountdown, isCalling: $isCalling, errorEvent: $errorEvent, successEvent: $successEvent)';
}
@@ -265,7 +269,7 @@ abstract mixin class _$RemoteConnectionViewStateCopyWith<$Res> implements $Remot
factory _$RemoteConnectionViewStateCopyWith(_RemoteConnectionViewState value, $Res Function(_RemoteConnectionViewState) _then) = __$RemoteConnectionViewStateCopyWithImpl;
@override @useResult
$Res call({
- String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage, String successMessage
+ String deviceId, String dialCode, String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isWaitingForPhoto, int photoCountdown, bool isCalling, RemoteConnectionErrorEvent? errorEvent, RemoteConnectionSuccessEvent? successEvent
});
@@ -282,7 +286,7 @@ class __$RemoteConnectionViewStateCopyWithImpl<$Res>
/// Create a copy of RemoteConnectionViewState
/// with the given fields replaced by the non-null parameter values.
-@override @pragma('vm:prefer-inline') $Res call({Object? deviceId = null,Object? dialCode = null,Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,Object? successMessage = null,}) {
+@override @pragma('vm:prefer-inline') $Res call({Object? deviceId = null,Object? dialCode = null,Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isWaitingForPhoto = null,Object? photoCountdown = null,Object? isCalling = null,Object? errorEvent = freezed,Object? successEvent = freezed,}) {
return _then(_RemoteConnectionViewState(
deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
@@ -291,10 +295,12 @@ as String,pictures: null == pictures ? _self._pictures : pictures // ignore: cas
as List,pictureIndex: null == pictureIndex ? _self.pictureIndex : pictureIndex // ignore: cast_nullable_to_non_nullable
as int,isLoadingPictures: null == isLoadingPictures ? _self.isLoadingPictures : isLoadingPictures // ignore: cast_nullable_to_non_nullable
as bool,isTakingPicture: null == isTakingPicture ? _self.isTakingPicture : isTakingPicture // ignore: cast_nullable_to_non_nullable
-as bool,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable
-as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
-as String,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable
-as String,
+as bool,isWaitingForPhoto: null == isWaitingForPhoto ? _self.isWaitingForPhoto : isWaitingForPhoto // ignore: cast_nullable_to_non_nullable
+as bool,photoCountdown: null == photoCountdown ? _self.photoCountdown : photoCountdown // ignore: cast_nullable_to_non_nullable
+as int,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable
+as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
+as RemoteConnectionErrorEvent?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
+as RemoteConnectionSuccessEvent?,
));
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart
index 753868a9..f4d14662 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart
@@ -45,7 +45,7 @@ class ShowPictureDialog extends ConsumerWidget {
child: Column(
children: [
Expanded(
- child: _PictureSection(fileId: picture.fileId),
+ child: _PictureSection(picture: picture),
),
_MetadataSection(picture: picture),
_ControlsSection(
@@ -59,24 +59,22 @@ class ShowPictureDialog extends ConsumerWidget {
}
class _PictureSection extends StatelessWidget {
- final String fileId;
+ final PictureEntity picture;
- const _PictureSection({required this.fileId});
+ const _PictureSection({required this.picture});
@override
Widget build(BuildContext context) {
- return Center(
- child: Image.network(
- fileId,
- fit: BoxFit.contain,
- loadingBuilder: (context, child, loadingProgress) {
- if (loadingProgress == null) return child;
- return const Center(child: CircularProgressIndicator());
- },
- errorBuilder: (context, error, stackTrace) {
- return const Icon(Icons.broken_image, size: 64, color: Colors.grey);
- },
- ),
+ if (picture.fileBytes != null) {
+ return Center(
+ child: Image.memory(
+ picture.fileBytes!,
+ fit: BoxFit.contain,
+ ),
+ );
+ }
+ return const Center(
+ child: Icon(Icons.broken_image, size: 64, color: Colors.grey),
);
}
}
diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart
index 7290c8a5..d8da3488 100644
--- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart
@@ -2,6 +2,7 @@ import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_model.dart';
+import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_state.dart';
import 'package:sf_localizations/sf_localizations.dart';
import 'package:utils/utils.dart';
@@ -13,26 +14,39 @@ class SpyCallDialog extends ConsumerWidget {
final theme = ref.watch(themePortProvider);
final vm = ref.read(remoteConnectionViewModelProvider.notifier);
- ref.listen(remoteConnectionViewModelProvider.select((s) => s.errorMessage),
- (_, msg) {
- if (msg.isNotEmpty) {
- showTopSnackbar(context,
- message: context.translate(msg), type: MessageType.error);
- }
- });
-
- ref.listen(remoteConnectionViewModelProvider.select((s) => s.isCalling),
- (prev, isCalling) {
- if (prev == true && !isCalling) {
- final error = ref.read(remoteConnectionViewModelProvider).errorMessage;
- if (error.isEmpty && context.mounted) {
- Navigator.pop(context);
- showTopSnackbar(context,
- message: context.translate(I18n.remoteListening),
- type: MessageType.success);
+ ref.listen(
+ remoteConnectionViewModelProvider.select((s) => s.errorEvent),
+ (_, next) {
+ if (next != null) {
+ final message = switch (next) {
+ RemoteConnectionErrorEvent.invalidPhone =>
+ context.translate(I18n.errorMessagePhoneIsInvalid),
+ RemoteConnectionErrorEvent.call =>
+ context.translate(I18n.errorCall),
+ RemoteConnectionErrorEvent.takePicture =>
+ context.translate(I18n.errorTakePicture),
+ RemoteConnectionErrorEvent.fetchPhotos =>
+ context.translate(I18n.errorFetchPhotos),
+ };
+ showTopSnackbar(context, message: message, type: MessageType.error);
}
- }
- });
+ },
+ );
+
+ ref.listen(
+ remoteConnectionViewModelProvider.select((s) => s.isCalling),
+ (prev, isCalling) {
+ if (prev == true && !isCalling) {
+ final error = ref.read(remoteConnectionViewModelProvider).errorEvent;
+ if (error == null && context.mounted) {
+ Navigator.pop(context);
+ showTopSnackbar(context,
+ message: context.translate(I18n.remoteListening),
+ type: MessageType.success);
+ }
+ }
+ },
+ );
return Container(
padding: SizeUtils.getByScreen(
diff --git a/modules/legacy/modules/device_management/lib/src/features/volume_control/presentation/state/volume_control_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/volume_control/presentation/state/volume_control_view_model.dart
index 86d73db7..6e422ba1 100644
--- a/modules/legacy/modules/device_management/lib/src/features/volume_control/presentation/state/volume_control_view_model.dart
+++ b/modules/legacy/modules/device_management/lib/src/features/volume_control/presentation/state/volume_control_view_model.dart
@@ -64,6 +64,7 @@ class VolumeControlViewModel extends Notifier {
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isLoading: false, isComplete: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/state/location_view_model.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/state/location_view_model.dart
index e9ee650b..b542a131 100644
--- a/modules/legacy/modules/location/lib/src/features/location/presentation/state/location_view_model.dart
+++ b/modules/legacy/modules/location/lib/src/features/location/presentation/state/location_view_model.dart
@@ -24,7 +24,7 @@ class LocationViewModel extends Notifier {
@override
LocationViewState build() {
_locationRepository = ref.read(locationRepositoryProvider);
- final device = ref.watch(selectedDeviceProvider);
+ final device = ref.read(selectedDeviceProvider);
if (device != null) {
_fetchData(device.id);
}
@@ -282,6 +282,7 @@ class LocationViewModel extends Notifier {
);
if (!ref.mounted) return false;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isSubmitting: false);
return true;
} catch (e) {
diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart
index ab92d9f7..699ed0ed 100644
--- a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart
+++ b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart
@@ -566,7 +566,7 @@ class _LocationMapState extends ConsumerState
const SizedBox(height: 8),
FrequencySelector(
currentFrequency:
- widget.selectedDevice!.settings.frequency,
+ ref.watch(selectedDeviceProvider)?.settings.frequency ?? 60,
options:
widget.selectedDevice!.capabilities!.location!.options,
onChanged: _updateFrequency,
diff --git a/modules/legacy/modules/settings/lib/src/features/alerts/presentation/state/alerts_view_model.dart b/modules/legacy/modules/settings/lib/src/features/alerts/presentation/state/alerts_view_model.dart
index 7063f8f8..03769872 100644
--- a/modules/legacy/modules/settings/lib/src/features/alerts/presentation/state/alerts_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/alerts/presentation/state/alerts_view_model.dart
@@ -57,6 +57,7 @@ class AlertsViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isSaving: false, saveSuccess: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/modules/settings/lib/src/features/battery/presentation/state/battery_view_model.dart b/modules/legacy/modules/settings/lib/src/features/battery/presentation/state/battery_view_model.dart
index 3d75ebe7..17ac7d36 100644
--- a/modules/legacy/modules/settings/lib/src/features/battery/presentation/state/battery_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/battery/presentation/state/battery_view_model.dart
@@ -41,6 +41,7 @@ class BatteryViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(
nightMode: value,
isSaving: false,
diff --git a/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/state/disable_functions_view_model.dart b/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/state/disable_functions_view_model.dart
index 432e789b..3096848b 100644
--- a/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/state/disable_functions_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/state/disable_functions_view_model.dart
@@ -53,6 +53,7 @@ class DisableFunctionsViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isSaving: false, saveSuccess: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/modules/settings/lib/src/features/language/presentation/state/language_view_model.dart b/modules/legacy/modules/settings/lib/src/features/language/presentation/state/language_view_model.dart
index 689eb3ed..29493337 100644
--- a/modules/legacy/modules/settings/lib/src/features/language/presentation/state/language_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/language/presentation/state/language_view_model.dart
@@ -57,6 +57,10 @@ class LanguageViewModel extends Notifier {
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(
+ device,
+ device.settings.copyWith(language: state.language),
+ );
state = state.copyWith(isLoading: false, isComplete: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/modules/settings/lib/src/features/sound/presentation/state/sound_view_model.dart b/modules/legacy/modules/settings/lib/src/features/sound/presentation/state/sound_view_model.dart
index f515d0d0..d13c6bb9 100644
--- a/modules/legacy/modules/settings/lib/src/features/sound/presentation/state/sound_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/sound/presentation/state/sound_view_model.dart
@@ -60,6 +60,7 @@ class SoundViewModel extends Notifier {
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isLoading: false, isComplete: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/modules/settings/lib/src/features/timezone/presentation/state/timezone_view_model.dart b/modules/legacy/modules/settings/lib/src/features/timezone/presentation/state/timezone_view_model.dart
index 4b95ba92..3e0cf2ea 100644
--- a/modules/legacy/modules/settings/lib/src/features/timezone/presentation/state/timezone_view_model.dart
+++ b/modules/legacy/modules/settings/lib/src/features/timezone/presentation/state/timezone_view_model.dart
@@ -52,6 +52,7 @@ class TimezoneViewModel extends Notifier {
updatedSettings: updatedSettings,
);
if (!ref.mounted) return;
+ ref.syncDeviceSettings(device, updatedSettings);
state = state.copyWith(isSaving: false, saveSuccess: true);
} catch (e) {
if (!ref.mounted) return;
diff --git a/modules/legacy/packages/legacy_shared/lib/src/data/datasources/commands_remote_datasource_impl.dart b/modules/legacy/packages/legacy_shared/lib/src/data/datasources/commands_remote_datasource_impl.dart
index bd5930b8..236e8764 100644
--- a/modules/legacy/packages/legacy_shared/lib/src/data/datasources/commands_remote_datasource_impl.dart
+++ b/modules/legacy/packages/legacy_shared/lib/src/data/datasources/commands_remote_datasource_impl.dart
@@ -14,7 +14,7 @@ class CommandsRemoteDatasourceImpl implements CommandsRemoteDatasource {
required SendCommandRequestModel request,
}) async {
await safeCall(
- () => _repository.post