From ea6b45388fbfa650b09d2e4397583975d6260e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Kunz?= Date: Sat, 18 Apr 2026 01:05:22 +0200 Subject: [PATCH] Refocus app around identity proof flows --- .gitignore | 1 + .../AppIcon.appiconset/Contents.json | 36 + .../ios-marketing-1024@1x.png | Bin 0 -> 57018 bytes .../AppIcon.appiconset/ipad-20@1x.png | Bin 0 -> 1006 bytes .../AppIcon.appiconset/ipad-20@2x.png | Bin 0 -> 2570 bytes .../AppIcon.appiconset/ipad-29@1x.png | Bin 0 -> 1629 bytes .../AppIcon.appiconset/ipad-29@2x.png | Bin 0 -> 4184 bytes .../AppIcon.appiconset/ipad-40@1x.png | Bin 0 -> 2570 bytes .../AppIcon.appiconset/ipad-40@2x.png | Bin 0 -> 6002 bytes .../AppIcon.appiconset/ipad-76@1x.png | Bin 0 -> 5736 bytes .../AppIcon.appiconset/ipad-76@2x.png | Bin 0 -> 12723 bytes .../AppIcon.appiconset/ipad-83.5@2x.png | Bin 0 -> 14346 bytes .../AppIcon.appiconset/iphone-20@2x.png | Bin 0 -> 2570 bytes .../AppIcon.appiconset/iphone-20@3x.png | Bin 0 -> 4233 bytes .../AppIcon.appiconset/iphone-29@2x.png | Bin 0 -> 4184 bytes .../AppIcon.appiconset/iphone-29@3x.png | Bin 0 -> 6716 bytes .../AppIcon.appiconset/iphone-40@2x.png | Bin 0 -> 6002 bytes .../AppIcon.appiconset/iphone-40@3x.png | Bin 0 -> 9707 bytes .../AppIcon.appiconset/iphone-60@2x.png | Bin 0 -> 9707 bytes .../AppIcon.appiconset/iphone-60@3x.png | Bin 0 -> 15819 bytes .../AppIcon.appiconset/mac-128@1x.png | Bin 0 -> 10532 bytes .../AppIcon.appiconset/mac-128@2x.png | Bin 0 -> 24261 bytes .../AppIcon.appiconset/mac-16@1x.png | Bin 0 -> 776 bytes .../AppIcon.appiconset/mac-16@2x.png | Bin 0 -> 1884 bytes .../AppIcon.appiconset/mac-256@1x.png | Bin 0 -> 24261 bytes .../AppIcon.appiconset/mac-256@2x.png | Bin 0 -> 54094 bytes .../AppIcon.appiconset/mac-32@1x.png | Bin 0 -> 1884 bytes .../AppIcon.appiconset/mac-32@2x.png | Bin 0 -> 4575 bytes .../AppIcon.appiconset/mac-512@1x.png | Bin 0 -> 54094 bytes .../AppIcon.appiconset/mac-512@2x.png | Bin 0 -> 57018 bytes Assets.xcassets/Contents.json | 6 + IDPGlobal.entitlements | 10 + IDPGlobal.xcodeproj/project.pbxproj | 215 +- README.md | 103 +- Sources/App/AppComponents.swift | 409 ++ Sources/App/AppViewModel.swift | 130 +- Sources/App/IDPGlobalApp.swift | 17 +- Sources/Core/Models/AppModels.swift | 185 +- Sources/Core/Services/MockIDPService.swift | 165 +- Sources/Features/Auth/LoginRootView.swift | 331 +- Sources/Features/Auth/NFCPairingView.swift | 296 ++ Sources/Features/Auth/QRScannerView.swift | 96 +- Sources/Features/Home/HomeRootView.swift | 3431 ++++------------- WatchApp/App/IDPGlobalWatchApp.swift | 33 + WatchApp/Features/WatchRootView.swift | 479 +++ 45 files changed, 2784 insertions(+), 3159 deletions(-) create mode 100644 Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Assets.xcassets/AppIcon.appiconset/ios-marketing-1024@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-20@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-20@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-29@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-29@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-40@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-40@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-76@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-76@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/ipad-83.5@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-20@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-20@3x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-29@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-29@3x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-40@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-40@3x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-60@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/iphone-60@3x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-128@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-128@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-16@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-16@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-256@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-256@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-32@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-32@2x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-512@1x.png create mode 100644 Assets.xcassets/AppIcon.appiconset/mac-512@2x.png create mode 100644 Assets.xcassets/Contents.json create mode 100644 IDPGlobal.entitlements create mode 100644 Sources/App/AppComponents.swift create mode 100644 Sources/Features/Auth/NFCPairingView.swift create mode 100644 WatchApp/App/IDPGlobalWatchApp.swift create mode 100644 WatchApp/Features/WatchRootView.swift diff --git a/.gitignore b/.gitignore index e8c1e30..b5a1f02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +agentcomms/ build/ DerivedData/ xcuserdata/ diff --git a/Assets.xcassets/AppIcon.appiconset/Contents.json b/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..fedfcea --- /dev/null +++ b/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { "filename" : "iphone-20@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "20x20" }, + { "filename" : "iphone-20@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "20x20" }, + { "filename" : "iphone-29@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "29x29" }, + { "filename" : "iphone-29@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "29x29" }, + { "filename" : "iphone-40@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "40x40" }, + { "filename" : "iphone-40@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "40x40" }, + { "filename" : "iphone-60@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "60x60" }, + { "filename" : "iphone-60@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "60x60" }, + { "filename" : "ipad-20@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" }, + { "filename" : "ipad-20@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" }, + { "filename" : "ipad-29@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" }, + { "filename" : "ipad-29@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" }, + { "filename" : "ipad-40@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" }, + { "filename" : "ipad-40@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" }, + { "filename" : "ipad-76@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "76x76" }, + { "filename" : "ipad-76@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" }, + { "filename" : "ipad-83.5@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" }, + { "filename" : "ios-marketing-1024@1x.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" }, + { "filename" : "mac-16@1x.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, + { "filename" : "mac-16@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, + { "filename" : "mac-32@1x.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, + { "filename" : "mac-32@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, + { "filename" : "mac-128@1x.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, + { "filename" : "mac-128@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, + { "filename" : "mac-256@1x.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, + { "filename" : "mac-256@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, + { "filename" : "mac-512@1x.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, + { "filename" : "mac-512@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Assets.xcassets/AppIcon.appiconset/ios-marketing-1024@1x.png b/Assets.xcassets/AppIcon.appiconset/ios-marketing-1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b0e8250be0657aaa7cda2cdb84d9cc06a1e1654 GIT binary patch literal 57018 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

d_K8TV&zJZl>6X@~E)(xjo`_4kWdqN$7 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-20@1x.png b/Assets.xcassets/AppIcon.appiconset/ipad-20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..54896474192b04ea6c6697bd0bec42d113b5bfb4 GIT binary patch literal 1006 zcmVd~{i`H{v_(`?m8_ z1m5+5P$D-2&2_LKqApfJ+aN%%MXRLLdRC)$7vQ#=msw z!W*>k#aA?a@-(`gu0Uj5DQXJ~N321~P9P>QqgJhA;pR^rK_n)C-NZny_6V*NxZ7Lkc|?(C#@DKEQcKzw~Hzi=FNaBCSFIC$QG&V7=AHdaH+jntg0^imfj1vT=MY$`UMnIPX!dRA8*dqt#W^A3ns- z^?F)2GCYg`LJ=gI5hZi99aN{=g)dzkf%v{He} zOb|wJC8V=C!W+#-Vyh@e2p)^~>-hf89ejA{1N`*Ox5%;#P=b3)OQ{NMx!G6)#d>G- zq6Gqn#Pr_s5|$tRj+M1F+6_3cP=qjicnu(PX9P1rzC#-PGfVgM{1H; zd$)9Hgd{Li^k1(iP_Y@b*65dIYEUdU9tcsU%wC673Yu$-NJDZWW^fucUhLPvNXm6z(KGz=79iR&xjedHJYMU32?IoLIhTd z0)eXDyHig(z6POO2$RW^pdvLZ0Kx&JcMX*Q!6V-`?ymUXiJcUWG$47RER0yX+Kabm c?e6{m0R(2={y6E>vH$=807*qoM6N<$g2R~ItpET3 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-20@2x.png b/Assets.xcassets/AppIcon.appiconset/ipad-20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e650447a747e82a7f82958668c78a319011a1e7a GIT binary patch literal 2570 zcmV+l3ib7gP)2({Rf zkl(z_QPDnq=*-=7tiUw@hTw%(k|xtap4O3?kU}><2!Rb#WQ z#@kzkk}_CNJLoxAKY&4KEh8n5S8A0L*10vA$#!^WZwTJ6Dl|mLf({}$n$l`1rsKGD zx>l(jO|oQn277OCY|g8K?6r^=Qp##vehVVl`DXJVfI7`U!4sr}_kNX;NTFL?a4-&= zthb{{2+c~l@`p&r=bK6M(cr^X-7T-`R;6S$j^Fm))f1CF8l0?;p+nfdZ95j`X7Rn3Uc!mfr%^4H;MsjwHcI?I3t%8BQ4nX1vFn7CPb- z1#=4x{PNA;V0dr{j>gg6w20EoZq`zbx!`Z3Fj!2QB^QSfhAcW*QAl&dzeVs#hwwJUa`Ywy<&S z`sGYY6cYlh&2FZ(8CF>8vcknwg3$8LjdbJIN?~et7SF!?GQP5F6sN||;h*E{h9yL@vJP|sECva2MYUU{ya$%q*+ECxjYc1(esKyqtl3~nrvXxo-8n4g==cdrzT zwfsp5N@y};(atQ4b@_Ozp!A5TGB9{+9ealEsHLn%&_YzyPNGc>a`m8;YbZYrCdQPwP>XVNoE*qnptGVAvF%| zG~Yn0ZTPyT1vzFzK&4b-O-H*MPzsfDnO%??gPS&N!2S2!gQU^me$(^w_{l4;;MDo^ z?CwKPKh4_Dq;2fI>uwC!hcMSn5Ni!793)9GArXYZLTccw%fle_Q4%X#p5zqhG@0nQ z*AxJU1_qE>i*lucH{O3AZy!0rmVfo|VZ49zC~CDDhsnmZYq4ql1~k(Q#s{>mLy|eR zC|Q!MmstTwkyyBoQSl7lX?YBzXlydKGYN{~X3bv<0xS7%uUDHZRQuKz{z!7~+6 zr62>W+=7w{T4~O1$AT;`91OS!pAJCcFUm6N90^MCxG?|fT3|j~-kai*Dhw|x1jo}d zfLbBa8cJyh;qra~P%45_c_RP9M3Vk}N87<2{Tcb|;oMyZ~k7Vr-C$$o!cx>}JxRFTVN2b>Le#a^&~;)3Lu{pjyojPeNdDU;rn^PUFDy&*R~*?ZsDjjdGGq&CKBA z@p0U}^HyA(oWkqxy~|37#p?29JwhPau#A?(+WYS9BqrIl8khf=S+m7Dx3fsiTn>f6 ziLq{E4W{Sk@&wX4f0eQ%*)Qp+dK5`JTYOGC*Gk~o2X4cS^)ifG%09sX zovY=3vBjh-1!h|res^qw1wp5~4>peVr>(4gf8n)GZmf(!GPi0a$({9T_1#9Ad{a1Y zeF!?%3SS@Hj7`HeWUg!Sq7`OFuSU)w;c&T`;+?;Linej|w+%|_s*c`E(sUF;P>lHQ ziMnGD-LY6N*A826*0hYdkBHnme%&LYq7*GoqNob#ysi>8^u;Iu>-ZxmDP+(JWvPxv zI{H_mogD0ry~TDlbs&jb8cFk!NbAYLQspfOkw~qiQc~CuD8>2U5{lPTtGoogCQ@1o zMZ1);U5m=^L{WU9k+dGY8n|8-T-vb|q7=n{t(Ge%Gi%nHEZbq7yMYeei=C8|h-3s6 zkp=s|IusCADK)L*_-sk3&yp;?t(}=Y%=|q@_5;`fNfwQx=wq#;3rfmXH%UlISxhQK zaV_ny(TR3k#TdKASaUn`Qy*~DuBE6M9L=0ryDM{c*Ge5G3qB+jLJH+tMPeD29&WuJ zfQ*5EQ+9RpV)vojk*4dMtNXtp=EDv5pn0#Ukgw-V(qpoaiwKH_;%w2kUFX^2zt;GR g9%mK)1^h$fKR!!|LHWSG=>Px#07*qoM6N<$f*v38$p8QV literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-29@1x.png b/Assets.xcassets/AppIcon.appiconset/ipad-29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba88e31512bf6185c511eeb53d1cc60fd5c5200 GIT binary patch literal 1629 zcmV-j2BP_iP)A7%75?tI_r962ohWib;smD-;G}A*xT3`}psG#9&yGbK0a6f1Eu~f0RjHaTLl*41 z=n6GkmffQ+_z^;+!6+mm5)gibl>~xgdz_g!@4fqT(7A8M_0KrTqE~vFc{BH(@BDn{ zJ6ApU%u|g2!-_G$RTVfm7-D3GK%_S9VfYYXZexf058VwYDTT~xfFcMnl2U@W0actZ zplv}Js$LwUyt_MrY6T=1t*jzVUv=>*8QkL`1oVm`rKw>pthIgMt&z&!yzHQrWm+OEe6`<@nYY@U zcL=jAEb4naK<89I;5$va?K#ed;DZAAuP?lSf4=;(+B-h3ocH~0{Q#wmN+}sF_kY0IGylMgzj+pUQApBA>RI}7##sAlzbd>wy_CXNs)`(U ztEf~n%W!330q>qahsk~W@Xmz`kl$jA2`n#)^nK5+UDz?w!qol)VAsR+!Kp!is+z$V zSET&thTJ3i6;_1_{#=wPu9j#W{*vWJJkPMGqDU65{QYxiz zYjqV`Yd9a!Eh;n{jhbX6N)%HWLb#10iMsU464M6{;^dQ0!i?;~n;(3D*WY*pqpcSH zeDWklnoV@NUA%wk5;PGWnVCTh0r!mWhL41mP64Y4q7yMHUS#qPOGqP;B)&5zGRZq>jW4fWg_RbG5uYtAK=t>wnoWer2n@Iw;W)xYMr0+u z3G&{joZs!JSuYMo2 zS5hsH9XW!>W@qvGE3ZJ4#@w-EBKE1aUtPbBW+Mal+f>VAG$^W?4}(ZVFr+@h&|X<2 z0T2fy3u&4&qi_}4oi0wF{a12E+UK#khjDy%HW@O_Ccax-&`Btwij`ybrimJko4&8_GojdW~#gEcxQ&1^&MOh)sEGGBv zO$1!&+``V$QQTNs+Q4L4tw!_BURnHdv-U>eIWuRZXelC&_j^)(^3|6q^<%Bpnly^i zjPBf#YWD5T#l%@D!%}+%&CJ5f>_9!aNMQwF15%U>0W<(jT&}!3+{m(vJy-oIh7iV@ zhF<&K<7&@X6Q%R@9Y|sweAX$cy=G3%tmG9={rf|1=Pnvcx}ojG(zzr3KC4fzPp?>L zSbH7}T?F@2$;F}FW5~3O#u`8(l@<_*+`Qx`7ou8N&LwroNMBHdvh-mt)nEwdTAG`g zeP1cci>mr@uX6VYuLiNDhPT<4JM9`U5L=m9Y}o8$1{y_GJ__D=N7@X!7O^I}mRWm6 z6IB3f0Zwh91=K?6VUen+OHiU z<{NUFk)_=8now`qwcQX;!0T@KS#7Ttk(90Nufg@E|6Sg;tlNz?Ik4sbq`P+>403LG b(E)r9Las;GT!mPL00000NkvXXu0mjf^%52f literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-29@2x.png b/Assets.xcassets/AppIcon.appiconset/ipad-29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..33e0f68453fe9bd1f09095de81a318f81ce4c6ce GIT binary patch literal 4184 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 ib4gS2({Rf zkl(z_QPDnq=*-=7tiUw@hTw%(k|xtap4O3?kU}><2!Rb#WQ z#@kzkk}_CNJLoxAKY&4KEh8n5S8A0L*10vA$#!^WZwTJ6Dl|mLf({}$n$l`1rsKGD zx>l(jO|oQn277OCY|g8K?6r^=Qp##vehVVl`DXJVfI7`U!4sr}_kNX;NTFL?a4-&= zthb{{2+c~l@`p&r=bK6M(cr^X-7T-`R;6S$j^Fm))f1CF8l0?;p+nfdZ95j`X7Rn3Uc!mfr%^4H;MsjwHcI?I3t%8BQ4nX1vFn7CPb- z1#=4x{PNA;V0dr{j>gg6w20EoZq`zbx!`Z3Fj!2QB^QSfhAcW*QAl&dzeVs#hwwJUa`Ywy<&S z`sGYY6cYlh&2FZ(8CF>8vcknwg3$8LjdbJIN?~et7SF!?GQP5F6sN||;h*E{h9yL@vJP|sECva2MYUU{ya$%q*+ECxjYc1(esKyqtl3~nrvXxo-8n4g==cdrzT zwfsp5N@y};(atQ4b@_Ozp!A5TGB9{+9ealEsHLn%&_YzyPNGc>a`m8;YbZYrCdQPwP>XVNoE*qnptGVAvF%| zG~Yn0ZTPyT1vzFzK&4b-O-H*MPzsfDnO%??gPS&N!2S2!gQU^me$(^w_{l4;;MDo^ z?CwKPKh4_Dq;2fI>uwC!hcMSn5Ni!793)9GArXYZLTccw%fle_Q4%X#p5zqhG@0nQ z*AxJU1_qE>i*lucH{O3AZy!0rmVfo|VZ49zC~CDDhsnmZYq4ql1~k(Q#s{>mLy|eR zC|Q!MmstTwkyyBoQSl7lX?YBzXlydKGYN{~X3bv<0xS7%uUDHZRQuKz{z!7~+6 zr62>W+=7w{T4~O1$AT;`91OS!pAJCcFUm6N90^MCxG?|fT3|j~-kai*Dhw|x1jo}d zfLbBa8cJyh;qra~P%45_c_RP9M3Vk}N87<2{Tcb|;oMyZ~k7Vr-C$$o!cx>}JxRFTVN2b>Le#a^&~;)3Lu{pjyojPeNdDU;rn^PUFDy&*R~*?ZsDjjdGGq&CKBA z@p0U}^HyA(oWkqxy~|37#p?29JwhPau#A?(+WYS9BqrIl8khf=S+m7Dx3fsiTn>f6 ziLq{E4W{Sk@&wX4f0eQ%*)Qp+dK5`JTYOGC*Gk~o2X4cS^)ifG%09sX zovY=3vBjh-1!h|res^qw1wp5~4>peVr>(4gf8n)GZmf(!GPi0a$({9T_1#9Ad{a1Y zeF!?%3SS@Hj7`HeWUg!Sq7`OFuSU)w;c&T`;+?;Linej|w+%|_s*c`E(sUF;P>lHQ ziMnGD-LY6N*A826*0hYdkBHnme%&LYq7*GoqNob#ysi>8^u;Iu>-ZxmDP+(JWvPxv zI{H_mogD0ry~TDlbs&jb8cFk!NbAYLQspfOkw~qiQc~CuD8>2U5{lPTtGoogCQ@1o zMZ1);U5m=^L{WU9k+dGY8n|8-T-vb|q7=n{t(Ge%Gi%nHEZbq7yMYeei=C8|h-3s6 zkp=s|IusCADK)L*_-sk3&yp;?t(}=Y%=|q@_5;`fNfwQx=wq#;3rfmXH%UlISxhQK zaV_ny(TR3k#TdKASaUn`Qy*~DuBE6M9L=0ryDM{c*Ge5G3qB+jLJH+tMPeD29&WuJ zfQ*5EQ+9RpV)vojk*4dMtNXtp=EDv5pn0#Ukgw-V(qpoaiwKH_;%w2kUFX^2zt;GR g9%mK)1^h$fKR!!|LHWSG=>Px#07*qoM6N<$f*v38$p8QV literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-40@2x.png b/Assets.xcassets/AppIcon.appiconset/ipad-40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..03e3ae1bac4cec0875fd93a3baad93681a36d206 GIT binary patch literal 6002 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-76@1x.png b/Assets.xcassets/AppIcon.appiconset/ipad-76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..a8b80ce915b38acec00dab75677273a21095611e GIT binary patch literal 5736 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/ipad-83.5@2x.png b/Assets.xcassets/AppIcon.appiconset/ipad-83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0c93e1e498a1dd2db2c92e72a63c60f0f990cf57 GIT binary patch literal 14346 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/iphone-20@3x.png b/Assets.xcassets/AppIcon.appiconset/iphone-20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a61951db9beb02451653f034e9328be62bd05f GIT binary patch literal 4233 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/iphone-29@2x.png b/Assets.xcassets/AppIcon.appiconset/iphone-29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..33e0f68453fe9bd1f09095de81a318f81ce4c6ce GIT binary patch literal 4184 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 ib4gS3 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/iphone-40@3x.png b/Assets.xcassets/AppIcon.appiconset/iphone-40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..22dfc7b50eca581242da6bbdd12de43fd29e9959 GIT binary patch literal 9707 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/iphone-60@2x.png b/Assets.xcassets/AppIcon.appiconset/iphone-60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..22dfc7b50eca581242da6bbdd12de43fd29e9959 GIT binary patch literal 9707 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/iphone-60@3x.png b/Assets.xcassets/AppIcon.appiconset/iphone-60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2d7ffde8217e3b2751bf5c6664e988643ced7a64 GIT binary patch literal 15819 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 X|{b)iGpxtr6! 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 VvR{oM?&tsj002ovPDHLkV1nJPuw?)M literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/mac-128@1x.png b/Assets.xcassets/AppIcon.appiconset/mac-128@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ecb20c67133e16344d5cb03a2f1ec9c79cfb4b3 GIT binary patch literal 10532 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/mac-16@1x.png b/Assets.xcassets/AppIcon.appiconset/mac-16@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..65f121aba4184b0de60422d04f06a2a83c224dcb GIT binary patch literal 776 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/mac-256@2x.png b/Assets.xcassets/AppIcon.appiconset/mac-256@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8d35f2ed796025f6b8962532d3146ed39cfc2f3 GIT binary patch literal 54094 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/mac-32@1x.png b/Assets.xcassets/AppIcon.appiconset/mac-32@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..f7be521622d72297743832956362d88f366b3443 GIT binary patch literal 1884 zcmV-i2c!6jP)(L+2@?OWHOVCO_P*#OweemHV~&`;-EhDH`*7UMEg(+ElBCR z2;x&H^dV1`3KBs=G=w5TRi=_lQzcF$x0B4AvoHTu*1yj=IZn(fv-(KU`r$bDI+NGh5&>x(Dff{36Kn8jA@2WF$OOMeISLr10uU#$$H~# zkR7HFIcC~Bx6M)fDBFqrZp3~yLRTOqgqCtSQ_aiH`+4X6&KP4WhDZS4W4uQMMIQw@ zUQ|e>ZZ>4LY^~d8;hu^ig+q)75D`cUkx6|?2z0t-@vIOsGu9%;h)k;#(Q#p5x0T@k z2_blR>lciPwwYxYi1bC{?B}Bo0rU`r7~apul@ON&&?%iej)*MJ^RRVtGCnpt8}p(} zAs8q8UtZ+#?)`Qw%Q7N_5M$Jpw?_%66v_A5Mz1Cw0e~2z%e4MmVXC9#L#T|w$M@_J zZ@&5}oqhdvT6+3v%FB`j7iK@|y;}-Fl`(Yalb@m=eftI4`@|lqtQACr;6f;^`C^u- zD+tjH+Y|%ug&-y9@7B2;NgEN0s>0%d1K7QL0W-7n_|l<6sH_G5*O%HMAg?MkvIc(g zy%+HOsc+(k&wn?iZBQeE$T+`CDtVos`%zGX`&Yiw1e28ohKtDTUkZHoo!l%QbN*1qQ_(l{zg(eE-xboLpMM-1Ib@cW7n}NTCq; z3K2qbNe*meM8YPI6Rx;16SAih%_e^Q+;hpxH_n_vduF6`QcPb}=ioz)KV%3-ar zSj#Os{971wD~rPTjREv)K?so|!q2Rnfy_=%r`&R@{`TE>Q|>uJe_UQhqtSqr67$>U zV4R1IK;;6;bbA;V;9@!{z#N@Ac`V6q0$`ngR}(_NMSCsC;EDKjWIMH?IMl|fG*$9W z^UMEYG8kU!y-xr*I>Ws$g@n=?O3HzgL~_u=2|zdRLP>=z21pQmWU}wI&XBUcSG=+A z<62l*C(mJ>L&;~x5HzJ^(#`Elp=RJrDHtc=d%8qv42rTuH_y>6auh{@vMf_>jj^e< zdX~~Nzkjf{hWo3l$yBq^z_Uk=B-Z@&zI|9c@D!@5O3K@-YtTxj>aXiaK}ZR$bV^$S z$4Xob@Ww!rfOkGMtd&kcgq5;W)o-L z`8Cd6IFFgR`Lt&LlTTvn)D&U}Xy^=iSz;~Ed)+gXM$sGHI3iMxZo?W(fRF+o{_AF) zE7io+8#mI%UV-2{uf2w!zx5{ColXMHMsMD|lM3?UpWjPtnbwaIE=mGu`_iF$cq0-& zx)~6A%3V;0RV1EoWEztV4K30<8~D#m%0Gn|CtUFR(`kl>r(tSL7s8%aqq$re!`>$r z+dVglH%@=9=5b%QA3Md~_eqC;>*xBEOOz5LesTT^{&BC1Ow}x^wZ75K^REm~$!c9@ zbYZHGwVKV}mDcbW1@B|HwOSC*K>b~8jEie{Fc~E-q$xI)eM_kG#+tnlB1^gHd%nF+ zL0dyLjB}sq=Y4n~jQ~(9sN-vu zl-HDycS-PvN&QWrNJ94_z+Xb6_QwF_gWqPI+Y3S2DC0@j$nCwNl W@Zia{uAol<00001 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/AppIcon.appiconset/mac-512@2x.png b/Assets.xcassets/AppIcon.appiconset/mac-512@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b0e8250be0657aaa7cda2cdb84d9cc06a1e1654 GIT binary patch literal 57018 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

d_K8TV&zJZl>6X@~E)(xjo`_4kWdqN$7 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 literal 0 HcmV?d00001 diff --git a/Assets.xcassets/Contents.json b/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IDPGlobal.entitlements b/IDPGlobal.entitlements new file mode 100644 index 0000000..5f7b942 --- /dev/null +++ b/IDPGlobal.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.developer.nfc.readersession.formats + + NDEF + + + diff --git a/IDPGlobal.xcodeproj/project.pbxproj b/IDPGlobal.xcodeproj/project.pbxproj index 575f3f6..7ec2d5b 100644 --- a/IDPGlobal.xcodeproj/project.pbxproj +++ b/IDPGlobal.xcodeproj/project.pbxproj @@ -15,8 +15,43 @@ B10000000000000000000006 /* LoginRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000006 /* LoginRootView.swift */; }; B10000000000000000000007 /* QRScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000007 /* QRScannerView.swift */; }; B10000000000000000000008 /* HomeRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000008 /* HomeRootView.swift */; }; + B10000000000000000000009 /* AppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000002 /* AppViewModel.swift */; }; + B1000000000000000000000A /* AppModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000003 /* AppModels.swift */; }; + B1000000000000000000000B /* MockIDPService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000004 /* MockIDPService.swift */; }; + B1000000000000000000000C /* NotificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000000000000000000005 /* NotificationCoordinator.swift */; }; + B1000000000000000000000D /* IDPGlobalWatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000B /* IDPGlobalWatchApp.swift */; }; + B1000000000000000000000E /* WatchRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000C /* WatchRootView.swift */; }; + B1000000000000000000000F /* IDPGlobalWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000A /* IDPGlobalWatch.app */; platformFilter = ios; }; + B10000000000000000000010 /* NFCPairingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000D /* NFCPairingView.swift */; }; + B10000000000000000000011 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000E /* Assets.xcassets */; }; + B10000000000000000000012 /* AppComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000F /* AppComponents.swift */; }; + B10000000000000000000013 /* AppComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000000000000000000000F /* AppComponents.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + B90000000000000000000001 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B60000000000000000000001 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B50000000000000000000002; + remoteInfo = IDPGlobalWatch; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + B30000000000000000000004 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + B1000000000000000000000F /* IDPGlobalWatch.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ B20000000000000000000001 /* IDPGlobalApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDPGlobalApp.swift; sourceTree = ""; }; B20000000000000000000002 /* AppViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppViewModel.swift; sourceTree = ""; }; @@ -27,6 +62,12 @@ B20000000000000000000007 /* QRScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerView.swift; sourceTree = ""; }; B20000000000000000000008 /* HomeRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRootView.swift; sourceTree = ""; }; B20000000000000000000009 /* IDPGlobal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IDPGlobal.app; sourceTree = BUILT_PRODUCTS_DIR; }; + B2000000000000000000000A /* IDPGlobalWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IDPGlobalWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + B2000000000000000000000B /* IDPGlobalWatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDPGlobalWatchApp.swift; sourceTree = ""; }; + B2000000000000000000000C /* WatchRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchRootView.swift; sourceTree = ""; }; + B2000000000000000000000D /* NFCPairingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NFCPairingView.swift; sourceTree = ""; }; + B2000000000000000000000E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + B2000000000000000000000F /* AppComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppComponents.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -37,6 +78,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B30000000000000000000005 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -51,7 +99,9 @@ B40000000000000000000002 /* IDPGlobal */ = { isa = PBXGroup; children = ( + B2000000000000000000000E /* Assets.xcassets */, B40000000000000000000003 /* Sources */, + B4000000000000000000000C /* WatchApp */, ); name = IDPGlobal; sourceTree = ""; @@ -69,6 +119,7 @@ B40000000000000000000004 /* App */ = { isa = PBXGroup; children = ( + B2000000000000000000000F /* AppComponents.swift */, B20000000000000000000001 /* IDPGlobalApp.swift */, B20000000000000000000002 /* AppViewModel.swift */, ); @@ -114,6 +165,7 @@ isa = PBXGroup; children = ( B20000000000000000000009 /* IDPGlobal.app */, + B2000000000000000000000A /* IDPGlobalWatch.app */, ); name = Products; sourceTree = ""; @@ -122,6 +174,7 @@ isa = PBXGroup; children = ( B20000000000000000000006 /* LoginRootView.swift */, + B2000000000000000000000D /* NFCPairingView.swift */, B20000000000000000000007 /* QRScannerView.swift */, ); path = Auth; @@ -135,6 +188,31 @@ path = Home; sourceTree = ""; }; + B4000000000000000000000C /* WatchApp */ = { + isa = PBXGroup; + children = ( + B4000000000000000000000D /* App */, + B4000000000000000000000E /* Features */, + ); + path = WatchApp; + sourceTree = ""; + }; + B4000000000000000000000D /* App */ = { + isa = PBXGroup; + children = ( + B2000000000000000000000B /* IDPGlobalWatchApp.swift */, + ); + path = App; + sourceTree = ""; + }; + B4000000000000000000000E /* Features */ = { + isa = PBXGroup; + children = ( + B2000000000000000000000C /* WatchRootView.swift */, + ); + path = Features; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -145,14 +223,33 @@ B30000000000000000000002 /* Sources */, B30000000000000000000001 /* Frameworks */, B30000000000000000000003 /* Resources */, + B30000000000000000000004 /* Embed Watch Content */, + ); + buildRules = ( + ); + dependencies = ( + B90000000000000000000002 /* PBXTargetDependency */, + ); + name = IDPGlobal; + productName = IDPGlobal; + productReference = B20000000000000000000009 /* IDPGlobal.app */; + productType = "com.apple.product-type.application"; + }; + B50000000000000000000002 /* IDPGlobalWatch */ = { + isa = PBXNativeTarget; + buildConfigurationList = B70000000000000000000003 /* Build configuration list for PBXNativeTarget "IDPGlobalWatch" */; + buildPhases = ( + B30000000000000000000007 /* Sources */, + B30000000000000000000005 /* Frameworks */, + B30000000000000000000006 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = IDPGlobal; - productName = IDPGlobal; - productReference = B20000000000000000000009 /* IDPGlobal.app */; + name = IDPGlobalWatch; + productName = IDPGlobalWatch; + productReference = B2000000000000000000000A /* IDPGlobalWatch.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -168,6 +265,9 @@ B50000000000000000000001 = { CreatedOnToolsVersion = 26.0; }; + B50000000000000000000002 = { + CreatedOnToolsVersion = 26.0; + }; }; }; buildConfigurationList = B70000000000000000000001 /* Build configuration list for PBXProject "IDPGlobal" */; @@ -184,12 +284,21 @@ projectRoot = ""; targets = ( B50000000000000000000001 /* IDPGlobal */, + B50000000000000000000002 /* IDPGlobalWatch */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ B30000000000000000000003 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B10000000000000000000011 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B30000000000000000000006 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -203,19 +312,44 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B10000000000000000000012 /* AppComponents.swift in Sources */, B10000000000000000000002 /* AppViewModel.swift in Sources */, B10000000000000000000008 /* HomeRootView.swift in Sources */, B10000000000000000000001 /* IDPGlobalApp.swift in Sources */, B10000000000000000000006 /* LoginRootView.swift in Sources */, B10000000000000000000004 /* MockIDPService.swift in Sources */, + B10000000000000000000010 /* NFCPairingView.swift in Sources */, B10000000000000000000005 /* NotificationCoordinator.swift in Sources */, B10000000000000000000003 /* AppModels.swift in Sources */, B10000000000000000000007 /* QRScannerView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; + B30000000000000000000007 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B10000000000000000000013 /* AppComponents.swift in Sources */, + B10000000000000000000009 /* AppViewModel.swift in Sources */, + B1000000000000000000000A /* AppModels.swift in Sources */, + B1000000000000000000000D /* IDPGlobalWatchApp.swift in Sources */, + B1000000000000000000000B /* MockIDPService.swift in Sources */, + B1000000000000000000000C /* NotificationCoordinator.swift in Sources */, + B1000000000000000000000E /* WatchRootView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + B90000000000000000000002 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = ios; + target = B50000000000000000000002 /* IDPGlobalWatch */; + targetProxy = B90000000000000000000001 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ B80000000000000000000001 /* Debug */ = { isa = XCBuildConfiguration; @@ -275,7 +409,9 @@ B80000000000000000000003 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = IDPGlobal.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; @@ -284,6 +420,8 @@ INFOPLIST_KEY_CFBundleDisplayName = "idp.global"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; INFOPLIST_KEY_NSCameraUsageDescription = "Scan pairing QR codes from the idp.global web portal."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Attach a signed GPS position to NFC authentication before binding this device."; + INFOPLIST_KEY_NFCReaderUsageDescription = "Read an idp.global pairing tag to bind this device."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; LD_RUNPATH_SEARCH_PATHS = ( @@ -305,7 +443,9 @@ B80000000000000000000004 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = IDPGlobal.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; @@ -314,6 +454,8 @@ INFOPLIST_KEY_CFBundleDisplayName = "idp.global"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; INFOPLIST_KEY_NSCameraUsageDescription = "Scan pairing QR codes from the idp.global web portal."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Attach a signed GPS position to NFC authentication before binding this device."; + INFOPLIST_KEY_NFCReaderUsageDescription = "Read an idp.global pairing tag to bind this device."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; LD_RUNPATH_SEARCH_PATHS = ( @@ -332,6 +474,64 @@ }; name = Release; }; + B80000000000000000000005 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "idp.global Watch"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = global.idp.app; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 0.1.0; + PRODUCT_BUNDLE_IDENTIFIER = global.idp.app.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchos watchsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBSERVATION_ENABLED = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 10.0; + }; + name = Debug; + }; + B80000000000000000000006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "idp.global Watch"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = global.idp.app; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 0.1.0; + PRODUCT_BUNDLE_IDENTIFIER = global.idp.app.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchos watchsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBSERVATION_ENABLED = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 10.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -353,6 +553,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B70000000000000000000003 /* Build configuration list for PBXNativeTarget "IDPGlobalWatch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B80000000000000000000005 /* Debug */, + B80000000000000000000006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = B60000000000000000000001 /* Project object */; diff --git a/README.md b/README.md index c190411..6bd28a8 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,40 @@ # idp.global Swift App -Multiplatform SwiftUI companion app for `idp.global` across iPhone, iPad, and Mac. +Multiplatform SwiftUI scaffold for the personal `idp.global` companion app on iPhone, iPad, Mac, and Apple Watch. -The current build is a polished preview backed by a mock service layer. It already walks through the core product flow: +## Included in this first pass -- bind a device to an account with a QR payload -- review and approve identity or access requests -- track recent security and system events -- manage notification permissions and send a local test alert +- QR and NFC-based device pairing flows with a seeded preview payload fallback +- NFC authentication now attaches a signed GPS position on supported iPhone hardware +- Mocked approval inbox for accepting or rejecting identity requests +- Notification center with local notification permission flow and a test notification trigger +- Apple Watch companion target with a compact approval-first dashboard and request detail flow +- Shared app state and mock backend boundary so a real API can be connected later -## Current Product Surface +## Open the project -After pairing, the app opens into a passport-style dashboard with four sections: +1. Open [IDPGlobal.xcodeproj](/Users/philkunz/gitea/idp.global-swiftapp/IDPGlobal/IDPGlobal.xcodeproj). +2. Build the `IDPGlobal` scheme for: + - `My Mac` + - an iPad simulator + - an iPhone simulator +3. Build the `IDPGlobalWatch` scheme for an Apple Watch simulator when you want to verify the companion experience. -- `Passport`: digital identity summary, trust context, and quick actions -- `Requests`: approval queue with elevated-risk guidance and inline review -- `Activity`: timeline of pairing, approval, and system events -- `Account`: member profile, trusted-device context, and recovery summary +## Mock QR payload -The layout adapts by platform: - -- iPhone uses a compact tab-based container -- iPad and Mac use a split-view workspace with richer side-by-side review - -## Pairing Flow - -The sign-in flow supports: - -- live QR scanning through the camera -- manual payload paste for testing -- a seeded preview payload while the real backend is still being wired up - -Seeded payload on first launch: +The app seeds this pairing payload on first launch: `idp.global://pair?token=swiftapp-demo-berlin&origin=code.foss.global&device=Safari%20on%20Berlin%20MBP` -## Mocked Preview Behavior +You can paste it manually, scan it as a QR code, or use the preview pairing action while the backend is still mocked. -The app currently runs against `MockIDPService`, which seeds: +For NFC authentication, the app reads the pairing payload from the tag, captures the current device location, signs that GPS position, and submits both together. -- a paired member profile -- pending and handled approval requests -- recent notifications and security events -- simulated incoming requests from the toolbar +## Next integration step -This keeps the UI realistic while preserving a clean integration seam for the live backend later. +Replace `MockIDPService` with a live service that: -## Open And Run - -1. Open `IDPGlobal.xcodeproj` in Xcode. -2. Build and run the `IDPGlobal` scheme on: - - `My Mac` - - an iPhone simulator - - an iPad simulator - -You can also build from the command line: - -```bash -xcodebuild -project IDPGlobal.xcodeproj -scheme IDPGlobal -configuration Debug -destination 'platform=macOS' build -``` - -## Useful Preview Launch Arguments - -These launch arguments are already supported by the app model: - -- `--mock-auto-pair`: automatically pair with the seeded preview payload on launch -- `--mock-section=overview` -- `--mock-section=requests` -- `--mock-section=activity` -- `--mock-section=account` -- `--mock-section=notifications`: opens the activity timeline using a notification-friendly alias - -Example: - -```text ---mock-auto-pair --mock-section=requests -``` - -## Project Structure - -- `Sources/App`: app entry point and shared state in `AppViewModel` -- `Sources/Features/Auth`: first-run pairing flow and QR scanner UI -- `Sources/Features/Home`: passport dashboard, requests, activity, notifications, and account surfaces -- `Sources/Core/Models`: app-facing domain models -- `Sources/Core/Services`: mock backend boundary and local notification coordination - -## Next Integration Step - -Replace `MockIDPService` with a live implementation that: - -- exchanges the QR payload for a real session -- loads profile, request, and activity data from the backend +- exchanges the pairing payload and signed NFC location proof for a session token +- loads approval requests and notifications from the backend - posts approval decisions back to `idp.global` -- syncs notification state with server-side events +- syncs session and request state between iPhone and Apple Watch, likely through a shared backend session or WatchConnectivity bridge diff --git a/Sources/App/AppComponents.swift b/Sources/App/AppComponents.swift new file mode 100644 index 0000000..9f2f432 --- /dev/null +++ b/Sources/App/AppComponents.swift @@ -0,0 +1,409 @@ +import SwiftUI + +enum AppTheme { + static let accent = Color(red: 0.12, green: 0.40, blue: 0.31) + static let warmAccent = Color(red: 0.84, green: 0.71, blue: 0.48) + static let border = Color.black.opacity(0.08) + static let shadow = Color.black.opacity(0.05) + static let cardFill = Color.white.opacity(0.96) + static let mutedFill = Color(red: 0.972, green: 0.976, blue: 0.970) +} + +enum AppLayout { + static let compactHorizontalPadding: CGFloat = 16 + static let regularHorizontalPadding: CGFloat = 28 + static let compactVerticalPadding: CGFloat = 18 + static let regularVerticalPadding: CGFloat = 28 + static let compactContentWidth: CGFloat = 720 + static let regularContentWidth: CGFloat = 920 + static let cardRadius: CGFloat = 24 + static let largeCardRadius: CGFloat = 30 + static let compactSectionPadding: CGFloat = 18 + static let regularSectionPadding: CGFloat = 24 + static let compactSectionSpacing: CGFloat = 18 + static let regularSectionSpacing: CGFloat = 24 + static let compactBottomDockPadding: CGFloat = 120 + static let regularBottomPadding: CGFloat = 56 + + static func horizontalPadding(for compactLayout: Bool) -> CGFloat { + compactLayout ? compactHorizontalPadding : regularHorizontalPadding + } + + static func verticalPadding(for compactLayout: Bool) -> CGFloat { + compactLayout ? compactVerticalPadding : regularVerticalPadding + } + + static func contentWidth(for compactLayout: Bool) -> CGFloat { + compactLayout ? compactContentWidth : regularContentWidth + } + + static func sectionPadding(for compactLayout: Bool) -> CGFloat { + compactLayout ? compactSectionPadding : regularSectionPadding + } + + static func sectionSpacing(for compactLayout: Bool) -> CGFloat { + compactLayout ? compactSectionSpacing : regularSectionSpacing + } +} + +extension View { + func appSurface(radius: CGFloat = AppLayout.cardRadius, fill: Color = AppTheme.cardFill) -> some View { + background( + fill, + in: RoundedRectangle(cornerRadius: radius, style: .continuous) + ) + .overlay( + RoundedRectangle(cornerRadius: radius, style: .continuous) + .stroke(AppTheme.border, lineWidth: 1) + ) + .shadow(color: AppTheme.shadow, radius: 12, y: 3) + } +} + +struct AppBackground: View { + var body: some View { + LinearGradient( + colors: [ + Color(red: 0.975, green: 0.978, blue: 0.972), + Color.white + ], + startPoint: .top, + endPoint: .bottom + ) + .overlay(alignment: .top) { + Rectangle() + .fill(Color.black.opacity(0.02)) + .frame(height: 160) + .blur(radius: 60) + .offset(y: -90) + } + .ignoresSafeArea() + } +} + +struct AppScrollScreen: View { + let compactLayout: Bool + var bottomPadding: CGFloat? = nil + let content: () -> Content + + init( + compactLayout: Bool, + bottomPadding: CGFloat? = nil, + @ViewBuilder content: @escaping () -> Content + ) { + self.compactLayout = compactLayout + self.bottomPadding = bottomPadding + self.content = content + } + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { + content() + } + .frame(maxWidth: AppLayout.contentWidth(for: compactLayout), alignment: .leading) + .padding(.horizontal, AppLayout.horizontalPadding(for: compactLayout)) + .padding(.top, AppLayout.verticalPadding(for: compactLayout)) + .padding(.bottom, bottomPadding ?? AppLayout.verticalPadding(for: compactLayout)) + .frame(maxWidth: .infinity, alignment: compactLayout ? .leading : .center) + } + .scrollIndicators(.hidden) + } +} + +struct AppPanel: View { + let compactLayout: Bool + let radius: CGFloat + let content: () -> Content + + init( + compactLayout: Bool, + radius: CGFloat = AppLayout.cardRadius, + @ViewBuilder content: @escaping () -> Content + ) { + self.compactLayout = compactLayout + self.radius = radius + self.content = content + } + + var body: some View { + VStack(alignment: .leading, spacing: 14) { + content() + } + .padding(AppLayout.sectionPadding(for: compactLayout)) + .frame(maxWidth: .infinity, alignment: .leading) + .appSurface(radius: radius) + } +} + +struct AppBadge: View { + let title: String + var tone: Color = AppTheme.accent + + var body: some View { + Text(title) + .font(.caption.weight(.semibold)) + .foregroundStyle(tone) + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background(tone.opacity(0.10), in: Capsule()) + } +} + +struct AppSectionCard: View { + let title: String + var subtitle: String? = nil + let compactLayout: Bool + let content: () -> Content + + init( + title: String, + subtitle: String? = nil, + compactLayout: Bool, + @ViewBuilder content: @escaping () -> Content + ) { + self.title = title + self.subtitle = subtitle + self.compactLayout = compactLayout + self.content = content + } + + var body: some View { + AppPanel(compactLayout: compactLayout) { + AppSectionTitle(title: title, subtitle: subtitle) + content() + } + } +} + +struct AppSectionTitle: View { + let title: String + var subtitle: String? = nil + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + Text(title) + .font(.title3.weight(.semibold)) + + if let subtitle, !subtitle.isEmpty { + Text(subtitle) + .font(.subheadline) + .foregroundStyle(.secondary) + } + } + } +} + +struct AppNotice: View { + let message: String + var tone: Color = AppTheme.accent + + var body: some View { + HStack(spacing: 10) { + Image(systemName: "checkmark.circle.fill") + .font(.footnote.weight(.bold)) + .foregroundStyle(tone) + Text(message) + .font(.subheadline.weight(.semibold)) + } + .padding(.horizontal, 16) + .padding(.vertical, 12) + .background(tone.opacity(0.08), in: Capsule()) + .overlay( + Capsule() + .stroke(AppTheme.border, lineWidth: 1) + ) + } +} + +struct AppStatusTag: View { + let title: String + var tone: Color = AppTheme.accent + + var body: some View { + Text(title) + .font(.caption.weight(.semibold)) + .lineLimit(1) + .minimumScaleFactor(0.8) + .fixedSize(horizontal: true, vertical: false) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background(tone.opacity(0.12), in: Capsule()) + .foregroundStyle(tone) + } +} + +struct AppKeyValue: View { + let label: String + let value: String + var monospaced: Bool = false + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + Text(label.uppercased()) + .font(.caption2.weight(.bold)) + .foregroundStyle(.secondary) + + Text(value) + .font(monospaced ? .subheadline.monospaced() : .subheadline.weight(.semibold)) + .lineLimit(2) + .minimumScaleFactor(0.8) + } + .frame(maxWidth: .infinity, alignment: .leading) + } +} + +struct AppMetric: View { + let title: String + let value: String + + var body: some View { + VStack(alignment: .leading, spacing: 6) { + Text(title.uppercased()) + .font(.caption.weight(.bold)) + .foregroundStyle(.secondary) + + Text(value) + .font(.title3.weight(.bold)) + } + .frame(maxWidth: .infinity, alignment: .leading) + } +} + +struct AppTextSurface: View { + let text: String + var monospaced: Bool = false + + var body: some View { + content + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .background(AppTheme.mutedFill, in: RoundedRectangle(cornerRadius: 20, style: .continuous)) + .overlay( + RoundedRectangle(cornerRadius: 20, style: .continuous) + .stroke(AppTheme.border, lineWidth: 1) + ) + } + + @ViewBuilder + private var content: some View { + #if os(watchOS) + Text(text) + .font(monospaced ? .body.monospaced() : .body) + #else + Text(text) + .font(monospaced ? .body.monospaced() : .body) + .textSelection(.enabled) + #endif + } +} + +struct AppTextEditorField: View { + @Binding var text: String + var minHeight: CGFloat = 120 + var monospaced: Bool = true + + var body: some View { + editor + .frame(minHeight: minHeight) + .background(AppTheme.mutedFill, in: RoundedRectangle(cornerRadius: 20, style: .continuous)) + .overlay( + RoundedRectangle(cornerRadius: 20, style: .continuous) + .stroke(AppTheme.border, lineWidth: 1) + ) + } + + @ViewBuilder + private var editor: some View { + #if os(watchOS) + Text(text) + .font(monospaced ? .body.monospaced() : .body) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(14) + #else + TextEditor(text: $text) + .font(monospaced ? .body.monospaced() : .body) + .scrollContentBackground(.hidden) + .autocorrectionDisabled() + .padding(14) + #endif + } +} + +struct AppActionRow: View { + let title: String + var subtitle: String? = nil + let systemImage: String + var tone: Color = AppTheme.accent + + var body: some View { + HStack(alignment: .top, spacing: 12) { + Image(systemName: systemImage) + .font(.subheadline.weight(.semibold)) + .foregroundStyle(tone) + .frame(width: 28, height: 28) + + VStack(alignment: .leading, spacing: 4) { + Text(title) + .font(.headline) + + if let subtitle, !subtitle.isEmpty { + Text(subtitle) + .font(.subheadline) + .foregroundStyle(.secondary) + .multilineTextAlignment(.leading) + } + } + + Spacer(minLength: 0) + + Image(systemName: "arrow.right") + .font(.footnote.weight(.bold)) + .foregroundStyle(.secondary) + } + .frame(maxWidth: .infinity, alignment: .leading) + } +} + +struct AppActionTile: View { + let title: String + let systemImage: String + var tone: Color = AppTheme.accent + var isBusy: Bool = false + + var body: some View { + VStack(alignment: .leading, spacing: 14) { + HStack(alignment: .center) { + ZStack { + Circle() + .fill(tone.opacity(0.10)) + .frame(width: 38, height: 38) + + if isBusy { + ProgressView() + .tint(tone) + } else { + Image(systemName: systemImage) + .font(.headline.weight(.semibold)) + .foregroundStyle(tone) + } + } + + Spacer(minLength: 0) + + Image(systemName: "arrow.up.right") + .font(.caption.weight(.bold)) + .foregroundStyle(.secondary) + } + + Text(title) + .font(.headline) + .multilineTextAlignment(.leading) + .lineLimit(2) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(16) + .frame(maxWidth: .infinity, minHeight: 92, alignment: .topLeading) + .appSurface(radius: 22) + } +} diff --git a/Sources/App/AppViewModel.swift b/Sources/App/AppViewModel.swift index cb7e37e..79affd5 100644 --- a/Sources/App/AppViewModel.swift +++ b/Sources/App/AppViewModel.swift @@ -3,8 +3,8 @@ import Foundation @MainActor final class AppViewModel: ObservableObject { - @Published var suggestedQRCodePayload = "" - @Published var manualQRCodePayload = "" + @Published var suggestedPairingPayload = "" + @Published var manualPairingPayload = "" @Published var session: AuthSession? @Published var profile: MemberProfile? @Published var requests: [ApprovalRequest] = [] @@ -13,11 +13,11 @@ final class AppViewModel: ObservableObject { @Published var selectedSection: AppSection = .overview @Published var isBootstrapping = false @Published var isAuthenticating = false + @Published var isIdentifying = false @Published var isRefreshing = false @Published var isNotificationCenterPresented = false @Published var activeRequestID: ApprovalRequest.ID? @Published var isScannerPresented = false - @Published var bannerMessage: String? @Published var errorMessage: String? private var hasBootstrapped = false @@ -84,13 +84,13 @@ final class AppViewModel: ObservableObject { do { let bootstrap = try await service.bootstrap() - suggestedQRCodePayload = bootstrap.suggestedQRCodePayload - manualQRCodePayload = bootstrap.suggestedQRCodePayload + suggestedPairingPayload = bootstrap.suggestedPairingPayload + manualPairingPayload = bootstrap.suggestedPairingPayload notificationPermission = await notificationCoordinator.authorizationStatus() if launchArguments.contains("--mock-auto-pair"), session == nil { - await signIn(with: bootstrap.suggestedQRCodePayload) + await signIn(with: bootstrap.suggestedPairingPayload, transport: .preview) if let preferredLaunchSection { selectedSection = preferredLaunchSection @@ -101,32 +101,52 @@ final class AppViewModel: ObservableObject { } } - func signInWithManualCode() async { - await signIn(with: manualQRCodePayload) + func signInWithManualPayload() async { + await signIn(with: manualPairingPayload, transport: .manual) } - func signInWithSuggestedCode() async { - manualQRCodePayload = suggestedQRCodePayload - await signIn(with: suggestedQRCodePayload) + func signInWithSuggestedPayload() async { + manualPairingPayload = suggestedPairingPayload + await signIn(with: suggestedPairingPayload, transport: .preview) } - func signIn(with payload: String) async { - let trimmed = payload.trimmingCharacters(in: .whitespacesAndNewlines) + func signIn( + with payload: String, + transport: PairingTransport = .manual, + signedGPSPosition: SignedGPSPosition? = nil + ) async { + await signIn( + with: PairingAuthenticationRequest( + pairingPayload: payload, + transport: transport, + signedGPSPosition: signedGPSPosition + ) + ) + } + + func signIn(with request: PairingAuthenticationRequest) async { + let trimmed = request.pairingPayload.trimmingCharacters(in: .whitespacesAndNewlines) guard !trimmed.isEmpty else { - errorMessage = "Paste or scan a QR payload first." + errorMessage = "Paste or scan a pairing payload first." return } + let normalizedRequest = PairingAuthenticationRequest( + pairingPayload: trimmed, + transport: request.transport, + signedGPSPosition: request.signedGPSPosition + ) + isAuthenticating = true defer { isAuthenticating = false } do { - let result = try await service.signIn(withQRCode: trimmed) + let result = try await service.signIn(with: normalizedRequest) session = result.session apply(snapshot: result.snapshot) notificationPermission = await notificationCoordinator.authorizationStatus() selectedSection = .overview - bannerMessage = "Paired with \(result.session.deviceName)." + errorMessage = nil isScannerPresented = false } catch let error as AppError { errorMessage = error.errorDescription @@ -135,6 +155,60 @@ final class AppViewModel: ObservableObject { } } + func identifyWithNFC(_ request: PairingAuthenticationRequest) async { + guard session != nil else { + errorMessage = "Set up this passport before proving your identity with NFC." + return + } + + await submitIdentityProof( + payload: request.pairingPayload, + transport: .nfc, + signedGPSPosition: request.signedGPSPosition + ) + } + + func identifyWithPayload(_ payload: String, transport: PairingTransport = .qr) async { + guard session != nil else { + errorMessage = "Set up this passport before proving your identity." + return + } + + await submitIdentityProof(payload: payload, transport: transport) + } + + private func submitIdentityProof( + payload: String, + transport: PairingTransport, + signedGPSPosition: SignedGPSPosition? = nil + ) async { + let trimmed = payload.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + errorMessage = "The provided idp.global payload was empty." + return + } + + let normalizedRequest = PairingAuthenticationRequest( + pairingPayload: trimmed, + transport: transport, + signedGPSPosition: signedGPSPosition + ) + + isIdentifying = true + defer { isIdentifying = false } + + do { + let snapshot = try await service.identify(with: normalizedRequest) + apply(snapshot: snapshot) + errorMessage = nil + isScannerPresented = false + } catch let error as AppError { + errorMessage = error.errorDescription + } catch { + errorMessage = "Unable to complete identity proof." + } + } + func refreshDashboard() async { guard session != nil else { return } @@ -144,6 +218,7 @@ final class AppViewModel: ObservableObject { do { let snapshot = try await service.refreshDashboard() apply(snapshot: snapshot) + errorMessage = nil } catch { errorMessage = "Unable to refresh the dashboard." } @@ -164,18 +239,16 @@ final class AppViewModel: ObservableObject { let snapshot = try await service.simulateIncomingRequest() apply(snapshot: snapshot) selectedSection = .requests - bannerMessage = "A new mock approval request arrived." + errorMessage = nil } catch { - errorMessage = "Unable to seed a new request right now." + errorMessage = "Unable to create a mock identity check right now." } } func requestNotificationAccess() async { do { notificationPermission = try await notificationCoordinator.requestAuthorization() - if notificationPermission == .allowed || notificationPermission == .provisional { - bannerMessage = "Notifications are ready on this device." - } + errorMessage = nil } catch { errorMessage = "Unable to update notification permission." } @@ -184,11 +257,11 @@ final class AppViewModel: ObservableObject { func sendTestNotification() async { do { try await notificationCoordinator.scheduleTestNotification( - title: "idp.global approval pending", - body: "A mock request is waiting for approval in the app." + title: "idp.global identity proof requested", + body: "A mock identity proof request is waiting in the app." ) - bannerMessage = "A local test notification will appear in a few seconds." notificationPermission = await notificationCoordinator.authorizationStatus() + errorMessage = nil } catch { errorMessage = "Unable to schedule a test notification." } @@ -198,6 +271,7 @@ final class AppViewModel: ObservableObject { do { let snapshot = try await service.markNotificationRead(id: notification.id) apply(snapshot: snapshot) + errorMessage = nil } catch { errorMessage = "Unable to update the notification." } @@ -209,8 +283,8 @@ final class AppViewModel: ObservableObject { requests = [] notifications = [] selectedSection = .overview - bannerMessage = nil - manualQRCodePayload = suggestedQRCodePayload + manualPairingPayload = suggestedPairingPayload + errorMessage = nil } private func mutateRequest(_ request: ApprovalRequest, approve: Bool) async { @@ -224,9 +298,9 @@ final class AppViewModel: ObservableObject { ? try await service.approveRequest(id: request.id) : try await service.rejectRequest(id: request.id) apply(snapshot: snapshot) - bannerMessage = approve ? "Request approved for \(request.source)." : "Request rejected for \(request.source)." + errorMessage = nil } catch { - errorMessage = "Unable to update the request." + errorMessage = "Unable to update the identity check." } } diff --git a/Sources/App/IDPGlobalApp.swift b/Sources/App/IDPGlobalApp.swift index 442bd8c..306b11a 100644 --- a/Sources/App/IDPGlobalApp.swift +++ b/Sources/App/IDPGlobalApp.swift @@ -7,7 +7,7 @@ struct IDPGlobalApp: App { var body: some Scene { WindowGroup { RootView(model: model) - .tint(Color(red: 0.12, green: 0.40, blue: 0.31)) + .tint(AppTheme.accent) .task { await model.bootstrap() } @@ -47,17 +47,8 @@ private struct RootView: View { HomeRootView(model: model) } } - .background( - LinearGradient( - colors: [ - Color(red: 0.96, green: 0.97, blue: 0.94), - Color(red: 0.89, green: 0.94, blue: 0.92), - Color(red: 0.94, green: 0.91, blue: 0.84) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - .ignoresSafeArea() - ) + .background { + AppBackground() + } } } diff --git a/Sources/Core/Models/AppModels.swift b/Sources/Core/Models/AppModels.swift index 5f84dd6..326fa49 100644 --- a/Sources/Core/Models/AppModels.swift +++ b/Sources/Core/Models/AppModels.swift @@ -1,3 +1,4 @@ +import CryptoKit import Foundation enum AppSection: String, CaseIterable, Identifiable, Hashable { @@ -58,17 +59,119 @@ enum NotificationPermissionState: String, CaseIterable, Identifiable { case .unknown: "The app has not asked for notification delivery yet." case .allowed: - "Alerts can break through immediately when a request arrives." + "Identity proof alerts can break through immediately when a check arrives." case .provisional: - "Notifications can be delivered quietly until the user promotes them." + "Identity proof alerts can be delivered quietly until the user promotes them." case .denied: - "Approval events stay in-app until the user re-enables notifications." + "Identity proof events stay in-app until the user re-enables notifications." } } } struct BootstrapContext { - let suggestedQRCodePayload: String + let suggestedPairingPayload: String +} + +enum PairingTransport: String, Hashable { + case qr + case nfc + case manual + case preview + + var title: String { + switch self { + case .qr: + "QR" + case .nfc: + "NFC" + case .manual: + "Manual" + case .preview: + "Preview" + } + } +} + +struct PairingAuthenticationRequest: Hashable { + let pairingPayload: String + let transport: PairingTransport + let signedGPSPosition: SignedGPSPosition? +} + +struct SignedGPSPosition: Hashable { + let latitude: Double + let longitude: Double + let horizontalAccuracyMeters: Double + let capturedAt: Date + let signatureBase64: String + let publicKeyBase64: String + + init( + latitude: Double, + longitude: Double, + horizontalAccuracyMeters: Double, + capturedAt: Date, + signatureBase64: String = "", + publicKeyBase64: String = "" + ) { + self.latitude = latitude + self.longitude = longitude + self.horizontalAccuracyMeters = horizontalAccuracyMeters + self.capturedAt = capturedAt + self.signatureBase64 = signatureBase64 + self.publicKeyBase64 = publicKeyBase64 + } + + var coordinateSummary: String { + "\(Self.normalized(latitude, precision: 5)), \(Self.normalized(longitude, precision: 5))" + } + + var accuracySummary: String { + "±\(Int(horizontalAccuracyMeters.rounded())) m" + } + + func signingPayload(for pairingPayload: String) -> Data { + let lines = [ + "payload=\(pairingPayload)", + "latitude=\(Self.normalized(latitude, precision: 6))", + "longitude=\(Self.normalized(longitude, precision: 6))", + "accuracy=\(Self.normalized(horizontalAccuracyMeters, precision: 2))", + "captured_at=\(Self.timestampFormatter.string(from: capturedAt))" + ] + return Data(lines.joined(separator: "\n").utf8) + } + + func verified(for pairingPayload: String) -> Bool { + guard let signatureData = Data(base64Encoded: signatureBase64), + let publicKeyData = Data(base64Encoded: publicKeyBase64), + let publicKey = try? P256.Signing.PublicKey(x963Representation: publicKeyData), + let signature = try? P256.Signing.ECDSASignature(derRepresentation: signatureData) else { + return false + } + + return publicKey.isValidSignature(signature, for: signingPayload(for: pairingPayload)) + } + + func signed(signatureData: Data, publicKeyData: Data) -> SignedGPSPosition { + SignedGPSPosition( + latitude: latitude, + longitude: longitude, + horizontalAccuracyMeters: horizontalAccuracyMeters, + capturedAt: capturedAt, + signatureBase64: signatureData.base64EncodedString(), + publicKeyBase64: publicKeyData.base64EncodedString() + ) + } + + private static let timestampFormatter: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter + }() + + private static func normalized(_ value: Double, precision: Int) -> String { + String(format: "%.\(precision)f", locale: Locale(identifier: "en_US_POSIX"), value) + } } struct DashboardSnapshot { @@ -114,6 +217,8 @@ struct AuthSession: Identifiable, Hashable { let pairedAt: Date let tokenPreview: String let pairingCode: String + let pairingTransport: PairingTransport + let signedGPSPosition: SignedGPSPosition? init( id: UUID = UUID(), @@ -121,7 +226,9 @@ struct AuthSession: Identifiable, Hashable { originHost: String, pairedAt: Date, tokenPreview: String, - pairingCode: String + pairingCode: String, + pairingTransport: PairingTransport = .manual, + signedGPSPosition: SignedGPSPosition? = nil ) { self.id = id self.deviceName = deviceName @@ -129,6 +236,8 @@ struct AuthSession: Identifiable, Hashable { self.pairedAt = pairedAt self.tokenPreview = tokenPreview self.pairingCode = pairingCode + self.pairingTransport = pairingTransport + self.signedGPSPosition = signedGPSPosition } } @@ -139,17 +248,17 @@ enum ApprovalRequestKind: String, CaseIterable, Hashable { var title: String { switch self { - case .signIn: "Sign-In" - case .accessGrant: "Access Grant" - case .elevatedAction: "Elevated Action" + case .signIn: "Identity Check" + case .accessGrant: "Strong Proof" + case .elevatedAction: "Sensitive Proof" } } var systemImage: String { switch self { case .signIn: "qrcode.viewfinder" - case .accessGrant: "key.fill" - case .elevatedAction: "shield.lefthalf.filled" + case .accessGrant: "person.badge.shield.checkmark.fill" + case .elevatedAction: "shield.checkered" } } } @@ -168,18 +277,18 @@ enum ApprovalRisk: String, Hashable { var summary: String { switch self { case .routine: - "Routine access to profile or sign-in scopes." + "A familiar identity proof for a normal sign-in or check." case .elevated: - "Sensitive access that can sign, publish, or unlock privileged actions." + "A higher-assurance identity proof for a sensitive check." } } var guidance: String { switch self { case .routine: - "Review the origin and scope list, then approve if the session matches the device you expect." + "Review the origin and continue only if it matches the proof you started." case .elevated: - "Treat this like a privileged operation. Verify the origin, the requested scopes, and whether the action is time-bound before approving." + "Only continue if you initiated this proof and trust the origin asking for it." } } } @@ -192,8 +301,8 @@ enum ApprovalStatus: String, Hashable { var title: String { switch self { case .pending: "Pending" - case .approved: "Approved" - case .rejected: "Rejected" + case .approved: "Verified" + case .rejected: "Declined" } } @@ -241,34 +350,34 @@ struct ApprovalRequest: Identifiable, Hashable { var scopeSummary: String { if scopes.isEmpty { - return "No scopes listed" + return "No proof details listed" } let suffix = scopes.count == 1 ? "" : "s" - return "\(scopes.count) requested scope\(suffix)" + return "\(scopes.count) proof detail\(suffix)" } var trustHeadline: String { switch (kind, risk) { case (.signIn, .routine): - "Low-friction sign-in request" + "Standard identity proof" case (.signIn, .elevated): - "Privileged sign-in request" + "High-assurance sign-in proof" case (.accessGrant, _): - "Token grant request" + "Cross-device identity proof" case (.elevatedAction, _): - "Sensitive action request" + "Sensitive identity proof" } } var trustDetail: String { switch kind { case .signIn: - "This request usually creates or refreshes a session token for a browser, CLI, or device." + "This request proves that the person at the browser, CLI, or device is really you." case .accessGrant: - "This request issues scoped access for a service or automation that wants to act on your behalf." + "This request asks for a stronger proof so the relying party can trust the session with higher confidence." case .elevatedAction: - "This request performs a privileged action such as signing, publishing, or creating short-lived credentials." + "This request asks for the highest confidence proof before continuing with a sensitive flow." } } } @@ -280,7 +389,7 @@ enum AppNotificationKind: String, Hashable { var title: String { switch self { - case .approval: "Approval" + case .approval: "Proof" case .security: "Security" case .system: "System" } @@ -297,9 +406,9 @@ enum AppNotificationKind: String, Hashable { var summary: String { switch self { case .approval: - "Decision and approval activity" + "Identity proof activity" case .security: - "Pairing and security posture updates" + "Passport and security posture updates" case .system: "Product and environment status messages" } @@ -332,15 +441,27 @@ struct AppNotification: Identifiable, Hashable { } enum AppError: LocalizedError { - case invalidQRCode + case invalidPairingPayload + case missingSignedGPSPosition + case invalidSignedGPSPosition + case locationPermissionDenied + case locationUnavailable case requestNotFound var errorDescription: String? { switch self { - case .invalidQRCode: - "That QR payload is not valid for idp.global sign-in." + case .invalidPairingPayload: + "That idp.global payload is not valid for this action." + case .missingSignedGPSPosition: + "Tap NFC requires a signed GPS position." + case .invalidSignedGPSPosition: + "The signed GPS position attached to this NFC proof could not be verified." + case .locationPermissionDenied: + "Location access is required so Tap NFC can attach a signed GPS position." + case .locationUnavailable: + "Unable to determine the current GPS position for Tap NFC." case .requestNotFound: - "The selected request could not be found." + "The selected identity check could not be found." } } } diff --git a/Sources/Core/Services/MockIDPService.swift b/Sources/Core/Services/MockIDPService.swift index 5723449..5c90650 100644 --- a/Sources/Core/Services/MockIDPService.swift +++ b/Sources/Core/Services/MockIDPService.swift @@ -2,7 +2,8 @@ import Foundation protocol IDPServicing { func bootstrap() async throws -> BootstrapContext - func signIn(withQRCode payload: String) async throws -> SignInResult + func signIn(with request: PairingAuthenticationRequest) async throws -> SignInResult + func identify(with request: PairingAuthenticationRequest) async throws -> DashboardSnapshot func refreshDashboard() async throws -> DashboardSnapshot func approveRequest(id: UUID) async throws -> DashboardSnapshot func rejectRequest(id: UUID) async throws -> DashboardSnapshot @@ -30,18 +31,19 @@ actor MockIDPService: IDPServicing { func bootstrap() async throws -> BootstrapContext { try await Task.sleep(for: .milliseconds(120)) return BootstrapContext( - suggestedQRCodePayload: "idp.global://pair?token=swiftapp-demo-berlin&origin=code.foss.global&device=Safari%20on%20Berlin%20MBP" + suggestedPairingPayload: "idp.global://pair?token=swiftapp-demo-berlin&origin=code.foss.global&device=Safari%20on%20Berlin%20MBP" ) } - func signIn(withQRCode payload: String) async throws -> SignInResult { + func signIn(with request: PairingAuthenticationRequest) async throws -> SignInResult { try await Task.sleep(for: .milliseconds(260)) - let session = try parseSession(from: payload) + try validateSignedGPSPosition(in: request) + let session = try parseSession(from: request) notifications.insert( AppNotification( - title: "New device paired", - message: "\(session.deviceName) completed a QR pairing against \(session.originHost).", + title: "Passport activated", + message: pairingMessage(for: session), sentAt: .now, kind: .security, isUnread: true @@ -55,6 +57,25 @@ actor MockIDPService: IDPServicing { ) } + func identify(with request: PairingAuthenticationRequest) async throws -> DashboardSnapshot { + try await Task.sleep(for: .milliseconds(180)) + + try validateSignedGPSPosition(in: request) + let context = try parsePayloadContext(from: request.pairingPayload) + notifications.insert( + AppNotification( + title: "Identity proof completed", + message: identificationMessage(for: context, signedGPSPosition: request.signedGPSPosition), + sentAt: .now, + kind: .security, + isUnread: true + ), + at: 0 + ) + + return snapshot() + } + func refreshDashboard() async throws -> DashboardSnapshot { try await Task.sleep(for: .milliseconds(180)) return snapshot() @@ -70,8 +91,8 @@ actor MockIDPService: IDPServicing { requests[index].status = .approved notifications.insert( AppNotification( - title: "Request approved", - message: "\(requests[index].title) was approved for \(requests[index].source).", + title: "Identity verified", + message: "\(requests[index].title) was completed for \(requests[index].source).", sentAt: .now, kind: .approval, isUnread: true @@ -92,8 +113,8 @@ actor MockIDPService: IDPServicing { requests[index].status = .rejected notifications.insert( AppNotification( - title: "Request rejected", - message: "\(requests[index].title) was rejected before token issuance.", + title: "Identity proof declined", + message: "\(requests[index].title) was declined before the session could continue.", sentAt: .now, kind: .security, isUnread: true @@ -108,21 +129,21 @@ actor MockIDPService: IDPServicing { try await Task.sleep(for: .milliseconds(120)) let syntheticRequest = ApprovalRequest( - title: "Approve SSH certificate issue", - subtitle: "CI runner wants a short-lived signing certificate for a deployment pipeline.", - source: "deploy.idp.global", + title: "Prove identity for web sign-in", + subtitle: "A browser session is asking this passport to prove that it is really you.", + source: "auth.idp.global", createdAt: .now, - kind: .elevatedAction, - risk: .elevated, - scopes: ["sign:ssh", "ttl:10m", "environment:staging"], + kind: .signIn, + risk: .routine, + scopes: ["proof:basic", "client:web", "method:qr"], status: .pending ) requests.insert(syntheticRequest, at: 0) notifications.insert( AppNotification( - title: "Fresh approval request", - message: "A staging deployment is waiting for your approval.", + title: "Fresh identity proof request", + message: "A new relying party is waiting for your identity proof.", sentAt: .now, kind: .approval, isUnread: true @@ -152,7 +173,33 @@ actor MockIDPService: IDPServicing { ) } - private func parseSession(from payload: String) throws -> AuthSession { + private func validateSignedGPSPosition(in request: PairingAuthenticationRequest) throws { + if request.transport == .nfc, + request.signedGPSPosition == nil { + throw AppError.missingSignedGPSPosition + } + + if let signedGPSPosition = request.signedGPSPosition, + !signedGPSPosition.verified(for: request.pairingPayload) { + throw AppError.invalidSignedGPSPosition + } + } + + private func parseSession(from request: PairingAuthenticationRequest) throws -> AuthSession { + let context = try parsePayloadContext(from: request.pairingPayload) + + return AuthSession( + deviceName: context.deviceName, + originHost: context.originHost, + pairedAt: .now, + tokenPreview: context.tokenPreview, + pairingCode: request.pairingPayload, + pairingTransport: request.transport, + signedGPSPosition: request.signedGPSPosition + ) + } + + private func parsePayloadContext(from payload: String) throws -> PayloadContext { if let components = URLComponents(string: payload), components.scheme == "idp.global", components.host == "pair" { @@ -161,58 +208,88 @@ actor MockIDPService: IDPServicing { let origin = queryItems.first(where: { $0.name == "origin" })?.value ?? "code.foss.global" let device = queryItems.first(where: { $0.name == "device" })?.value ?? "Web Session" - return AuthSession( + return PayloadContext( deviceName: device, originHost: origin, - pairedAt: .now, - tokenPreview: String(token.suffix(6)), - pairingCode: payload + tokenPreview: String(token.suffix(6)) ) } if payload.contains("token") || payload.contains("pair") { - return AuthSession( - deviceName: "Manual Pairing", + return PayloadContext( + deviceName: "Manual Session", originHost: "code.foss.global", - pairedAt: .now, - tokenPreview: String(payload.suffix(6)), - pairingCode: payload + tokenPreview: String(payload.suffix(6)) ) } - throw AppError.invalidQRCode + throw AppError.invalidPairingPayload + } + + private func pairingMessage(for session: AuthSession) -> String { + let transportSummary: String + switch session.pairingTransport { + case .qr: + transportSummary = "activated via QR" + case .nfc: + transportSummary = "activated via NFC with a signed GPS position" + case .manual: + transportSummary = "activated via manual payload" + case .preview: + transportSummary = "activated via preview payload" + } + + if let signedGPSPosition = session.signedGPSPosition { + return "\(session.deviceName) is now acting as a passport, \(transportSummary) against \(session.originHost) from \(signedGPSPosition.coordinateSummary) \(signedGPSPosition.accuracySummary)." + } + + return "\(session.deviceName) is now acting as a passport, \(transportSummary) against \(session.originHost)." + } + + private func identificationMessage(for context: PayloadContext, signedGPSPosition: SignedGPSPosition?) -> String { + if let signedGPSPosition { + return "A signed GPS proof was sent for \(context.deviceName) on \(context.originHost) from \(signedGPSPosition.coordinateSummary) \(signedGPSPosition.accuracySummary)." + } + + return "An identity proof was completed for \(context.deviceName) on \(context.originHost)." + } + + private struct PayloadContext { + let deviceName: String + let originHost: String + let tokenPreview: String } private static func seedRequests() -> [ApprovalRequest] { [ ApprovalRequest( - title: "Approve Safari sign-in", - subtitle: "A browser session from Berlin wants an SSO token for the portal.", + title: "Prove identity for Safari sign-in", + subtitle: "The portal wants this passport to prove that the browser session is really you.", source: "code.foss.global", createdAt: .now.addingTimeInterval(-60 * 12), kind: .signIn, risk: .routine, - scopes: ["openid", "profile", "groups:read"], + scopes: ["proof:basic", "client:web", "origin:trusted"], status: .pending ), ApprovalRequest( - title: "Grant package publish access", - subtitle: "The release bot is asking for a scoped publish token.", - source: "registry.foss.global", + title: "Prove identity for workstation unlock", + subtitle: "Your secure workspace is asking for a stronger proof before it unlocks.", + source: "berlin-mbp.idp.global", createdAt: .now.addingTimeInterval(-60 * 42), - kind: .accessGrant, + kind: .elevatedAction, risk: .elevated, - scopes: ["packages:write", "ttl:30m"], + scopes: ["proof:high", "client:desktop", "presence:required"], status: .pending ), ApprovalRequest( - title: "Approve CLI login", - subtitle: "A terminal session completed QR pairing earlier today.", + title: "Prove identity for CLI session", + subtitle: "The CLI session asked for proof earlier and was completed from this passport.", source: "cli.idp.global", createdAt: .now.addingTimeInterval(-60 * 180), kind: .signIn, risk: .routine, - scopes: ["openid", "profile"], + scopes: ["proof:basic", "client:cli"], status: .approved ) ] @@ -221,8 +298,8 @@ actor MockIDPService: IDPServicing { private static func seedNotifications() -> [AppNotification] { [ AppNotification( - title: "Two requests are waiting", - message: "The queue includes one routine sign-in and one elevated access grant.", + title: "Two identity checks are waiting", + message: "One routine web proof and one stronger workstation proof are waiting for this passport.", sentAt: .now.addingTimeInterval(-60 * 8), kind: .approval, isUnread: true @@ -235,8 +312,8 @@ actor MockIDPService: IDPServicing { isUnread: false ), AppNotification( - title: "Quiet hours active on mobile", - message: "Routine notifications will be delivered silently until the morning.", + title: "Passport quiet hours active", + message: "Routine identity checks will be delivered silently until the morning.", sentAt: .now.addingTimeInterval(-60 * 220), kind: .security, isUnread: false diff --git a/Sources/Features/Auth/LoginRootView.swift b/Sources/Features/Auth/LoginRootView.swift index d2e54d3..24d7365 100644 --- a/Sources/Features/Auth/LoginRootView.swift +++ b/Sources/Features/Auth/LoginRootView.swift @@ -1,29 +1,26 @@ import SwiftUI -private let loginAccent = Color(red: 0.12, green: 0.40, blue: 0.31) -private let loginGold = Color(red: 0.90, green: 0.79, blue: 0.60) +private let loginAccent = AppTheme.accent struct LoginRootView: View { @ObservedObject var model: AppViewModel @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { - ScrollView { - VStack(spacing: compactLayout ? 18 : 24) { - LoginHeroPanel(model: model, compactLayout: compactLayout) - PairingConsoleCard(model: model, compactLayout: compactLayout) - TrustFootprintCard(model: model, compactLayout: compactLayout) - } - .frame(maxWidth: 1040) - .padding(compactLayout ? 18 : 28) + AppScrollScreen(compactLayout: compactLayout) { + LoginHeroPanel(model: model, compactLayout: compactLayout) + PairingConsoleCard(model: model, compactLayout: compactLayout) } .sheet(isPresented: $model.isScannerPresented) { QRScannerSheet( - seededPayload: model.suggestedQRCodePayload, + seededPayload: model.suggestedPairingPayload, + title: "Scan linking QR", + description: "Use the camera to scan the QR code from the web flow that activates this device as your passport.", + navigationTitle: "Scan Linking QR", onCodeScanned: { payload in - model.manualQRCodePayload = payload + model.manualPairingPayload = payload Task { - await model.signIn(with: payload) + await model.signIn(with: payload, transport: .qr) } } ) @@ -44,51 +41,49 @@ private struct LoginHeroPanel: View { let compactLayout: Bool var body: some View { - ZStack(alignment: .bottomLeading) { - RoundedRectangle(cornerRadius: 36, style: .continuous) - .fill( - LinearGradient( - colors: [ - Color(red: 0.13, green: 0.22, blue: 0.19), - Color(red: 0.20, green: 0.41, blue: 0.33), - loginGold - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) + AppPanel(compactLayout: compactLayout, radius: AppLayout.largeCardRadius) { + AppBadge(title: "Secure passport setup", tone: loginAccent) - VStack(alignment: .leading, spacing: compactLayout ? 16 : 18) { - Text("Bind this device to your idp.global account") - .font(.system(size: compactLayout ? 32 : 44, weight: .bold, design: .rounded)) - .foregroundStyle(.white) + Text("Turn this device into a passport for your idp.global identity") + .font(.system(size: compactLayout ? 28 : 36, weight: .bold, design: .rounded)) + .lineLimit(3) - Text("Scan the pairing QR from your account to turn this device into your approval and notification app.") - .font(compactLayout ? .body : .title3) - .foregroundStyle(.white.opacity(0.88)) + Text("Scan a linking QR code or paste a payload to activate this device as your passport for identity proofs and security alerts.") + .font(.subheadline) + .foregroundStyle(.secondary) - if compactLayout { - VStack(alignment: .leading, spacing: 10) { - HeroTag(title: "Account binding") - HeroTag(title: "QR pairing") - HeroTag(title: "iPhone, iPad, Mac") - } - } else { - HStack(spacing: 12) { - HeroTag(title: "Account binding") - HeroTag(title: "QR pairing") - HeroTag(title: "iPhone, iPad, Mac") - } - } + Divider() - if model.isBootstrapping { - ProgressView("Preparing preview pairing payload…") - .tint(.white) - } + VStack(alignment: .leading, spacing: 14) { + LoginFeatureRow(icon: "qrcode.viewfinder", title: "Scan a QR code from the web flow") + LoginFeatureRow(icon: "doc.text.viewfinder", title: "Paste a payload when you already have one") + LoginFeatureRow(icon: "iphone.gen3", title: "Handle identity checks and alerts here") + } + + if model.isBootstrapping { + ProgressView("Preparing preview passport...") + .tint(loginAccent) } - .padding(compactLayout ? 22 : 32) } - .frame(minHeight: compactLayout ? 280 : 320) + } +} + +private struct LoginFeatureRow: View { + let icon: String + let title: String + + var body: some View { + HStack(alignment: .center, spacing: 12) { + Image(systemName: icon) + .font(.subheadline.weight(.semibold)) + .foregroundStyle(loginAccent) + .frame(width: 28, height: 28) + + Text(title) + .font(.headline) + + Spacer(minLength: 0) + } } } @@ -97,46 +92,41 @@ private struct PairingConsoleCard: View { let compactLayout: Bool var body: some View { - LoginCard(title: "Bind your account", subtitle: "Scan the QR code from your idp.global account or use the preview payload while backend wiring is still in progress.") { - VStack(alignment: .leading, spacing: 16) { - VStack(alignment: .leading, spacing: 8) { - Text("Open your account pairing screen, then scan the QR code here.") - .font(.headline) - Text("If you are testing the preview build without the live backend yet, the seeded payload below will still bind the mock session.") + AppSectionCard(title: "Set up passport", compactLayout: compactLayout) { + VStack(alignment: .leading, spacing: 8) { + Text("Link payload") + .font(.subheadline.weight(.semibold)) + + AppTextEditorField( + text: $model.manualPairingPayload, + minHeight: compactLayout ? 132 : 150 + ) + } + + if model.isAuthenticating { + HStack(spacing: 10) { + ProgressView() + Text("Activating this passport...") .foregroundStyle(.secondary) } + } - TextEditor(text: $model.manualQRCodePayload) - .font(.body.monospaced()) - .scrollContentBackground(.hidden) - .padding(16) - .frame(minHeight: compactLayout ? 130 : 150) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) + Text("NFC, QR, and OTP proof methods become available after this passport is active.") + .font(.footnote) + .foregroundStyle(.secondary) - if model.isAuthenticating { - HStack(spacing: 10) { - ProgressView() - Text("Binding this device to your account…") - .foregroundStyle(.secondary) - } + if compactLayout { + VStack(spacing: 12) { + primaryButtons + secondaryButtons } - - Group { - if compactLayout { - VStack(spacing: 12) { - primaryButtons - secondaryButtons - } - } else { - VStack(spacing: 12) { - HStack(spacing: 12) { - primaryButtons - } - HStack(spacing: 12) { - secondaryButtons - } - } + } else { + VStack(spacing: 12) { + HStack(spacing: 12) { + primaryButtons } + + secondaryButtons } } } @@ -147,154 +137,57 @@ private struct PairingConsoleCard: View { Button { model.isScannerPresented = true } label: { - Label("Bind With QR Code", systemImage: "qrcode.viewfinder") + Label("Scan QR", systemImage: "qrcode.viewfinder") + .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) - - Button { - Task { - await model.signInWithManualCode() - } - } label: { - if model.isAuthenticating { - ProgressView() - } else { - Label("Bind With Payload", systemImage: "arrow.right.circle.fill") - } - } - .buttonStyle(.bordered) - .disabled(model.isAuthenticating) + .controlSize(.large) } @ViewBuilder private var secondaryButtons: some View { + if compactLayout { + VStack(spacing: 12) { + usePayloadButton + previewPayloadButton + } + } else { + HStack(spacing: 12) { + usePayloadButton + previewPayloadButton + } + } + } + + private var usePayloadButton: some View { Button { Task { - await model.signInWithSuggestedCode() + await model.signInWithManualPayload() } } label: { - Label("Use Preview QR", systemImage: "wand.and.stars") + if model.isAuthenticating { + ProgressView() + .frame(maxWidth: .infinity) + } else { + Label("Link with payload", systemImage: "arrow.right.circle") + .frame(maxWidth: .infinity) + } } .buttonStyle(.bordered) - - Text("This preview keeps the account-binding flow realistic while the live API is still being wired in.") - .font(.footnote) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: compactLayout ? .leading : .trailing) + .controlSize(.large) + .disabled(model.isAuthenticating) } -} -private struct TrustFootprintCard: View { - @ObservedObject var model: AppViewModel - let compactLayout: Bool - - var body: some View { - LoginCard(title: "About this build", subtitle: "Keep the first-run screen simple, but still explain the trust context and preview status clearly.") { - VStack(alignment: .leading, spacing: 16) { - if compactLayout { - VStack(spacing: 12) { - trustFacts - } - } else { - HStack(alignment: .top, spacing: 12) { - trustFacts - } - } - - VStack(alignment: .leading, spacing: 8) { - Text("Preview Pairing Payload") - .font(.headline) - Text(model.suggestedQRCodePayload.isEmpty ? "Preparing preview payload…" : model.suggestedQRCodePayload) - .font(.footnote.monospaced()) - .foregroundStyle(.secondary) - .padding(14) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 22, style: .continuous)) - } + private var previewPayloadButton: some View { + Button { + Task { + await model.signInWithSuggestedPayload() } + } label: { + Label("Use preview passport", systemImage: "wand.and.stars") + .frame(maxWidth: .infinity) } - } - - @ViewBuilder - private var trustFacts: some View { - TrustFactCard( - icon: "person.badge.key.fill", - title: "Account Binding", - message: "This device binds to your idp.global account and becomes your place for approvals and alerts." - ) - TrustFactCard( - icon: "person.2.badge.gearshape.fill", - title: "Built by foss.global", - message: "foss.global is the open-source collective behind idp.global and the current preview environment." - ) - TrustFactCard( - icon: "bolt.badge.clock", - title: "Preview Backend", - message: "Login, requests, and notifications are mocked behind a clean service boundary until live integration is ready." - ) - } -} - -private struct LoginCard: View { - let title: String - let subtitle: String - let content: () -> Content - - init(title: String, subtitle: String, @ViewBuilder content: @escaping () -> Content) { - self.title = title - self.subtitle = subtitle - self.content = content - } - - var body: some View { - VStack(alignment: .leading, spacing: 18) { - VStack(alignment: .leading, spacing: 6) { - Text(title) - .font(.title2.weight(.semibold)) - Text(subtitle) - .foregroundStyle(.secondary) - } - - content() - } - .padding(24) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.white.opacity(0.68), in: RoundedRectangle(cornerRadius: 32, style: .continuous)) - } -} - -private struct HeroTag: View { - let title: String - - var body: some View { - Text(title) - .font(.caption.weight(.semibold)) - .foregroundStyle(.white) - .padding(.horizontal, 12) - .padding(.vertical, 9) - .background(.white.opacity(0.14), in: RoundedRectangle(cornerRadius: 16, style: .continuous)) - } -} - -private struct TrustFactCard: View { - let icon: String - let title: String - let message: String - - var body: some View { - VStack(alignment: .leading, spacing: 12) { - Image(systemName: icon) - .font(.title2) - .foregroundStyle(loginAccent) - - Text(title) - .font(.headline) - - Text(message) - .foregroundStyle(.secondary) - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) + .buttonStyle(.bordered) + .controlSize(.large) } } diff --git a/Sources/Features/Auth/NFCPairingView.swift b/Sources/Features/Auth/NFCPairingView.swift new file mode 100644 index 0000000..a38bb68 --- /dev/null +++ b/Sources/Features/Auth/NFCPairingView.swift @@ -0,0 +1,296 @@ +import SwiftUI + +#if canImport(CoreLocation) && canImport(CoreNFC) && canImport(CryptoKit) && os(iOS) +import CoreLocation +import CoreNFC +import CryptoKit + +@MainActor +final class NFCIdentifyReader: NSObject, ObservableObject, @preconcurrency NFCNDEFReaderSessionDelegate { + @Published private(set) var helperText: String + @Published private(set) var isScanning = false + @Published private(set) var isSupported: Bool + + var onAuthenticationRequestDetected: ((PairingAuthenticationRequest) -> Void)? + var onError: ((String) -> Void)? + + private let signedGPSPositionProvider = SignedGPSPositionProvider() + private var session: NFCNDEFReaderSession? + private var isPreparingLocationProof = false + + override init() { + let supported = NFCNDEFReaderSession.readingAvailable + _helperText = Published(initialValue: supported ? NFCIdentifyReader.idleHelperText : NFCIdentifyReader.unavailableHelperText) + _isSupported = Published(initialValue: supported) + super.init() + } + + func beginScanning() { + refreshAvailability() + + guard isSupported else { + onError?(Self.unavailableErrorMessage) + return + } + + guard !isScanning else { return } + + isScanning = true + isPreparingLocationProof = false + helperText = Self.scanningHelperText + + let session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true) + session.alertMessage = "Hold your iPhone near the idp.global tag. A signed GPS position will be attached to this NFC identify action." + self.session = session + session.begin() + } + + func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) { + DispatchQueue.main.async { + self.helperText = Self.scanningHelperText + } + } + + func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) { + guard let payload = extractPayload(from: messages) else { + session.invalidate() + DispatchQueue.main.async { + self.finishScanning() + self.onError?(Self.invalidTagMessage) + } + return + } + + DispatchQueue.main.async { + self.isPreparingLocationProof = true + self.helperText = Self.signingLocationHelperText + + Task { @MainActor in + await self.completeAuthentication(for: payload) + } + } + } + + func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) { + let nsError = error as NSError + let ignoredCodes = [200, 204] // User canceled, first tag read. + + DispatchQueue.main.async { + self.session = nil + } + + guard !(nsError.domain == NFCErrorDomain && ignoredCodes.contains(nsError.code)) else { + if !isPreparingLocationProof { + DispatchQueue.main.async { + self.finishScanning() + } + } + return + } + + DispatchQueue.main.async { + self.finishScanning() + self.onError?(Self.failureMessage(for: nsError)) + } + } + + @MainActor + private func completeAuthentication(for payload: String) async { + do { + let signedGPSPosition = try await signedGPSPositionProvider.currentSignedGPSPosition(for: payload) + let request = PairingAuthenticationRequest( + pairingPayload: payload, + transport: .nfc, + signedGPSPosition: signedGPSPosition + ) + finishScanning() + onAuthenticationRequestDetected?(request) + } catch let error as AppError { + finishScanning() + onError?(error.errorDescription ?? Self.gpsSigningFailureMessage) + } catch { + finishScanning() + onError?(Self.gpsSigningFailureMessage) + } + } + + private func finishScanning() { + session = nil + isPreparingLocationProof = false + isScanning = false + refreshAvailability() + } + + private func refreshAvailability() { + let available = NFCNDEFReaderSession.readingAvailable + isSupported = available + if !isScanning { + helperText = available ? Self.idleHelperText : Self.unavailableHelperText + } + } + + private func extractPayload(from messages: [NFCNDEFMessage]) -> String? { + for message in messages { + for record in message.records { + if let url = record.wellKnownTypeURIPayload() { + return url.absoluteString + } + + let (text, _) = record.wellKnownTypeTextPayload() + if let trimmed = text?.trimmingCharacters(in: .whitespacesAndNewlines), + !trimmed.isEmpty { + return trimmed + } + + if let fallback = String(data: record.payload, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !fallback.isEmpty { + return fallback + } + } + } + + return nil + } + + private static func failureMessage(for error: NSError) -> String { + if error.domain == NFCErrorDomain && error.code == 2 { + return "NFC identify is not permitted in this build. Check the NFC entitlement and privacy description." + } + + return "NFC identify could not be completed on this device." + } + + private static let idleHelperText = "Tap to identify with an NFC tag on supported iPhone hardware. A signed GPS position will be attached automatically." + private static let scanningHelperText = "Hold the top of your iPhone near the NFC tag until it is identified." + private static let signingLocationHelperText = "Tag detected. Capturing and signing the current GPS position for NFC identify." + private static let unavailableHelperText = "NFC identify is unavailable on this device." + private static let unavailableErrorMessage = "Tap to identify requires supported iPhone hardware with NFC enabled." + private static let invalidTagMessage = "The NFC tag did not contain a usable idp.global payload." + private static let gpsSigningFailureMessage = "The NFC tag was read, but the signed GPS position could not be attached." +} + +@MainActor +private final class SignedGPSPositionProvider: NSObject, @preconcurrency CLLocationManagerDelegate { + private var manager: CLLocationManager? + private var authorizationContinuation: CheckedContinuation? + private var locationContinuation: CheckedContinuation? + + func currentSignedGPSPosition(for pairingPayload: String) async throws -> SignedGPSPosition { + let location = try await currentLocation() + return try sign(location: location, pairingPayload: pairingPayload) + } + + private func currentLocation() async throws -> CLLocation { + let manager = CLLocationManager() + manager.delegate = self + manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters + manager.distanceFilter = kCLDistanceFilterNone + self.manager = manager + + switch manager.authorizationStatus { + case .authorizedAlways, .authorizedWhenInUse: + break + case .notDetermined: + let status = await requestAuthorization(using: manager) + guard status == .authorizedAlways || status == .authorizedWhenInUse else { + throw AppError.locationPermissionDenied + } + case .denied, .restricted: + throw AppError.locationPermissionDenied + @unknown default: + throw AppError.locationUnavailable + } + + return try await requestLocation(using: manager) + } + + private func requestAuthorization(using manager: CLLocationManager) async -> CLAuthorizationStatus { + manager.requestWhenInUseAuthorization() + return await withCheckedContinuation { continuation in + authorizationContinuation = continuation + } + } + + private func requestLocation(using manager: CLLocationManager) async throws -> CLLocation { + try await withCheckedThrowingContinuation { continuation in + locationContinuation = continuation + manager.requestLocation() + } + } + + private func sign(location: CLLocation, pairingPayload: String) throws -> SignedGPSPosition { + let isFresh = abs(location.timestamp.timeIntervalSinceNow) <= 120 + guard location.horizontalAccuracy >= 0, + isFresh else { + throw AppError.locationUnavailable + } + + let unsignedPosition = SignedGPSPosition( + latitude: location.coordinate.latitude, + longitude: location.coordinate.longitude, + horizontalAccuracyMeters: location.horizontalAccuracy, + capturedAt: location.timestamp + ) + + let privateKey = P256.Signing.PrivateKey() + let signature = try privateKey.signature(for: unsignedPosition.signingPayload(for: pairingPayload)) + return unsignedPosition.signed( + signatureData: signature.derRepresentation, + publicKeyData: privateKey.publicKey.x963Representation + ) + } + + func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { + guard let continuation = authorizationContinuation else { return } + + let status = manager.authorizationStatus + guard status != .notDetermined else { return } + + authorizationContinuation = nil + continuation.resume(returning: status) + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + guard let continuation = locationContinuation, + let location = locations.last else { + return + } + + authorizationContinuation = nil + locationContinuation = nil + self.manager = nil + continuation.resume(returning: location) + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + guard let continuation = locationContinuation else { return } + + authorizationContinuation = nil + locationContinuation = nil + self.manager = nil + + if let locationError = error as? CLError, + locationError.code == .denied { + continuation.resume(throwing: AppError.locationPermissionDenied) + return + } + + continuation.resume(throwing: AppError.locationUnavailable) + } +} +#else +@MainActor +final class NFCIdentifyReader: NSObject, ObservableObject { + @Published private(set) var helperText = "NFC identify with a signed GPS position is available on supported iPhone hardware only." + @Published private(set) var isScanning = false + @Published private(set) var isSupported = false + + var onAuthenticationRequestDetected: ((PairingAuthenticationRequest) -> Void)? + var onError: ((String) -> Void)? + + func beginScanning() { + onError?("Tap to identify requires supported iPhone hardware with NFC and location access enabled.") + } +} +#endif diff --git a/Sources/Features/Auth/QRScannerView.swift b/Sources/Features/Auth/QRScannerView.swift index 567e224..b13d7b9 100644 --- a/Sources/Features/Auth/QRScannerView.swift +++ b/Sources/Features/Auth/QRScannerView.swift @@ -9,56 +9,58 @@ import AppKit struct QRScannerSheet: View { let seededPayload: String + let title: String + let description: String + let navigationTitleText: String let onCodeScanned: (String) -> Void @Environment(\.dismiss) private var dismiss + @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var manualFallback = "" + init( + seededPayload: String, + title: String = "Scan QR", + description: String = "Use the camera to scan an idp.global QR challenge.", + navigationTitle: String = "Scan QR", + onCodeScanned: @escaping (String) -> Void + ) { + self.seededPayload = seededPayload + self.title = title + self.description = description + self.navigationTitleText = navigationTitle + self.onCodeScanned = onCodeScanned + } + var body: some View { NavigationStack { - ScrollView { - VStack(alignment: .leading, spacing: 20) { - Text("Use the camera to scan the QR code shown by the web portal. If you’re on a simulator or desktop without a camera, the seeded payload works as a mock fallback.") + AppScrollScreen(compactLayout: compactLayout) { + AppSectionCard(title: title, compactLayout: compactLayout) { + Text(description) + .font(.subheadline) .foregroundStyle(.secondary) LiveQRScannerView(onCodeScanned: onCodeScanned) .frame(minHeight: 340) + } - VStack(alignment: .leading, spacing: 12) { - Text("Fallback Pairing Payload") - .font(.headline) - - TextEditor(text: $manualFallback) - .font(.body.monospaced()) - .scrollContentBackground(.hidden) - .padding(14) - .frame(minHeight: 120) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) + AppSectionCard(title: "Manual fallback", compactLayout: compactLayout) { + AppTextEditorField(text: $manualFallback, minHeight: 120) + if compactLayout { + VStack(spacing: 12) { + useFallbackButton + useSeededButton + } + } else { HStack(spacing: 12) { - Button { - let chosen = manualFallback.trimmingCharacters(in: .whitespacesAndNewlines) - onCodeScanned(chosen.isEmpty ? seededPayload : chosen) - dismiss() - } label: { - Label("Use Fallback Payload", systemImage: "arrow.up.forward.square") - } - .buttonStyle(.borderedProminent) - - Button { - manualFallback = seededPayload - } label: { - Label("Use Seeded Mock", systemImage: "wand.and.rays") - } - .buttonStyle(.bordered) + useFallbackButton + useSeededButton } } - .padding(20) - .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous)) } - .padding(24) } - .navigationTitle("Scan QR Code") + .navigationTitle(navigationTitleText) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Close") { @@ -71,6 +73,36 @@ struct QRScannerSheet: View { } } } + + private var compactLayout: Bool { + #if os(iOS) + horizontalSizeClass == .compact + #else + false + #endif + } + + private var useFallbackButton: some View { + Button { + let chosen = manualFallback.trimmingCharacters(in: .whitespacesAndNewlines) + onCodeScanned(chosen.isEmpty ? seededPayload : chosen) + dismiss() + } label: { + Label("Use payload", systemImage: "arrow.up.forward.square") + .frame(maxWidth: .infinity) + } + .buttonStyle(.borderedProminent) + } + + private var useSeededButton: some View { + Button { + manualFallback = seededPayload + } label: { + Label("Reset sample", systemImage: "wand.and.rays") + .frame(maxWidth: .infinity) + } + .buttonStyle(.bordered) + } } private struct LiveQRScannerView: View { diff --git a/Sources/Features/Home/HomeRootView.swift b/Sources/Features/Home/HomeRootView.swift index 5c1051b..519dbfb 100644 --- a/Sources/Features/Home/HomeRootView.swift +++ b/Sources/Features/Home/HomeRootView.swift @@ -1,55 +1,40 @@ +import CryptoKit +import Foundation import SwiftUI -private let dashboardAccent = Color(red: 0.12, green: 0.40, blue: 0.31) -private let dashboardGold = Color(red: 0.84, green: 0.71, blue: 0.48) -private let dashboardBorder = Color.black.opacity(0.06) -private let dashboardShadow = Color.black.opacity(0.05) - -private enum DashboardSpacing { - static let compactOuterPadding: CGFloat = 16 - static let regularOuterPadding: CGFloat = 28 - static let compactTopPadding: CGFloat = 10 - static let regularTopPadding: CGFloat = 18 - static let compactBottomPadding: CGFloat = 120 - static let regularBottomPadding: CGFloat = 56 - static let compactStackSpacing: CGFloat = 20 - static let regularStackSpacing: CGFloat = 28 - static let compactContentWidth: CGFloat = 720 - static let regularContentWidth: CGFloat = 980 - static let compactSectionPadding: CGFloat = 18 - static let regularSectionPadding: CGFloat = 24 - static let compactRadius: CGFloat = 24 - static let regularRadius: CGFloat = 28 -} +private let dashboardAccent = AppTheme.accent +private let dashboardGold = AppTheme.warmAccent private extension View { - func dashboardSurface(radius: CGFloat, fillOpacity: Double = 0.88) -> some View { - background( - Color.white.opacity(fillOpacity), - in: RoundedRectangle(cornerRadius: radius, style: .continuous) - ) - .overlay( - RoundedRectangle(cornerRadius: radius, style: .continuous) - .stroke(dashboardBorder, lineWidth: 1) - ) - .shadow(color: dashboardShadow, radius: 14, y: 6) + @ViewBuilder + func inlineNavigationTitleOnIOS() -> some View { + #if os(iOS) + navigationBarTitleDisplayMode(.inline) + #else + self + #endif + } + + @ViewBuilder + func cleanTabBarOnIOS() -> some View { + #if os(iOS) + toolbarBackground(.visible, for: .tabBar) + .toolbarBackground(Color.white.opacity(0.98), for: .tabBar) + #else + self + #endif } } struct HomeRootView: View { @ObservedObject var model: AppViewModel - @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { - ZStack { - DashboardBackdrop() - - Group { - if usesCompactNavigation { - CompactHomeContainer(model: model) - } else { - RegularHomeContainer(model: model) - } + Group { + if usesCompactNavigation { + CompactHomeContainer(model: model) + } else { + RegularHomeContainer(model: model) } } .sheet(isPresented: $model.isNotificationCenterPresented) { @@ -59,7 +44,7 @@ struct HomeRootView: View { private var usesCompactNavigation: Bool { #if os(iOS) - horizontalSizeClass == .compact + true #else false #endif @@ -68,29 +53,34 @@ struct HomeRootView: View { private struct CompactHomeContainer: View { @ObservedObject var model: AppViewModel + @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { TabView(selection: $model.selectedSection) { - compactTab(for: .overview) - compactTab(for: .requests) - compactTab(for: .activity) - compactTab(for: .account) + ForEach(AppSection.allCases) { section in + NavigationStack { + HomeSectionScreen(model: model, section: section, compactLayout: compactLayout) + .navigationTitle(section.title) + .inlineNavigationTitleOnIOS() + .toolbar { + DashboardToolbar(model: model) + } + } + .tag(section) + .tabItem { + Label(section.title, systemImage: section.systemImage) + } + } } + .cleanTabBarOnIOS() } - @ViewBuilder - private func compactTab(for section: AppSection) -> some View { - NavigationStack { - HomeSectionScreen(model: model, section: section, compactLayout: true) - .navigationTitle(section.title) - .toolbar { - DashboardToolbar(model: model, compactLayout: true) - } - } - .tag(section) - .tabItem { - Label(section.title, systemImage: section.systemImage) - } + private var compactLayout: Bool { + #if os(iOS) + horizontalSizeClass == .compact + #else + false + #endif } } @@ -104,7 +94,7 @@ private struct RegularHomeContainer: View { HomeSectionScreen(model: model, section: model.selectedSection, compactLayout: false) .navigationTitle(model.selectedSection.title) .toolbar { - DashboardToolbar(model: model, compactLayout: false) + DashboardToolbar(model: model) } } .navigationSplitViewStyle(.balanced) @@ -113,70 +103,10 @@ private struct RegularHomeContainer: View { private struct DashboardToolbar: ToolbarContent { @ObservedObject var model: AppViewModel - let compactLayout: Bool var body: some ToolbarContent { - if compactLayout { - ToolbarItemGroup(placement: .primaryAction) { - NotificationBellButton(model: model) - - Menu { - Button { - Task { - await model.refreshDashboard() - } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - - Button { - Task { - await model.simulateIncomingRequest() - } - } label: { - Label("Mock Request", systemImage: "sparkles.rectangle.stack.fill") - } - - Button { - Task { - await model.sendTestNotification() - } - } label: { - Label("Send Test Alert", systemImage: "paperplane.fill") - } - } label: { - Image(systemName: "ellipsis.circle") - } - } - } else { - ToolbarItemGroup(placement: .primaryAction) { - NotificationBellButton(model: model) - - Button { - Task { - await model.refreshDashboard() - } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .disabled(model.isRefreshing) - - Button { - Task { - await model.simulateIncomingRequest() - } - } label: { - Label("Mock Request", systemImage: "sparkles.rectangle.stack.fill") - } - - Button { - Task { - await model.sendTestNotification() - } - } label: { - Label("Test Alert", systemImage: "paperplane.fill") - } - } + ToolbarItemGroup(placement: .primaryAction) { + NotificationBellButton(model: model) } } } @@ -187,47 +117,124 @@ private struct HomeSectionScreen: View { let compactLayout: Bool @State private var focusedRequest: ApprovalRequest? + @State private var isOTPPresented = false + @StateObject private var identifyReader = NFCIdentifyReader() var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: compactLayout ? DashboardSpacing.compactStackSpacing : DashboardSpacing.regularStackSpacing) { - if let banner = model.bannerMessage { - BannerCard(message: banner, compactLayout: compactLayout) - } + AppScrollScreen( + compactLayout: compactLayout, + bottomPadding: compactLayout ? AppLayout.compactBottomDockPadding : AppLayout.regularBottomPadding + ) { + HomeTopActions( + model: model, + identifyReader: identifyReader, + onScanQR: { model.isScannerPresented = true }, + onShowOTP: { isOTPPresented = true } + ) - switch section { - case .overview: - OverviewPanel( - model: model, - compactLayout: compactLayout, - onOpenRequest: { focusedRequest = $0 } - ) - case .requests: - RequestsPanel( - model: model, - compactLayout: compactLayout, - onOpenRequest: { focusedRequest = $0 } - ) - case .activity: - ActivityPanel( - model: model, - compactLayout: compactLayout, - onOpenRequest: { focusedRequest = $0 } - ) - case .account: - AccountPanel(model: model, compactLayout: compactLayout) + switch section { + case .overview: + OverviewPanel(model: model, compactLayout: compactLayout) + case .requests: + RequestsPanel(model: model, compactLayout: compactLayout, onOpenRequest: { focusedRequest = $0 }) + case .activity: + ActivityPanel(model: model, compactLayout: compactLayout) + case .account: + AccountPanel(model: model, compactLayout: compactLayout) + } + } + .task { + identifyReader.onAuthenticationRequestDetected = { request in + Task { + await model.identifyWithNFC(request) } } - .padding(.horizontal, compactLayout ? DashboardSpacing.compactOuterPadding : DashboardSpacing.regularOuterPadding) - .padding(.top, compactLayout ? DashboardSpacing.compactTopPadding : DashboardSpacing.regularTopPadding) - .padding(.bottom, compactLayout ? DashboardSpacing.compactBottomPadding : DashboardSpacing.regularBottomPadding) - .frame(maxWidth: compactLayout ? DashboardSpacing.compactContentWidth : DashboardSpacing.regularContentWidth, alignment: .leading) - .frame(maxWidth: .infinity, alignment: compactLayout ? .leading : .center) + + identifyReader.onError = { message in + model.errorMessage = message + } } - .scrollIndicators(.hidden) .sheet(item: $focusedRequest) { request in RequestDetailSheet(request: request, model: model) } + .sheet(isPresented: $model.isScannerPresented) { + QRScannerSheet( + seededPayload: model.session?.pairingCode ?? model.suggestedPairingPayload, + title: "Scan proof QR", + description: "Use the camera to scan an idp.global QR challenge from the site or device asking you to prove that it is really you.", + navigationTitle: "Scan Proof QR", + onCodeScanned: { payload in + Task { + await model.identifyWithPayload(payload, transport: .qr) + } + } + ) + } + .sheet(isPresented: $isOTPPresented) { + if let session = model.session { + OneTimePasscodeSheet(session: session) + } + } + } +} + +private struct HomeTopActions: View { + @ObservedObject var model: AppViewModel + @ObservedObject var identifyReader: NFCIdentifyReader + let onScanQR: () -> Void + let onShowOTP: () -> Void + + var body: some View { + LazyVGrid(columns: columns, spacing: 12) { + identifyButton + qrButton + otpButton + } + } + + private var columns: [GridItem] { + Array(repeating: GridItem(.flexible(), spacing: 12), count: 3) + } + + private var identifyButton: some View { + Button { + identifyReader.beginScanning() + } label: { + AppActionTile( + title: identifyReader.isScanning ? "Scanning NFC" : "Tap NFC", + systemImage: "dot.radiowaves.left.and.right", + tone: dashboardAccent, + isBusy: identifyReader.isScanning || model.isIdentifying + ) + } + .buttonStyle(.plain) + .disabled(identifyReader.isScanning || !identifyReader.isSupported || model.isIdentifying) + } + + private var qrButton: some View { + Button { + onScanQR() + } label: { + AppActionTile( + title: "Scan QR", + systemImage: "qrcode.viewfinder", + tone: dashboardAccent + ) + } + .buttonStyle(.plain) + } + + private var otpButton: some View { + Button { + onShowOTP() + } label: { + AppActionTile( + title: "OTP", + systemImage: "number.square.fill", + tone: dashboardGold + ) + } + .buttonStyle(.plain) } } @@ -246,7 +253,23 @@ private struct Sidebar: View { Section("Workspace") { ForEach(AppSection.allCases) { section in - sidebarRow(for: section) + Button { + model.selectedSection = section + } label: { + HStack { + Label(section.title, systemImage: section.systemImage) + Spacer() + if badgeCount(for: section) > 0 { + AppStatusTag(title: "\(badgeCount(for: section))", tone: dashboardAccent) + } + } + } + .buttonStyle(.plain) + .listRowBackground( + model.selectedSection == section + ? dashboardAccent.opacity(0.10) + : Color.clear + ) } } } @@ -260,55 +283,11 @@ private struct Sidebar: View { case .requests: model.pendingRequests.count case .activity: - 0 + model.unreadNotificationCount case .account: 0 } } - - @ViewBuilder - private func sidebarRow(for section: AppSection) -> some View { - Button { - model.selectedSection = section - } label: { - HStack(spacing: 14) { - Image(systemName: section.systemImage) - .font(.headline) - .frame(width: 30, height: 30) - .background { - if model.selectedSection == section { - Circle() - .fill(dashboardAccent.opacity(0.18)) - } else { - Circle() - .fill(.thinMaterial) - } - } - .foregroundStyle(model.selectedSection == section ? dashboardAccent : .primary) - - Text(section.title) - .font(.headline) - - Spacer() - - if badgeCount(for: section) > 0 { - Text("\(badgeCount(for: section))") - .font(.caption.weight(.semibold)) - .padding(.horizontal, 9) - .padding(.vertical, 5) - .background(.thinMaterial, in: Capsule()) - } - } - .padding(.vertical, 4) - .contentShape(Rectangle()) - } - .buttonStyle(.plain) - .listRowBackground( - model.selectedSection == section - ? dashboardAccent.opacity(0.12) - : Color.clear - ) - } } private struct SidebarStatusCard: View { @@ -317,16 +296,16 @@ private struct SidebarStatusCard: View { let unreadCount: Int var body: some View { - VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 10) { Text("Digital Passport") - .font(.title3.weight(.semibold)) + .font(.headline) - Text(profile?.handle ?? "Not paired yet") + Text(profile?.handle ?? "No passport active") .foregroundStyle(.secondary) - HStack(spacing: 10) { - SmallMetricPill(title: "Pending", value: "\(pendingCount)") - SmallMetricPill(title: "Unread", value: "\(unreadCount)") + HStack(spacing: 8) { + AppStatusTag(title: "\(pendingCount) pending", tone: dashboardAccent) + AppStatusTag(title: "\(unreadCount) unread", tone: dashboardGold) } } .padding(.vertical, 6) @@ -336,10 +315,9 @@ private struct SidebarStatusCard: View { private struct OverviewPanel: View { @ObservedObject var model: AppViewModel let compactLayout: Bool - let onOpenRequest: (ApprovalRequest) -> Void var body: some View { - VStack(alignment: .leading, spacing: compactLayout ? 18 : 24) { + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { if let profile = model.profile, let session = model.session { OverviewHero( profile: profile, @@ -349,456 +327,67 @@ private struct OverviewPanel: View { compactLayout: compactLayout ) } - - SectionCard( - title: "Quick Actions", - subtitle: "Refresh the bound session, seed a request, or test device alerts while the backend is still mocked.", - compactLayout: compactLayout - ) { - QuickActionsDeck(model: model, compactLayout: compactLayout) - } - - SectionCard( - title: "Requests In Focus", - subtitle: "Your passport is the identity surface. This queue is where anything asking for access should earn trust.", - compactLayout: compactLayout - ) { - if model.pendingRequests.isEmpty { - EmptyStateCopy( - title: "Nothing waiting", - systemImage: "checkmark.shield.fill", - message: "Every pending approval has been handled." - ) - } else { - VStack(spacing: 16) { - if let featured = model.pendingRequests.first { - FeaturedRequestCard( - request: featured, - compactLayout: compactLayout, - onOpenRequest: { onOpenRequest(featured) } - ) - } - - ForEach(model.pendingRequests.dropFirst().prefix(2)) { request in - RequestCard( - request: request, - compactLayout: compactLayout, - isBusy: model.activeRequestID == request.id, - onApprove: { - Task { await model.approve(request) } - }, - onReject: { - Task { await model.reject(request) } - }, - onOpenRequest: { - onOpenRequest(request) - } - ) - } - } - } - } - - SectionCard( - title: "Recent Activity", - subtitle: "Keep the full timeline in its own view, and use the bell above for alerts that need device-level attention.", - compactLayout: compactLayout - ) { - ActivityPreviewCard(model: model, compactLayout: compactLayout) - } } } } -private struct ActivityPanel: View { - @ObservedObject var model: AppViewModel - let compactLayout: Bool - let onOpenRequest: (ApprovalRequest) -> Void - - @State private var selectedNotificationID: AppNotification.ID? - - private var notificationIDs: [AppNotification.ID] { - model.notifications.map(\.id) - } - - private var selectedNotification: AppNotification? { - if let selectedNotificationID, - let match = model.notifications.first(where: { $0.id == selectedNotificationID }) { - return match - } - - return model.notifications.first - } - - var body: some View { - VStack(alignment: .leading, spacing: compactLayout ? 18 : 24) { - if compactLayout { - SectionCard( - title: "Recent Activity", - subtitle: "A dedicated home for approvals, pairing events, and system changes after they happen." - ) { - VStack(spacing: 16) { - activityMetricRow - - if model.notifications.isEmpty { - EmptyStateCopy( - title: "No activity yet", - systemImage: "clock.badge.xmark", - message: "Once requests and pairing events arrive, the timeline will fill in here." - ) - } else { - ForEach(model.notifications) { notification in - NotificationCard( - notification: notification, - compactLayout: compactLayout, - onMarkRead: { - Task { await model.markNotificationRead(notification) } - } - ) - } - } - } - } - } else { - SectionCard( - title: "Activity Timeline", - subtitle: "Review what already happened across approvals, pairing, and system state without mixing it into the notification surface." - ) { - VStack(alignment: .leading, spacing: 18) { - activityMetricRow - - if model.notifications.isEmpty { - EmptyStateCopy( - title: "No activity yet", - systemImage: "clock.badge.xmark", - message: "Once requests and pairing events arrive, the timeline will fill in here." - ) - } else { - HStack(alignment: .top, spacing: 18) { - VStack(alignment: .leading, spacing: 14) { - Text("Timeline") - .font(.headline) - - Text("The latest product and security events stay readable here, while the bell above stays focused on device notifications.") - .foregroundStyle(.secondary) - - VStack(spacing: 12) { - ForEach(model.notifications) { notification in - NotificationFeedRow( - notification: notification, - isSelected: notification.id == selectedNotification?.id - ) { - selectedNotificationID = notification.id - } - } - } - } - .frame(width: 390, alignment: .leading) - .padding(18) - .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous)) - - if let notification = selectedNotification { - NotificationWorkbenchDetail( - notification: notification, - permissionState: model.notificationPermission, - onMarkRead: { - Task { await model.markNotificationRead(notification) } - } - ) - } - } - } - } - } - } - - if !model.handledRequests.isEmpty { - SectionCard( - title: "Handled Requests", - subtitle: "A compact audit trail for the approvals and rejections that already moved through the queue." - ) { - LazyVStack(spacing: 14) { - ForEach(model.handledRequests.prefix(compactLayout ? 4 : 6)) { request in - RequestCard( - request: request, - compactLayout: compactLayout, - isBusy: false, - onApprove: nil, - onReject: nil, - onOpenRequest: { - onOpenRequest(request) - } - ) - } - } - } - } - } - .onChange(of: notificationIDs, initial: true) { _, _ in - syncSelectedNotification() - } - } - - @ViewBuilder - private var activityMetricRow: some View { - if compactLayout { - VStack(spacing: 10) { - SmallMetricPill(title: "Events", value: "\(model.notifications.count)") - SmallMetricPill(title: "Unread", value: "\(model.unreadNotificationCount)") - SmallMetricPill(title: "Handled", value: "\(model.handledRequests.count)") - } - } else { - HStack(spacing: 14) { - NotificationMetricCard( - title: "Events", - value: "\(model.notifications.count)", - subtitle: model.notifications.isEmpty ? "Quiet so far" : "Timeline active", - accent: dashboardAccent - ) - NotificationMetricCard( - title: "Unread", - value: "\(model.unreadNotificationCount)", - subtitle: model.unreadNotificationCount == 0 ? "Everything acknowledged" : "Still highlighted", - accent: .orange - ) - NotificationMetricCard( - title: "Handled", - value: "\(model.handledRequests.count)", - subtitle: model.handledRequests.isEmpty ? "No completed approvals yet" : "Recent decisions ready to review", - accent: dashboardGold - ) - } - } - } - - private func syncSelectedNotification() { - if let selectedNotificationID, - notificationIDs.contains(selectedNotificationID) { - return - } - - selectedNotificationID = model.notifications.first?.id - } -} - private struct RequestsPanel: View { @ObservedObject var model: AppViewModel let compactLayout: Bool let onOpenRequest: (ApprovalRequest) -> Void - @State private var selectedRequestID: ApprovalRequest.ID? - - private var requestIDs: [ApprovalRequest.ID] { - model.requests.map(\.id) - } - - private var selectedRequest: ApprovalRequest? { - if let selectedRequestID, - let match = model.requests.first(where: { $0.id == selectedRequestID }) { - return match - } - - return model.pendingRequests.first ?? model.handledRequests.first - } - var body: some View { - VStack(alignment: .leading, spacing: compactLayout ? 18 : 24) { - if compactLayout { - SectionCard( - title: "Approval Desk", - subtitle: "Treat every request like a border checkpoint: verify the origin, timing, and scope before letting it through.", - compactLayout: compactLayout - ) { - VStack(spacing: 16) { - RequestQueueSummary( - pendingCount: model.pendingRequests.count, - elevatedCount: model.elevatedPendingCount, - compactLayout: compactLayout - ) - - if model.pendingRequests.isEmpty { - EmptyStateCopy( - title: "Queue is clear", - systemImage: "checkmark.circle", - message: "Use the toolbar to simulate another request if you want to keep testing." - ) - } else { - ForEach(model.pendingRequests) { request in - RequestCard( - request: request, - compactLayout: compactLayout, - isBusy: model.activeRequestID == request.id, - onApprove: { - Task { await model.approve(request) } - }, - onReject: { - Task { await model.reject(request) } - }, - onOpenRequest: { - onOpenRequest(request) - } - ) - } - } - } - } - - SectionCard( - title: "Decision Guide", - subtitle: "What to check before approving high-sensitivity actions from your phone.", - compactLayout: compactLayout - ) { - VStack(alignment: .leading, spacing: 14) { - GuidanceRow( - icon: "network.badge.shield.half.filled", - title: "Confirm the origin", - message: "The service hostname should match the product or automation you intentionally triggered." - ) - GuidanceRow( - icon: "timer", - title: "Look for short lifetimes", - message: "Privileged grants should usually be limited in time instead of creating long-lived access." - ) - GuidanceRow( - icon: "lock.shield", - title: "Escalate mentally for elevated scopes", - message: "Signing, publishing, and write scopes deserve a slower second look before approval." - ) - } - } - - if !model.handledRequests.isEmpty { - SectionCard( - title: "Recently Handled", - subtitle: "A compact audit trail of the latest approvals and rejections.", - compactLayout: compactLayout - ) { - LazyVStack(spacing: 14) { - ForEach(model.handledRequests.prefix(4)) { request in - RequestCard( - request: request, - compactLayout: compactLayout, - isBusy: false, - onApprove: nil, - onReject: nil, - onOpenRequest: { - onOpenRequest(request) - } - ) - } - } - } + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { + if model.requests.isEmpty { + AppPanel(compactLayout: compactLayout) { + EmptyStateCopy( + title: "No checks waiting", + systemImage: "checkmark.circle", + message: "Identity proof requests from sites and devices appear here." + ) } } else { - SectionCard( - title: "Approval Workbench", - subtitle: "Use the queue on the left and a richer inline review on the right so each decision feels deliberate instead of mechanical." - ) { - VStack(alignment: .leading, spacing: 18) { - RequestQueueSummary( - pendingCount: model.pendingRequests.count, - elevatedCount: model.elevatedPendingCount, - compactLayout: compactLayout - ) - - if model.requests.isEmpty { - EmptyStateCopy( - title: "Queue is clear", - systemImage: "checkmark.circle", - message: "Use the toolbar to simulate another request if you want to keep testing." - ) - } else { - HStack(alignment: .top, spacing: 18) { - VStack(alignment: .leading, spacing: 14) { - Text("Queue") - .font(.headline) - - Text("Pending and recently handled items stay visible here so you can sanity-check decisions without leaving the flow.") - .foregroundStyle(.secondary) - - VStack(spacing: 12) { - ForEach(model.requests) { request in - RequestQueueRow( - request: request, - isSelected: request.id == selectedRequest?.id - ) { - selectedRequestID = request.id - } - } - } - } - .frame(width: 390, alignment: .leading) - .padding(18) - .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous)) - - if let request = selectedRequest { - RequestWorkbenchDetail( - request: request, - isBusy: model.activeRequestID == request.id, - onApprove: request.status == .pending ? { - Task { await model.approve(request) } - } : nil, - onReject: request.status == .pending ? { - Task { await model.reject(request) } - } : nil, - onOpenRequest: { - onOpenRequest(request) - } - ) - } - } - } - } - } - - SectionCard( - title: "Operator Checklist", - subtitle: "A calm review pattern for larger screens, especially when elevated scopes show up." - ) { - LazyVGrid( - columns: [ - GridItem(.flexible(), spacing: 14), - GridItem(.flexible(), spacing: 14) - ], - alignment: .leading, - spacing: 14 - ) { - GuidanceCard( - icon: "network.badge.shield.half.filled", - title: "Confirm the origin", - message: "The hostname should map to the workflow or portal you intentionally triggered." - ) - GuidanceCard( - icon: "timer", - title: "Look for short lifetimes", - message: "Elevated grants are safer when they expire quickly instead of becoming ambient access." - ) - GuidanceCard( - icon: "lock.shield", - title: "Escalate for signing and publish scopes", - message: "If the action can sign, publish, or write, slow down and verify the target system twice." - ) - GuidanceCard( - icon: "person.badge.shield.checkmark", - title: "Match the device", - message: "The request story should line up with the paired browser, CLI, or automation session you expect." - ) - } - } + RequestList( + requests: model.requests, + compactLayout: compactLayout, + activeRequestID: model.activeRequestID, + onApprove: { request in + Task { await model.approve(request) } + }, + onReject: { request in + Task { await model.reject(request) } + }, + onOpenRequest: onOpenRequest + ) } } - .onChange(of: requestIDs, initial: true) { _, _ in - syncSelectedRequest() - } } +} - private func syncSelectedRequest() { - if let selectedRequestID, - requestIDs.contains(selectedRequestID) { - return +private struct ActivityPanel: View { + @ObservedObject var model: AppViewModel + let compactLayout: Bool + + var body: some View { + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { + if model.notifications.isEmpty { + AppPanel(compactLayout: compactLayout) { + EmptyStateCopy( + title: "No proof activity yet", + systemImage: "clock.badge.xmark", + message: "Identity proofs and security events will appear here." + ) + } + } else { + NotificationList( + notifications: model.notifications, + compactLayout: compactLayout, + onMarkRead: { notification in + Task { await model.markNotificationRead(notification) } + } + ) + } } - - selectedRequestID = model.pendingRequests.first?.id ?? model.handledRequests.first?.id } } @@ -806,148 +395,30 @@ private struct NotificationsPanel: View { @ObservedObject var model: AppViewModel let compactLayout: Bool - @State private var selectedNotificationID: AppNotification.ID? - - private var notificationIDs: [AppNotification.ID] { - model.notifications.map(\.id) - } - - private var selectedNotification: AppNotification? { - if let selectedNotificationID, - let match = model.notifications.first(where: { $0.id == selectedNotificationID }) { - return match - } - - return model.notifications.first - } - var body: some View { - VStack(alignment: .leading, spacing: compactLayout ? 18 : 24) { - if compactLayout { - SectionCard( - title: "Notification Delivery", - subtitle: "Control lock-screen delivery now, then evolve this into remote push once the backend is live.", - compactLayout: compactLayout - ) { - NotificationPermissionCard(model: model, compactLayout: compactLayout) - } + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { + AppSectionCard(title: "Delivery", compactLayout: compactLayout) { + NotificationPermissionSummary(model: model, compactLayout: compactLayout) + } - SectionCard( - title: "Alert Inbox", - subtitle: "Unread alerts stay emphasized here until you explicitly clear them.", - compactLayout: compactLayout - ) { - if model.notifications.isEmpty { - EmptyStateCopy( - title: "No alerts yet", - systemImage: "bell.slash", - message: "New pairing and approval alerts will accumulate here." - ) - } else { - LazyVStack(spacing: 14) { - ForEach(model.notifications) { notification in - NotificationCard( - notification: notification, - compactLayout: compactLayout, - onMarkRead: { - Task { await model.markNotificationRead(notification) } - } - ) - } + AppSectionCard(title: "Alerts", compactLayout: compactLayout) { + if model.notifications.isEmpty { + EmptyStateCopy( + title: "No alerts yet", + systemImage: "bell.slash", + message: "New passport and identity-proof alerts will accumulate here." + ) + } else { + NotificationList( + notifications: model.notifications, + compactLayout: compactLayout, + onMarkRead: { notification in + Task { await model.markNotificationRead(notification) } } - } - } - } else { - SectionCard( - title: "Delivery Posture", - subtitle: "Keep delivery health, unread pressure, and the latest alert in one glance from the notification center." - ) { - VStack(alignment: .leading, spacing: 18) { - HStack(spacing: 14) { - NotificationMetricCard( - title: "Unread", - value: "\(model.unreadNotificationCount)", - subtitle: model.unreadNotificationCount == 0 ? "Inbox clear" : "Needs triage", - accent: .orange - ) - NotificationMetricCard( - title: "Permission", - value: model.notificationPermission.title, - subtitle: model.notificationPermission == .allowed ? "Lock screen ready" : "Review device status", - accent: dashboardAccent - ) - NotificationMetricCard( - title: "Latest", - value: model.latestNotification?.kind.title ?? "Quiet", - subtitle: model.latestNotification?.sentAt.formatted(date: .omitted, time: .shortened) ?? "No recent events", - accent: dashboardGold - ) - } - - NotificationPermissionCard(model: model, compactLayout: compactLayout) - } - } - - SectionCard( - title: "Alert Inbox", - subtitle: "Select an alert to inspect the message body, delivery state, and the right follow-up action." - ) { - if model.notifications.isEmpty { - EmptyStateCopy( - title: "No alerts yet", - systemImage: "bell.slash", - message: "New pairing and approval alerts will accumulate here." - ) - } else { - HStack(alignment: .top, spacing: 18) { - VStack(alignment: .leading, spacing: 14) { - Text("Feed") - .font(.headline) - - Text("Unread items stay visually lifted until you clear them, which makes it easier to scan the important changes first.") - .foregroundStyle(.secondary) - - VStack(spacing: 12) { - ForEach(model.notifications) { notification in - NotificationFeedRow( - notification: notification, - isSelected: notification.id == selectedNotification?.id - ) { - selectedNotificationID = notification.id - } - } - } - } - .frame(maxWidth: 340, alignment: .leading) - .padding(18) - .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous)) - - if let notification = selectedNotification { - NotificationWorkbenchDetail( - notification: notification, - permissionState: model.notificationPermission, - onMarkRead: { - Task { await model.markNotificationRead(notification) } - } - ) - } - } - } + ) } } } - .onChange(of: notificationIDs, initial: true) { _, _ in - syncSelectedNotification() - } - } - - private func syncSelectedNotification() { - if let selectedNotificationID, - notificationIDs.contains(selectedNotificationID) { - return - } - - selectedNotificationID = model.notifications.first?.id } } @@ -956,37 +427,20 @@ private struct AccountPanel: View { let compactLayout: Bool var body: some View { - VStack(alignment: .leading, spacing: compactLayout ? 18 : 24) { + VStack(alignment: .leading, spacing: AppLayout.sectionSpacing(for: compactLayout)) { if let profile = model.profile, let session = model.session { AccountHero(profile: profile, session: session, compactLayout: compactLayout) - SectionCard( - title: "Session Security", - subtitle: "The core trust facts for the currently paired session.", - compactLayout: compactLayout - ) { - AccountFactGrid(profile: profile, session: session, compactLayout: compactLayout) + AppSectionCard(title: "Session", compactLayout: compactLayout) { + AccountFactsGrid(profile: profile, session: session, compactLayout: compactLayout) } } - SectionCard( - title: "Mock Pairing Payload", - subtitle: "Useful for testing QR flow while the real portal integration is still pending.", - compactLayout: compactLayout - ) { - Text(model.suggestedQRCodePayload) - .font(.body.monospaced()) - .textSelection(.enabled) - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) + AppSectionCard(title: "Pairing payload", compactLayout: compactLayout) { + AppTextSurface(text: model.suggestedPairingPayload, monospaced: true) } - SectionCard( - title: "Session Controls", - subtitle: "Use this once you want to reset back to the login and pairing flow.", - compactLayout: compactLayout - ) { + AppSectionCard(title: "Actions", compactLayout: compactLayout) { Button(role: .destructive) { model.signOut() } label: { @@ -1005,765 +459,413 @@ private struct OverviewHero: View { let unreadCount: Int let compactLayout: Bool - var body: some View { - ZStack(alignment: .topLeading) { - RoundedRectangle(cornerRadius: 34, style: .continuous) - .fill( - LinearGradient( - colors: [ - Color(red: 0.07, green: 0.18, blue: 0.15), - Color(red: 0.11, green: 0.28, blue: 0.24), - Color(red: 0.29, green: 0.24, blue: 0.12) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) - .overlay( - RoundedRectangle(cornerRadius: 34, style: .continuous) - .strokeBorder(dashboardGold.opacity(0.55), lineWidth: 1.2) - ) - - Circle() - .fill(.white.opacity(0.08)) - .frame(width: compactLayout ? 180 : 260, height: compactLayout ? 180 : 260) - .offset(x: compactLayout ? 210 : 420, y: compactLayout ? -30 : -50) - - Image(systemName: "globe.europe.africa.fill") - .font(.system(size: compactLayout ? 92 : 122)) - .foregroundStyle(.white.opacity(0.07)) - .offset(x: compactLayout ? 220 : 455, y: compactLayout ? 4 : 8) - - VStack(alignment: .leading, spacing: compactLayout ? 16 : 20) { - passportHeader - - passportBody - - if !compactLayout { - PassportMachineStrip(code: machineReadableCode) - } - - passportMetrics - } - .padding(compactLayout ? 22 : 28) - } - .frame(minHeight: compactLayout ? 380 : 390) + private var detailColumns: [GridItem] { + Array(repeating: GridItem(.flexible(), spacing: 16), count: compactLayout ? 1 : 2) } - private var passportHeader: some View { - HStack(alignment: .top, spacing: 16) { - VStack(alignment: .leading, spacing: 8) { - Text("IDP.GLOBAL DIGITAL PASSPORT") - .font(.caption.weight(.bold)) - .tracking(1.8) - .foregroundStyle(.white.opacity(0.78)) + private var metricColumns: [GridItem] { + Array(repeating: GridItem(.flexible(), spacing: 16), count: 3) + } + var body: some View { + AppPanel(compactLayout: compactLayout, radius: AppLayout.largeCardRadius) { + AppBadge(title: "Digital passport", tone: dashboardAccent) + + VStack(alignment: .leading, spacing: 6) { Text(profile.name) - .font(.system(size: compactLayout ? 30 : 36, weight: .bold, design: .rounded)) - .foregroundStyle(.white) + .font(.system(size: compactLayout ? 30 : 38, weight: .bold, design: .rounded)) + .lineLimit(2) - Text("Bound to \(session.deviceName) for requests coming from \(session.originHost).") - .font(compactLayout ? .subheadline : .title3) - .foregroundStyle(.white.opacity(0.88)) + Text("\(profile.handle) • \(profile.organization)") + .font(.subheadline) + .foregroundStyle(.secondary) } - Spacer(minLength: 0) - - PassportDocumentBadge( - number: documentNumber, - issuedAt: session.pairedAt, - compactLayout: compactLayout - ) - } - } - - @ViewBuilder - private var passportBody: some View { - if compactLayout { - VStack(alignment: .leading, spacing: 14) { - HStack(alignment: .top, spacing: 14) { - passportPortrait - - VStack(alignment: .leading, spacing: 10) { - PassportField(label: "Holder", value: profile.name, emphasized: true) - PassportField(label: "Handle", value: profile.handle, monospaced: true) - PassportField(label: "Origin", value: session.originHost, monospaced: true) - } - } - - LazyVGrid( - columns: [ - GridItem(.flexible(), spacing: 10), - GridItem(.flexible(), spacing: 10) - ], - spacing: 10 - ) { - PassportInlineFact(label: "Device", value: session.deviceName) - PassportInlineFact(label: "Issued", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) - PassportInlineFact(label: "Organization", value: profile.organization) - PassportInlineFact(label: "Token", value: "...\(session.tokenPreview)", monospaced: true) - } + HStack(spacing: 8) { + AppStatusTag(title: "Passport active", tone: dashboardAccent) + AppStatusTag(title: session.pairingTransport.title, tone: dashboardGold) } - .padding(18) - .background(.white.opacity(0.11), in: RoundedRectangle(cornerRadius: 28, style: .continuous)) - } else { - VStack(alignment: .leading, spacing: 16) { - HStack(alignment: .top, spacing: 18) { - passportPortrait - HStack(alignment: .top, spacing: 14) { - passportPrimaryFields - passportSecondaryFields - } - } + Divider() - LazyVGrid( - columns: [ - GridItem(.flexible(), spacing: 12), - GridItem(.flexible(), spacing: 12), - GridItem(.flexible(), spacing: 12) - ], - spacing: 12 - ) { - PassportInlineFact(label: "Document No.", value: documentNumber, monospaced: true) - PassportInlineFact(label: "Issued", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) - PassportInlineFact(label: "Membership", value: "\(profile.deviceCount) trusted devices") - } + LazyVGrid(columns: detailColumns, alignment: .leading, spacing: 16) { + AppKeyValue(label: "Device", value: session.deviceName) + AppKeyValue(label: "Origin", value: session.originHost, monospaced: true) + AppKeyValue(label: "Linked", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) + AppKeyValue(label: "Token", value: "...\(session.tokenPreview)", monospaced: true) } - .padding(20) - .background(.white.opacity(0.11), in: RoundedRectangle(cornerRadius: 28, style: .continuous)) - } - } - private var passportMetrics: some View { - Group { - if compactLayout { - VStack(spacing: 10) { - passportMetricCards - } - } else { - HStack(spacing: 12) { - passportMetricCards - } + Divider() + + LazyVGrid(columns: metricColumns, alignment: .leading, spacing: 16) { + AppMetric(title: "Pending", value: "\(pendingCount)") + AppMetric(title: "Alerts", value: "\(unreadCount)") + AppMetric(title: "Devices", value: "\(profile.deviceCount)") } } } - - @ViewBuilder - private var passportMetricCards: some View { - PassportMetricBadge( - title: "Pending", - value: "\(pendingCount)", - subtitle: pendingCount == 0 ? "No approvals waiting" : "Requests still at the border" - ) - PassportMetricBadge( - title: "Alerts", - value: "\(unreadCount)", - subtitle: unreadCount == 0 ? "Notification bell is clear" : "Unread device alerts" - ) - PassportMetricBadge( - title: "Devices", - value: "\(profile.deviceCount)", - subtitle: "\(profile.organization) membership" - ) - } - - private var passportPortrait: some View { - VStack(alignment: .leading, spacing: 12) { - RoundedRectangle(cornerRadius: 26, style: .continuous) - .fill(.white.opacity(0.12)) - .frame(width: compactLayout ? 102 : 132, height: compactLayout ? 132 : 166) - .overlay { - VStack(spacing: 10) { - Circle() - .fill(.white.opacity(0.18)) - .frame(width: compactLayout ? 52 : 64, height: compactLayout ? 52 : 64) - .overlay { - Text(holderInitials) - .font(.system(size: compactLayout ? 24 : 28, weight: .bold, design: .rounded)) - .foregroundStyle(.white) - } - - Text("TRUSTED HOLDER") - .font(.caption2.weight(.bold)) - .tracking(1.2) - .foregroundStyle(.white.opacity(0.72)) - - Text(compactLayout ? documentNumber : profile.handle) - .font(.footnote.monospaced()) - .foregroundStyle(.white.opacity(0.9)) - .lineLimit(2) - .minimumScaleFactor(0.7) - } - .padding(12) - } - - Text("Issued \(session.pairedAt.formatted(date: .abbreviated, time: .shortened))") - .font(.caption) - .foregroundStyle(.white.opacity(0.74)) - } - } - - private var passportPrimaryFields: some View { - VStack(alignment: .leading, spacing: 12) { - PassportField(label: "Holder", value: profile.name, emphasized: true) - PassportField(label: "Handle", value: profile.handle, monospaced: true) - PassportField(label: "Organization", value: profile.organization) - } - } - - private var passportSecondaryFields: some View { - VStack(alignment: .leading, spacing: 12) { - PassportField(label: "Bound Device", value: session.deviceName) - PassportField(label: "Origin", value: session.originHost, monospaced: true) - PassportField(label: "Token Preview", value: "...\(session.tokenPreview)", monospaced: true) - } - } - - private var holderInitials: String { - let parts = profile.name - .split(separator: " ") - .prefix(2) - .compactMap { $0.first } - - let initials = String(parts) - return initials.isEmpty ? "ID" : initials.uppercased() - } - - private var documentNumber: String { - "IDP-\(session.id.uuidString.prefix(8).uppercased())" - } - - private var machineReadableCode: String { - let normalizedName = sanitize(profile.name) - let normalizedHandle = sanitize(profile.handle) - let normalizedOrigin = sanitize(session.originHost) - return "P<\(documentNumber)<\(normalizedName)<<\(normalizedHandle)<<\(normalizedOrigin)" - } - - private func sanitize(_ value: String) -> String { - value - .uppercased() - .map { character in - character.isLetter || character.isNumber ? String(character) : "<" - } - .joined() - } } -private struct PassportDocumentBadge: View { - let number: String - let issuedAt: Date - let compactLayout: Bool - - var body: some View { - VStack(alignment: .trailing, spacing: 8) { - StatusBadge(title: "Bound", tone: .white) - - VStack(alignment: .trailing, spacing: 4) { - Text("Document No.") - .font(.caption2.weight(.bold)) - .tracking(1.0) - .foregroundStyle(.white.opacity(0.72)) - - Text(number) - .font((compactLayout ? Font.footnote : Font.body).monospaced().weight(.semibold)) - .foregroundStyle(.white) - } - - if !compactLayout { - Text("Issued \(issuedAt.formatted(date: .abbreviated, time: .shortened))") - .font(.caption) - .foregroundStyle(.white.opacity(0.76)) - } - } - .padding(.horizontal, compactLayout ? 12 : 14) - .padding(.vertical, 10) - .background(.white.opacity(0.10), in: RoundedRectangle(cornerRadius: 22, style: .continuous)) - } -} - -private struct PassportInlineFact: View { - let label: String - let value: String - var monospaced: Bool = false - - var body: some View { - VStack(alignment: .leading, spacing: 5) { - Text(label.uppercased()) - .font(.caption2.weight(.bold)) - .tracking(1.0) - .foregroundStyle(.white.opacity(0.72)) - - Text(value) - .font(monospaced ? .subheadline.monospaced() : .subheadline.weight(.semibold)) - .foregroundStyle(.white) - .lineLimit(2) - .minimumScaleFactor(0.7) - } - .padding(12) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.white.opacity(0.09), in: RoundedRectangle(cornerRadius: 18, style: .continuous)) - } -} - -private struct PassportField: View { - let label: String - let value: String - var monospaced: Bool = false - var emphasized: Bool = false - - var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(label.uppercased()) - .font(.caption2.weight(.bold)) - .tracking(1.0) - .foregroundStyle(.white.opacity(0.72)) - - Text(value) - .font(valueFont) - .foregroundStyle(.white) - .lineLimit(2) - .minimumScaleFactor(0.8) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - private var valueFont: Font { - if monospaced { - return .body.monospaced() - } - - return emphasized ? .headline : .body - } -} - -private struct PassportMetricBadge: View { - let title: String - let value: String - let subtitle: String - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - Text(title.uppercased()) - .font(.caption.weight(.bold)) - .tracking(1.0) - .foregroundStyle(.white.opacity(0.72)) - - Text(value) - .font(.title2.weight(.bold)) - .foregroundStyle(.white) - - Text(subtitle) - .font(.footnote) - .foregroundStyle(.white.opacity(0.82)) - } - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.white.opacity(0.10), in: RoundedRectangle(cornerRadius: 22, style: .continuous)) - } -} - -private struct PassportMachineStrip: View { - let code: String - - var body: some View { - Text(code) - .font(.caption.monospaced().weight(.semibold)) - .lineLimit(1) - .minimumScaleFactor(0.5) - .padding(.horizontal, 14) - .padding(.vertical, 12) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.black.opacity(0.22), in: RoundedRectangle(cornerRadius: 18, style: .continuous)) - .foregroundStyle(.white.opacity(0.94)) - } -} - -private struct QuickActionsDeck: View { +private struct NotificationPermissionSummary: View { @ObservedObject var model: AppViewModel let compactLayout: Bool var body: some View { - Group { - if compactLayout { - VStack(spacing: 12) { - actionButtons - } - } else { - HStack(alignment: .top, spacing: 14) { - actionButtons - } - } - } - } - - @ViewBuilder - private var actionButtons: some View { - ActionTile( - title: "Refresh State", - subtitle: "Pull the latest requests and notifications from the mock service.", - systemImage: "arrow.clockwise" - ) { - Task { - await model.refreshDashboard() - } - } - - ActionTile( - title: "Seed Request", - subtitle: "Inject a new elevated approval flow to test the queue.", - systemImage: "sparkles.rectangle.stack.fill" - ) { - Task { - await model.simulateIncomingRequest() - } - } - - ActionTile( - title: "Test Alert", - subtitle: "Schedule a local notification so the phone behavior is easy to verify.", - systemImage: "bell.badge.fill" - ) { - Task { - await model.sendTestNotification() - } - } - } -} - -private struct ActionTile: View { - let title: String - let subtitle: String - let systemImage: String - let action: () -> Void - - var body: some View { - Button(action: action) { - VStack(alignment: .leading, spacing: 12) { - Image(systemName: systemImage) - .font(.title3.weight(.semibold)) - .foregroundStyle(dashboardAccent) - .frame(width: 42, height: 42) - .background(dashboardAccent.opacity(0.10), in: RoundedRectangle(cornerRadius: 14, style: .continuous)) - Text(title) + VStack(alignment: .leading, spacing: 14) { + HStack(alignment: .top, spacing: 12) { + Image(systemName: model.notificationPermission.systemImage) .font(.headline) - .foregroundStyle(.primary) - Text(subtitle) - .font(.subheadline) - .foregroundStyle(.secondary) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(18) - .background(Color.white.opacity(0.76), in: RoundedRectangle(cornerRadius: 24, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 24, style: .continuous) - .stroke(dashboardAccent.opacity(0.08), lineWidth: 1) - ) - } - .buttonStyle(.plain) - } -} - -private struct FeaturedRequestCard: View { - let request: ApprovalRequest - let compactLayout: Bool - let onOpenRequest: () -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - HStack(alignment: .center, spacing: 12) { - Image(systemName: request.risk == .elevated ? "shield.lefthalf.filled.badge.checkmark" : request.kind.systemImage) - .font(.title2) - .foregroundStyle(request.risk == .elevated ? .orange : dashboardAccent) + .foregroundStyle(dashboardAccent) + .frame(width: 28, height: 28) VStack(alignment: .leading, spacing: 4) { - Text(request.trustHeadline) + Text(model.notificationPermission.title) .font(.headline) - Text(request.title) - .font(.title3.weight(.semibold)) + Text(model.notificationPermission.summary) + .font(.subheadline) + .foregroundStyle(.secondary) } - - Spacer() - - StatusBadge( - title: request.risk.title, - tone: request.risk == .routine ? .mint : .orange - ) - } - - Text(request.trustDetail) - .foregroundStyle(.secondary) - - HStack(spacing: 8) { - StatusBadge(title: request.kind.title, tone: .blue) - StatusBadge(title: request.source, tone: .gray) - StatusBadge(title: request.scopeSummary, tone: .green) } if compactLayout { VStack(alignment: .leading, spacing: 12) { - Button("Review Full Context", action: onOpenRequest) - .buttonStyle(.borderedProminent) - Text(request.risk.guidance) - .font(.footnote) - .foregroundStyle(.secondary) + permissionButtons } } else { - HStack { - Button("Review Full Context", action: onOpenRequest) - .buttonStyle(.borderedProminent) - Spacer() - Text(request.risk.guidance) - .font(.footnote) - .foregroundStyle(.secondary) - .multilineTextAlignment(.trailing) - } - } - } - .padding(compactLayout ? 18 : 22) - .background( - LinearGradient( - colors: [ - request.risk == .routine ? dashboardAccent.opacity(0.12) : Color.orange.opacity(0.16), - Color.white.opacity(0.7) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ), - in: RoundedRectangle(cornerRadius: 28, style: .continuous) - ) - } -} - -private struct RequestQueueSummary: View { - let pendingCount: Int - let elevatedCount: Int - let compactLayout: Bool - - var body: some View { - if compactLayout { - VStack(spacing: 12) { HStack(spacing: 12) { - pendingCard - elevatedCard - } - - postureCard - } - } else { - HStack(spacing: 12) { - pendingCard - elevatedCard - postureCard - } - } - } - - private var pendingCard: some View { - RequestSummaryMetricCard( - title: "Pending", - value: "\(pendingCount)", - subtitle: pendingCount == 0 ? "Queue is clear" : "Still waiting on your call", - accent: dashboardAccent - ) - } - - private var elevatedCard: some View { - RequestSummaryMetricCard( - title: "Elevated", - value: "\(elevatedCount)", - subtitle: elevatedCount == 0 ? "No privileged scopes" : "Needs slower review", - accent: .orange - ) - } - - private var postureCard: some View { - RequestSummaryMetricCard( - title: "Posture", - value: trustMode, - subtitle: postureSummary, - accent: dashboardGold - ) - } - - private var trustMode: String { - if pendingCount == 0 { - return "Clear" - } - - if elevatedCount == 0 { - return "Active" - } - - return elevatedCount > 1 ? "Escalate" : "Guarded" - } - - private var postureSummary: String { - if pendingCount == 0 { - return "Nothing at the border" - } - - if elevatedCount == 0 { - return "Routine traffic only" - } - - return "Privileged access in queue" - } -} - -private struct RequestSummaryMetricCard: View { - let title: String - let value: String - let subtitle: String - let accent: Color - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - Text(title.uppercased()) - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - - Text(value) - .font(.title3.weight(.semibold)) - .foregroundStyle(.primary) - - Text(subtitle) - .font(.footnote) - .foregroundStyle(.secondary) - } - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background(accent.opacity(0.10), in: RoundedRectangle(cornerRadius: 20, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 20, style: .continuous) - .stroke(accent.opacity(0.08), lineWidth: 1) - ) - } -} - -private struct NotificationPermissionCard: View { - @ObservedObject var model: AppViewModel - let compactLayout: Bool - - var body: some View { - VStack(alignment: .leading, spacing: 18) { - HStack(alignment: .top, spacing: 14) { - Image(systemName: model.notificationPermission.systemImage) - .font(.title2) - .frame(width: 38, height: 38) - .background(.thinMaterial, in: Circle()) - .foregroundStyle(dashboardAccent) - - VStack(alignment: .leading, spacing: 5) { - Text(model.notificationPermission.title) - .font(.headline) - Text(model.notificationPermission.summary) - .foregroundStyle(.secondary) - } - } - - Group { - if compactLayout { - VStack(spacing: 12) { - permissionButtons - } - } else { - HStack(spacing: 12) { - permissionButtons - } + permissionButtons } } } - .padding(18) - .dashboardSurface(radius: 24) } @ViewBuilder private var permissionButtons: some View { Button { - Task { - await model.requestNotificationAccess() - } + Task { await model.requestNotificationAccess() } } label: { - Label("Enable Notifications", systemImage: "bell.and.waves.left.and.right.fill") + Label("Enable notifications", systemImage: "bell.and.waves.left.and.right.fill") + .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) Button { - Task { - await model.sendTestNotification() - } + Task { await model.sendTestNotification() } } label: { - Label("Send Test Alert", systemImage: "paperplane.fill") + Label("Send test alert", systemImage: "paperplane.fill") + .frame(maxWidth: .infinity) } .buttonStyle(.bordered) } } -private struct ActivityPreviewCard: View { - @ObservedObject var model: AppViewModel +private struct AccountHero: View { + let profile: MemberProfile + let session: AuthSession let compactLayout: Bool var body: some View { - VStack(alignment: .leading, spacing: 16) { - if let latest = model.latestNotification { - NotificationCard( - notification: latest, - compactLayout: compactLayout, - onMarkRead: { - Task { await model.markNotificationRead(latest) } - } - ) - } else { - EmptyStateCopy( - title: "No activity yet", - systemImage: "clock.badge.xmark", - message: "Once requests and pairing events arrive, the activity timeline will fill in here." + AppPanel(compactLayout: compactLayout, radius: AppLayout.largeCardRadius) { + AppBadge(title: "Account", tone: dashboardAccent) + + Text(profile.name) + .font(.system(size: compactLayout ? 28 : 34, weight: .bold, design: .rounded)) + .lineLimit(2) + + Text(profile.handle) + .font(.headline) + .foregroundStyle(.secondary) + + Text("Active client: \(session.deviceName)") + .font(.subheadline) + .foregroundStyle(.secondary) + } + } +} + +private struct AccountFactsGrid: View { + let profile: MemberProfile + let session: AuthSession + let compactLayout: Bool + + private var columns: [GridItem] { + Array(repeating: GridItem(.flexible(), spacing: 16), count: compactLayout ? 1 : 2) + } + + var body: some View { + LazyVGrid(columns: columns, alignment: .leading, spacing: 16) { + AppKeyValue(label: "Organization", value: profile.organization) + AppKeyValue(label: "Origin", value: session.originHost, monospaced: true) + AppKeyValue(label: "Linked At", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) + AppKeyValue(label: "Method", value: session.pairingTransport.title) + AppKeyValue(label: "Token", value: "...\(session.tokenPreview)", monospaced: true) + AppKeyValue(label: "Recovery", value: profile.recoverySummary) + if let signedGPSPosition = session.signedGPSPosition { + AppKeyValue( + label: "Signed GPS", + value: "\(signedGPSPosition.coordinateSummary) \(signedGPSPosition.accuracySummary)", + monospaced: true ) } + AppKeyValue(label: "Trusted Devices", value: "\(profile.deviceCount)") + } + } +} + +private struct RequestList: View { + let requests: [ApprovalRequest] + let compactLayout: Bool + let activeRequestID: ApprovalRequest.ID? + let onApprove: ((ApprovalRequest) -> Void)? + let onReject: ((ApprovalRequest) -> Void)? + let onOpenRequest: (ApprovalRequest) -> Void + + var body: some View { + VStack(spacing: 14) { + ForEach(requests) { request in + RequestCard( + request: request, + compactLayout: compactLayout, + isBusy: activeRequestID == request.id, + onApprove: onApprove == nil ? nil : { onApprove?(request) }, + onReject: onReject == nil ? nil : { onReject?(request) }, + onOpenRequest: { onOpenRequest(request) } + ) + } + } + } +} + +private struct RequestCard: View { + let request: ApprovalRequest + let compactLayout: Bool + let isBusy: Bool + let onApprove: (() -> Void)? + let onReject: (() -> Void)? + let onOpenRequest: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 12) { + HStack(alignment: .top, spacing: 12) { + Image(systemName: request.kind.systemImage) + .font(.headline) + .foregroundStyle(requestAccent) + .frame(width: 28, height: 28) + + VStack(alignment: .leading, spacing: 4) { + Text(request.title) + .font(.headline) + .multilineTextAlignment(.leading) + + Text(request.source) + .font(.subheadline) + .foregroundStyle(.secondary) + .lineLimit(1) + } + + Spacer(minLength: 0) + + AppStatusTag(title: request.status.title, tone: statusTone) + } + + Text(request.subtitle) + .font(.subheadline) + .foregroundStyle(.secondary) + .lineLimit(2) + + HStack(spacing: 8) { + AppStatusTag(title: request.risk.title, tone: request.risk == .routine ? dashboardAccent : .orange) + Text(request.scopeSummary) + .font(.footnote) + .foregroundStyle(.secondary) + Spacer(minLength: 0) + Text(request.createdAt, style: .relative) + .font(.footnote) + .foregroundStyle(.secondary) + } + + if !request.scopes.isEmpty { + Text("Proof details: \(request.scopes.joined(separator: ", "))") + .font(.footnote) + .foregroundStyle(.secondary) + .lineLimit(2) + } + + controls + } + .padding(compactLayout ? 18 : 20) + .appSurface(radius: 24) + } + + @ViewBuilder + private var controls: some View { + if compactLayout { + VStack(alignment: .leading, spacing: 10) { + reviewButton + decisionButtons + } + } else { + HStack(spacing: 12) { + reviewButton + Spacer(minLength: 0) + decisionButtons + } + } + } + + private var reviewButton: some View { + Button { + onOpenRequest() + } label: { + Label("Review proof", systemImage: "arrow.up.forward.app") + } + .buttonStyle(.bordered) + } + + @ViewBuilder + private var decisionButtons: some View { + if request.status == .pending, let onApprove, let onReject { + Button { + onApprove() + } label: { + if isBusy { + ProgressView() + } else { + Label("Verify", systemImage: "checkmark.circle.fill") + } + } + .buttonStyle(.borderedProminent) + .disabled(isBusy) + + Button(role: .destructive) { + onReject() + } label: { + Label("Decline", systemImage: "xmark.circle.fill") + } + .buttonStyle(.bordered) + .disabled(isBusy) + } + } + + private var statusTone: Color { + switch request.status { + case .pending: + .orange + case .approved: + .green + case .rejected: + .red + } + } + + private var requestAccent: Color { + switch request.status { + case .approved: + .green + case .rejected: + .red + case .pending: + request.risk == .routine ? dashboardAccent : .orange + } + } +} + +private struct NotificationList: View { + let notifications: [AppNotification] + let compactLayout: Bool + let onMarkRead: (AppNotification) -> Void + + var body: some View { + VStack(spacing: 14) { + ForEach(notifications) { notification in + NotificationCard( + notification: notification, + compactLayout: compactLayout, + onMarkRead: { onMarkRead(notification) } + ) + } + } + } +} + +private struct NotificationCard: View { + let notification: AppNotification + let compactLayout: Bool + let onMarkRead: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + HStack(alignment: .top, spacing: 12) { + Image(systemName: notification.kind.systemImage) + .font(.headline) + .foregroundStyle(accentColor) + .frame(width: 28, height: 28) + + VStack(alignment: .leading, spacing: 4) { + Text(notification.title) + .font(.headline) + + HStack(spacing: 8) { + AppStatusTag(title: notification.kind.title, tone: accentColor) + if notification.isUnread { + AppStatusTag(title: "Unread", tone: .orange) + } + } + } + + Spacer(minLength: 0) + } + + Text(notification.message) + .font(.subheadline) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) if compactLayout { - VStack(alignment: .leading, spacing: 12) { - Button { - model.selectedSection = .activity - } label: { - Label("Open Activity", systemImage: "clock.arrow.trianglehead.counterclockwise.rotate.90") + VStack(alignment: .leading, spacing: 10) { + timestamp + if notification.isUnread { + markReadButton } - .buttonStyle(.borderedProminent) - - Button { - model.isNotificationCenterPresented = true - } label: { - Label("Open Notification Bell", systemImage: "bell") - } - .buttonStyle(.bordered) } } else { - HStack(spacing: 12) { - Button { - model.selectedSection = .activity - } label: { - Label("Open Activity", systemImage: "clock.arrow.trianglehead.counterclockwise.rotate.90") + HStack { + timestamp + Spacer(minLength: 0) + if notification.isUnread { + markReadButton } - .buttonStyle(.borderedProminent) - - Button { - model.isNotificationCenterPresented = true - } label: { - Label("Open Notifications", systemImage: "bell") - } - .buttonStyle(.bordered) - - Spacer() - - Text("Unread device alerts now live in the bell above instead of taking a full navigation slot.") - .font(.footnote) - .foregroundStyle(.secondary) - .multilineTextAlignment(.trailing) } } } + .padding(compactLayout ? 18 : 20) + .appSurface(radius: 24) + } + + private var timestamp: some View { + Text(notification.sentAt.formatted(date: .abbreviated, time: .shortened)) + .font(.footnote) + .foregroundStyle(.secondary) + } + + private var markReadButton: some View { + Button { + onMarkRead() + } label: { + Label("Mark read", systemImage: "checkmark") + } + .buttonStyle(.bordered) + } + + private var accentColor: Color { + switch notification.kind { + case .approval: + .green + case .security: + .orange + case .system: + .blue + } } } @@ -1802,15 +904,12 @@ private struct NotificationCenterSheet: View { var body: some View { NavigationStack { - ScrollView { + AppScrollScreen( + compactLayout: compactLayout, + bottomPadding: compactLayout ? AppLayout.compactBottomDockPadding : AppLayout.regularBottomPadding + ) { NotificationsPanel(model: model, compactLayout: compactLayout) - .padding(.horizontal, compactLayout ? DashboardSpacing.compactOuterPadding : DashboardSpacing.regularOuterPadding) - .padding(.top, compactLayout ? DashboardSpacing.compactTopPadding : DashboardSpacing.regularTopPadding) - .padding(.bottom, compactLayout ? DashboardSpacing.compactBottomPadding : DashboardSpacing.regularBottomPadding) - .frame(maxWidth: compactLayout ? DashboardSpacing.compactContentWidth : DashboardSpacing.regularContentWidth, alignment: .leading) - .frame(maxWidth: .infinity, alignment: compactLayout ? .leading : .center) } - .scrollIndicators(.hidden) .navigationTitle("Notifications") .toolbar { ToolbarItem(placement: .cancellationAction) { @@ -1834,671 +933,6 @@ private struct NotificationCenterSheet: View { } } -private struct AccountHero: View { - let profile: MemberProfile - let session: AuthSession - let compactLayout: Bool - - var body: some View { - ZStack(alignment: .bottomLeading) { - RoundedRectangle(cornerRadius: 32, style: .continuous) - .fill( - LinearGradient( - colors: [ - dashboardAccent.opacity(0.95), - Color(red: 0.19, green: 0.49, blue: 0.40), - dashboardGold.opacity(0.92) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) - - VStack(alignment: .leading, spacing: 14) { - Text(profile.name) - .font(.system(size: compactLayout ? 28 : 34, weight: .bold, design: .rounded)) - .foregroundStyle(.white) - Text(profile.handle) - .font(.headline) - .foregroundStyle(.white.opacity(0.84)) - Text("Current trusted device: \(session.deviceName)") - .foregroundStyle(.white.opacity(0.86)) - } - .padding(compactLayout ? 22 : 28) - } - .frame(minHeight: compactLayout ? 190 : 220) - } -} - -private struct AccountFactGrid: View { - let profile: MemberProfile - let session: AuthSession - let compactLayout: Bool - - private var columns: [GridItem] { - Array(repeating: GridItem(.flexible(), spacing: 12), count: compactLayout ? 1 : 2) - } - - var body: some View { - LazyVGrid(columns: columns, spacing: 12) { - FactCard(label: "Organization", value: profile.organization) - FactCard(label: "Origin", value: session.originHost) - FactCard(label: "Paired At", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) - FactCard(label: "Token Preview", value: "…\(session.tokenPreview)") - FactCard(label: "Trusted Devices", value: "\(profile.deviceCount)") - FactCard(label: "Recovery", value: profile.recoverySummary) - } - } -} - -private struct RequestCard: View { - let request: ApprovalRequest - let compactLayout: Bool - let isBusy: Bool - let onApprove: (() -> Void)? - let onReject: (() -> Void)? - let onOpenRequest: (() -> Void)? - - private var infoColumns: [GridItem] { - Array(repeating: GridItem(.flexible(), spacing: 10), count: compactLayout ? 2 : 3) - } - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - HStack(alignment: .top, spacing: 14) { - ZStack { - Circle() - .fill(requestAccent.opacity(0.14)) - - Image(systemName: request.kind.systemImage) - .font(.title2) - .foregroundStyle(requestAccent) - } - .frame(width: 46, height: 46) - - VStack(alignment: .leading, spacing: 8) { - HStack(alignment: .top, spacing: 12) { - VStack(alignment: .leading, spacing: 4) { - Text(request.trustHeadline) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(requestAccent) - - Text(request.title) - .font(.headline) - .foregroundStyle(.primary) - } - - Spacer() - - StatusBadge( - title: request.status.title, - tone: statusTone - ) - } - - Text(request.subtitle) - .foregroundStyle(.secondary) - - HStack(spacing: 8) { - StatusBadge(title: request.kind.title, tone: .blue) - StatusBadge(title: request.risk.title, tone: request.risk == .routine ? .mint : .orange) - Text(request.createdAt, style: .relative) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - } - - LazyVGrid(columns: infoColumns, alignment: .leading, spacing: 10) { - RequestFactPill(label: "Source", value: request.source, accent: dashboardAccent) - RequestFactPill( - label: "Requested", - value: request.createdAt.formatted(date: .abbreviated, time: .shortened), - accent: dashboardGold - ) - RequestFactPill(label: "Access", value: request.scopeSummary, accent: requestAccent) - } - - VStack(alignment: .leading, spacing: 10) { - Label(request.status == .pending ? "Decision posture" : "Decision record", systemImage: request.status.systemImage) - .font(.headline) - .foregroundStyle(.primary) - - Text(request.trustDetail) - .foregroundStyle(.secondary) - - Text(reviewSummary) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(requestAccent) - } - .padding(14) - .frame(maxWidth: .infinity, alignment: .leading) - .background(requestAccent.opacity(0.10), in: RoundedRectangle(cornerRadius: 22, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 22, style: .continuous) - .stroke(requestAccent.opacity(0.08), lineWidth: 1) - ) - - if !request.scopes.isEmpty { - VStack(alignment: .leading, spacing: 10) { - Text("Requested scopes") - .font(.subheadline.weight(.semibold)) - - FlowScopes(scopes: request.scopes) - } - } - - VStack(spacing: 12) { - if let onOpenRequest { - Button { - onOpenRequest() - } label: { - Label("Review Details", systemImage: "arrow.up.forward.app") - } - .buttonStyle(.bordered) - .frame(maxWidth: .infinity, alignment: .leading) - } - - if let onApprove, let onReject, request.status == .pending { - if compactLayout { - VStack(spacing: 10) { - Button { - onApprove() - } label: { - if isBusy { - ProgressView() - } else { - Label("Approve Request", systemImage: "checkmark.circle.fill") - } - } - .buttonStyle(.borderedProminent) - .disabled(isBusy) - - Button(role: .destructive) { - onReject() - } label: { - Label("Reject Request", systemImage: "xmark.circle.fill") - } - .buttonStyle(.bordered) - .disabled(isBusy) - } - } else { - HStack(spacing: 12) { - Button { - onApprove() - } label: { - if isBusy { - ProgressView() - } else { - Label("Approve", systemImage: "checkmark.circle.fill") - } - } - .buttonStyle(.borderedProminent) - .disabled(isBusy) - - Button(role: .destructive) { - onReject() - } label: { - Label("Reject", systemImage: "xmark.circle.fill") - } - .buttonStyle(.bordered) - .disabled(isBusy) - } - } - } - } - } - .padding(compactLayout ? 18 : 20) - .background( - LinearGradient( - colors: [ - Color.white.opacity(0.92), - requestAccent.opacity(0.05) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ), - in: RoundedRectangle(cornerRadius: 28, style: .continuous) - ) - .overlay( - RoundedRectangle(cornerRadius: 28, style: .continuous) - .stroke(requestAccent.opacity(0.10), lineWidth: 1) - ) - .shadow(color: dashboardShadow, radius: 12, y: 5) - } - - private var statusTone: Color { - switch request.status { - case .pending: - return .orange - case .approved: - return .green - case .rejected: - return .red - } - } - - private var requestAccent: Color { - switch request.status { - case .approved: - return .green - case .rejected: - return .red - case .pending: - return request.risk == .routine ? dashboardAccent : .orange - } - } - - private var reviewSummary: String { - switch request.status { - case .pending: - if request.risk == .elevated { - return "This is privileged access. Let it through only if the origin and the moment both match what you just initiated." - } - return "This looks routine, but it still needs to match the browser, CLI, or device session you expect." - case .approved: - return "This request was already approved in the mock queue and is now part of the recent audit trail." - case .rejected: - return "This request was rejected and should remain a closed lane unless a new request is issued." - } - } -} - -private struct RequestQueueRow: View { - let request: ApprovalRequest - let isSelected: Bool - let action: () -> Void - - var body: some View { - Button(action: action) { - HStack(alignment: .top, spacing: 12) { - ZStack { - RoundedRectangle(cornerRadius: 16, style: .continuous) - .fill(rowAccent.opacity(0.14)) - - Image(systemName: request.kind.systemImage) - .font(.headline) - .foregroundStyle(rowAccent) - } - .frame(width: 38, height: 38) - - VStack(alignment: .leading, spacing: 10) { - HStack(alignment: .top, spacing: 12) { - VStack(alignment: .leading, spacing: 4) { - Text(request.title) - .font(.headline) - .foregroundStyle(.primary) - .multilineTextAlignment(.leading) - .lineLimit(2) - - Text(request.trustHeadline) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(rowAccent) - .lineLimit(1) - } - - Spacer(minLength: 0) - - StatusBadge( - title: request.status.title, - tone: statusTone - ) - } - - Text(request.source) - .font(.subheadline) - .foregroundStyle(.secondary) - .lineLimit(1) - - Text(request.subtitle) - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(1) - .multilineTextAlignment(.leading) - - HStack(spacing: 8) { - StatusBadge(title: request.risk.title, tone: request.risk == .routine ? .mint : .orange) - StatusBadge(title: request.scopeSummary, tone: .blue) - Spacer() - Text(request.createdAt, style: .relative) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - - Image(systemName: isSelected ? "chevron.right.circle.fill" : "chevron.right") - .font(.headline) - .foregroundStyle(isSelected ? rowAccent : .secondary.opacity(0.7)) - .padding(.top, 2) - } - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background(backgroundStyle, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 24, style: .continuous) - .stroke(isSelected ? rowAccent.opacity(0.36) : Color.clear, lineWidth: 1.5) - ) - .overlay(alignment: .leading) { - Capsule() - .fill(rowAccent.opacity(isSelected ? 0.80 : 0.30)) - .frame(width: 5) - .padding(.vertical, 16) - .padding(.leading, 8) - } - } - .buttonStyle(.plain) - } - - private var statusTone: Color { - switch request.status { - case .pending: - .orange - case .approved: - .green - case .rejected: - .red - } - } - - private var backgroundStyle: Color { - isSelected ? rowAccent.opacity(0.08) : Color.white.opacity(0.90) - } - - private var rowAccent: Color { - switch request.status { - case .approved: - .green - case .rejected: - .red - case .pending: - request.risk == .routine ? dashboardAccent : .orange - } - } -} - -private struct RequestWorkbenchDetail: View { - let request: ApprovalRequest - let isBusy: Bool - let onApprove: (() -> Void)? - let onReject: (() -> Void)? - let onOpenRequest: () -> Void - - private let columns = [ - GridItem(.flexible(), spacing: 12), - GridItem(.flexible(), spacing: 12) - ] - - var body: some View { - VStack(alignment: .leading, spacing: 18) { - ZStack(alignment: .topLeading) { - RoundedRectangle(cornerRadius: 30, style: .continuous) - .fill( - LinearGradient( - colors: [ - request.risk == .routine ? dashboardAccent.opacity(0.95) : Color.orange.opacity(0.92), - dashboardGold.opacity(0.88) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) - .overlay( - RoundedRectangle(cornerRadius: 30, style: .continuous) - .strokeBorder(requestAccent.opacity(0.20), lineWidth: 1) - ) - - VStack(alignment: .leading, spacing: 16) { - HStack(alignment: .top, spacing: 12) { - VStack(alignment: .leading, spacing: 10) { - HStack(spacing: 8) { - StatusBadge(title: request.kind.title, tone: .white) - StatusBadge(title: request.risk.title, tone: .white) - StatusBadge(title: request.status.title, tone: .white) - } - - Text(request.title) - .font(.system(size: 30, weight: .bold, design: .rounded)) - .foregroundStyle(.white) - - Text(request.trustHeadline) - .font(.headline) - .foregroundStyle(.white.opacity(0.84)) - } - - Spacer(minLength: 0) - - VStack(alignment: .trailing, spacing: 6) { - Text("REQUESTED") - .font(.caption.weight(.bold)) - .foregroundStyle(.white.opacity(0.72)) - - Text(request.createdAt.formatted(date: .abbreviated, time: .shortened)) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.white) - } - } - - Text(request.subtitle) - .font(.title3) - .foregroundStyle(.white.opacity(0.88)) - - HStack(spacing: 14) { - Label(request.source, systemImage: "network") - Label(request.scopeSummary, systemImage: "lock.shield") - } - .font(.subheadline) - .foregroundStyle(.white.opacity(0.88)) - - Text(request.trustDetail) - .font(.subheadline) - .foregroundStyle(.white.opacity(0.82)) - } - .padding(24) - } - .frame(minHeight: 220) - - LazyVGrid(columns: columns, spacing: 12) { - FactCard(label: "Source", value: request.source) - FactCard(label: "Requested", value: request.createdAt.formatted(date: .abbreviated, time: .shortened)) - FactCard(label: "Type", value: request.kind.title) - FactCard(label: "Status", value: request.status.title) - FactCard(label: "Risk", value: request.risk.summary) - FactCard(label: "Access", value: request.scopeSummary) - } - - HStack(alignment: .top, spacing: 12) { - RequestSignalCard( - title: "Trust Signals", - subtitle: "The approval story should match the device, the product, and the moment you just triggered.", - accent: requestAccent - ) { - VStack(alignment: .leading, spacing: 14) { - GuidanceRow( - icon: "network.badge.shield.half.filled", - title: "Source must look familiar", - message: "This request comes from \(request.source). Only approve if that host or product lines up with what you intended." - ) - GuidanceRow( - icon: "person.badge.shield.checkmark", - title: "Action should fit the session", - message: request.trustDetail - ) - GuidanceRow( - icon: request.risk == .routine ? "checkmark.shield" : "exclamationmark.shield", - title: request.risk == .routine ? "Routine review is still a review" : "Elevated access deserves a pause", - message: request.risk.guidance - ) - } - } - - RequestSignalCard( - title: "Access Envelope", - subtitle: "These are the capabilities this request wants before it can proceed.", - accent: dashboardGold - ) { - if request.scopes.isEmpty { - Text("The mock backend did not provide explicit scopes for this request.") - .foregroundStyle(.secondary) - } else { - FlowScopes(scopes: request.scopes) - } - } - } - - RequestSignalCard( - title: request.status == .pending ? "Decision Rail" : "Decision Record", - subtitle: request.status == .pending - ? "Use the actions below only once the request story matches the device in your hand." - : "This request already moved through the queue, so this rail becomes a compact audit note.", - accent: statusTone - ) { - VStack(alignment: .leading, spacing: 14) { - Text(request.trustDetail) - .foregroundStyle(.secondary) - - Text(decisionSummary) - .font(.headline) - - HStack(spacing: 12) { - Button { - onOpenRequest() - } label: { - Label("Open Full Review", systemImage: "arrow.up.forward.app") - } - .buttonStyle(.bordered) - - Spacer() - - if let onApprove, let onReject, request.status == .pending { - Button { - onApprove() - } label: { - if isBusy { - ProgressView() - } else { - Label("Approve", systemImage: "checkmark.circle.fill") - } - } - .buttonStyle(.borderedProminent) - .disabled(isBusy) - - Button(role: .destructive) { - onReject() - } label: { - Label("Reject", systemImage: "xmark.circle.fill") - } - .buttonStyle(.bordered) - .disabled(isBusy) - } - } - } - } - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - private var statusTone: Color { - switch request.status { - case .pending: - return .orange - case .approved: - return .green - case .rejected: - return .red - } - } - - private var requestAccent: Color { - request.risk == .routine ? dashboardAccent : .orange - } - - private var decisionSummary: String { - switch request.status { - case .pending: - return request.risk == .routine - ? "Approve only if the origin and timing feel boringly expected." - : "Privileged requests should feel unmistakably intentional before you approve them." - case .approved: - return "This request has already been approved and should now be treated as part of your recent decision history." - case .rejected: - return "This request was rejected and is now a record of a blocked access attempt." - } - } -} - -private struct RequestFactPill: View { - let label: String - let value: String - let accent: Color - - var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(label.uppercased()) - .font(.caption2.weight(.semibold)) - .foregroundStyle(.secondary) - - Text(value) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.primary) - .lineLimit(2) - .minimumScaleFactor(0.8) - } - .padding(.horizontal, 12) - .padding(.vertical, 10) - .frame(maxWidth: .infinity, alignment: .leading) - .background(accent.opacity(0.10), in: RoundedRectangle(cornerRadius: 18, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 18, style: .continuous) - .stroke(accent.opacity(0.08), lineWidth: 1) - ) - } -} - -private struct RequestSignalCard: View { - let title: String - let subtitle: String - let accent: Color - let content: () -> Content - - init( - title: String, - subtitle: String, - accent: Color, - @ViewBuilder content: @escaping () -> Content - ) { - self.title = title - self.subtitle = subtitle - self.accent = accent - self.content = content - } - - var body: some View { - VStack(alignment: .leading, spacing: 14) { - HStack(alignment: .top, spacing: 12) { - Circle() - .fill(accent.opacity(0.16)) - .frame(width: 34, height: 34) - .overlay { - Circle() - .stroke(accent.opacity(0.30), lineWidth: 1) - } - - VStack(alignment: .leading, spacing: 4) { - Text(title) - .font(.headline) - Text(subtitle) - .foregroundStyle(.secondary) - } - } - - content() - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .dashboardSurface(radius: 24) - } -} - private struct RequestDetailSheet: View { let request: ApprovalRequest @ObservedObject var model: AppViewModel @@ -2507,46 +941,40 @@ private struct RequestDetailSheet: View { var body: some View { NavigationStack { - ScrollView { - VStack(alignment: .leading, spacing: 20) { - RequestDetailHero(request: request) + AppScrollScreen( + compactLayout: true, + bottomPadding: AppLayout.compactBottomDockPadding + ) { + RequestDetailHero(request: request) - SectionCard( - title: "Requested Access", - subtitle: "The exact scopes or capabilities this action wants to receive." - ) { - if request.scopes.isEmpty { - Text("No explicit scopes were provided by the mock backend.") - .foregroundStyle(.secondary) - } else { - FlowScopes(scopes: request.scopes) - } - } + AppSectionCard(title: "Summary", compactLayout: true) { + AppKeyValue(label: "Source", value: request.source) + AppKeyValue(label: "Requested", value: request.createdAt.formatted(date: .abbreviated, time: .shortened)) + AppKeyValue(label: "Risk", value: request.risk.summary) + AppKeyValue(label: "Type", value: request.kind.title) + } - SectionCard( - title: "Trust Signals", - subtitle: "The details to validate before you approve anything sensitive." - ) { - VStack(alignment: .leading, spacing: 12) { - FactCard(label: "Source", value: request.source) - FactCard(label: "Requested", value: request.createdAt.formatted(date: .abbreviated, time: .shortened)) - FactCard(label: "Type", value: request.kind.title) - FactCard(label: "Risk", value: request.risk.summary) - } - } - - SectionCard( - title: "Decision Guidance", - subtitle: "A short operator-minded reminder before you accept or reject this request." - ) { - Text(request.trustDetail) + AppSectionCard(title: "Proof details", compactLayout: true) { + if request.scopes.isEmpty { + Text("No explicit proof details were provided by the mock backend.") + .foregroundStyle(.secondary) + } else { + Text(request.scopes.joined(separator: "\n")) + .font(.body.monospaced()) .foregroundStyle(.secondary) - - Text(request.risk.guidance) - .font(.headline) } + } - if request.status == .pending { + AppSectionCard(title: "Guidance", compactLayout: true) { + Text(request.trustDetail) + .foregroundStyle(.secondary) + + Text(request.risk.guidance) + .font(.headline) + } + + if request.status == .pending { + AppSectionCard(title: "Actions", compactLayout: true) { VStack(spacing: 12) { Button { Task { @@ -2557,7 +985,8 @@ private struct RequestDetailSheet: View { if model.activeRequestID == request.id { ProgressView() } else { - Label("Approve Request", systemImage: "checkmark.circle.fill") + Label("Verify identity", systemImage: "checkmark.circle.fill") + .frame(maxWidth: .infinity) } } .buttonStyle(.borderedProminent) @@ -2569,20 +998,17 @@ private struct RequestDetailSheet: View { dismiss() } } label: { - Label("Reject Request", systemImage: "xmark.circle.fill") + Label("Decline", systemImage: "xmark.circle.fill") + .frame(maxWidth: .infinity) } .buttonStyle(.bordered) .disabled(model.activeRequestID == request.id) } } } - .padding(.horizontal, DashboardSpacing.compactOuterPadding) - .padding(.top, DashboardSpacing.compactTopPadding) - .padding(.bottom, DashboardSpacing.compactBottomPadding) - .frame(maxWidth: DashboardSpacing.compactContentWidth, alignment: .leading) - .frame(maxWidth: .infinity, alignment: .leading) } - .navigationTitle("Review Request") + .navigationTitle("Review Proof") + .inlineNavigationTitleOnIOS() .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Close") { @@ -2597,465 +1023,116 @@ private struct RequestDetailSheet: View { private struct RequestDetailHero: View { let request: ApprovalRequest - var body: some View { - ZStack(alignment: .bottomLeading) { - RoundedRectangle(cornerRadius: 30, style: .continuous) - .fill( - LinearGradient( - colors: [ - request.risk == .routine ? dashboardAccent.opacity(0.92) : Color.orange.opacity(0.92), - dashboardGold.opacity(0.88) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) - - VStack(alignment: .leading, spacing: 12) { - Text(request.trustHeadline) - .font(.headline) - .foregroundStyle(.white.opacity(0.86)) - Text(request.title) - .font(.system(size: 30, weight: .bold, design: .rounded)) - .foregroundStyle(.white) - Text(request.subtitle) - .foregroundStyle(.white.opacity(0.86)) - } - .padding(24) - } - .frame(minHeight: 210) - } -} - -private struct NotificationCard: View { - let notification: AppNotification - let compactLayout: Bool - let onMarkRead: () -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 14) { - HStack(alignment: .top, spacing: 14) { - Image(systemName: notification.kind.systemImage) - .font(.title3) - .frame(width: 38, height: 38) - .background(.thinMaterial, in: Circle()) - .foregroundStyle(accentColor) - - VStack(alignment: .leading, spacing: 8) { - HStack { - Text(notification.title) - .font(.headline) - Spacer() - if notification.isUnread { - StatusBadge(title: "Unread", tone: .orange) - } - } - - Text(notification.kind.summary) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - - Text(notification.message) - .foregroundStyle(.secondary) - - Group { - if compactLayout { - VStack(alignment: .leading, spacing: 10) { - timestampLabel - if notification.isUnread { - markReadButton - } - } - } else { - HStack { - timestampLabel - Spacer() - if notification.isUnread { - markReadButton - } - } - } - } - } - .padding(compactLayout ? 16 : 18) - .dashboardSurface(radius: compactLayout ? 22 : 24) - } - - private var timestampLabel: some View { - Text(notification.sentAt.formatted(date: .abbreviated, time: .shortened)) - .font(.footnote) - .foregroundStyle(.secondary) - } - - private var markReadButton: some View { - Button { - onMarkRead() - } label: { - Label("Mark Read", systemImage: "checkmark") - } - .buttonStyle(.bordered) - } - - private var accentColor: Color { - switch notification.kind { - case .approval: + private var accent: Color { + switch request.status { + case .approved: .green - case .security: - .orange - case .system: - .blue + case .rejected: + .red + case .pending: + request.risk == .routine ? dashboardAccent : .orange + } + } + + var body: some View { + AppPanel(compactLayout: true, radius: AppLayout.largeCardRadius) { + AppBadge(title: request.kind.title, tone: accent) + + Text(request.title) + .font(.system(size: 30, weight: .bold, design: .rounded)) + .lineLimit(3) + + Text(request.subtitle) + .foregroundStyle(.secondary) + + HStack(spacing: 8) { + AppStatusTag(title: request.status.title, tone: accent) + AppStatusTag(title: request.risk.title, tone: request.risk == .routine ? dashboardAccent : .orange) + } } } } -private struct NotificationMetricCard: View { - let title: String - let value: String - let subtitle: String - let accent: Color +private struct OneTimePasscodeSheet: View { + let session: AuthSession + + @Environment(\.dismiss) private var dismiss + @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { - VStack(alignment: .leading, spacing: 10) { - Text(title.uppercased()) - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) + NavigationStack { + TimelineView(.periodic(from: .now, by: 1)) { context in + let code = passcode(at: context.date) + let secondsRemaining = renewalCountdown(at: context.date) - Text(value) - .font(.title3.weight(.semibold)) - .foregroundStyle(.primary) + AppScrollScreen(compactLayout: compactLayout) { + AppPanel(compactLayout: compactLayout, radius: AppLayout.largeCardRadius) { + AppBadge(title: "One-time passcode", tone: dashboardGold) - Text(subtitle) - .font(.footnote) - .foregroundStyle(.secondary) - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(accent.opacity(0.10), in: RoundedRectangle(cornerRadius: 20, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 20, style: .continuous) - .stroke(accent.opacity(0.08), lineWidth: 1) - ) - } -} + Text("OTP") + .font(.system(size: compactLayout ? 32 : 40, weight: .bold, design: .rounded)) -private struct NotificationFeedRow: View { - let notification: AppNotification - let isSelected: Bool - let action: () -> Void - - var body: some View { - Button(action: action) { - VStack(alignment: .leading, spacing: 10) { - HStack(alignment: .top, spacing: 12) { - Image(systemName: notification.kind.systemImage) - .font(.headline) - .foregroundStyle(accentColor) - .frame(width: 34, height: 34) - .background(.thinMaterial, in: Circle()) - - VStack(alignment: .leading, spacing: 4) { - Text(notification.title) - .font(.headline) - .foregroundStyle(.primary) - .multilineTextAlignment(.leading) - - Text(notification.kind.summary) + Text("Share this code only with the site or device asking you to prove that it is really you.") .font(.subheadline) .foregroundStyle(.secondary) - } - Spacer(minLength: 0) + Text(code) + .font(.system(size: compactLayout ? 42 : 54, weight: .bold, design: .rounded).monospacedDigit()) + .tracking(compactLayout ? 4 : 6) + .frame(maxWidth: .infinity) + .padding(.vertical, compactLayout ? 16 : 20) + .background(AppTheme.mutedFill, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) + .overlay( + RoundedRectangle(cornerRadius: 24, style: .continuous) + .stroke(AppTheme.border, lineWidth: 1) + ) - if notification.isUnread { - Circle() - .fill(Color.orange) - .frame(width: 10, height: 10) + HStack(spacing: 8) { + AppStatusTag(title: "Renews in \(secondsRemaining)s", tone: dashboardGold) + AppStatusTag(title: session.originHost, tone: dashboardAccent) + } + + Divider() + + AppKeyValue(label: "Client", value: session.deviceName) + AppKeyValue(label: "Linked", value: session.pairedAt.formatted(date: .abbreviated, time: .shortened)) } } - - Text(notification.message) - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(2) - .multilineTextAlignment(.leading) - - HStack { - StatusBadge(title: notification.kind.title, tone: accentColor) - Spacer() - Text(notification.sentAt.formatted(date: .omitted, time: .shortened)) - .font(.footnote) - .foregroundStyle(.secondary) - } } - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background(backgroundStyle, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) - .overlay( - RoundedRectangle(cornerRadius: 24, style: .continuous) - .stroke(isSelected ? accentColor.opacity(0.35) : Color.clear, lineWidth: 1.5) - ) - } - .buttonStyle(.plain) - } - - private var accentColor: Color { - switch notification.kind { - case .approval: - .green - case .security: - .orange - case .system: - .blue - } - } - - private var backgroundStyle: Color { - isSelected ? accentColor.opacity(0.10) : Color.white.opacity(0.58) - } -} - -private struct NotificationWorkbenchDetail: View { - let notification: AppNotification - let permissionState: NotificationPermissionState - let onMarkRead: () -> Void - - private let columns = [ - GridItem(.flexible(), spacing: 12), - GridItem(.flexible(), spacing: 12) - ] - - var body: some View { - VStack(alignment: .leading, spacing: 18) { - ZStack(alignment: .bottomLeading) { - RoundedRectangle(cornerRadius: 30, style: .continuous) - .fill( - LinearGradient( - colors: [ - accentColor.opacity(0.95), - accentColor.opacity(0.70), - dashboardGold.opacity(0.82) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - ) - - VStack(alignment: .leading, spacing: 12) { - HStack(spacing: 8) { - StatusBadge(title: notification.kind.title, tone: .white) - StatusBadge(title: notification.isUnread ? "Unread" : "Read", tone: .white) + .navigationTitle("OTP") + .inlineNavigationTitleOnIOS() + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Close") { + dismiss() } - - Text(notification.title) - .font(.system(size: 30, weight: .bold, design: .rounded)) - .foregroundStyle(.white) - - Text(notification.message) - .foregroundStyle(.white.opacity(0.9)) - } - .padding(24) - } - .frame(minHeight: 210) - - LazyVGrid(columns: columns, spacing: 12) { - FactCard(label: "Category", value: notification.kind.summary) - FactCard(label: "Sent", value: notification.sentAt.formatted(date: .abbreviated, time: .shortened)) - FactCard(label: "Inbox State", value: notification.isUnread ? "Still highlighted" : "Already cleared") - FactCard(label: "Delivery", value: permissionState.title) - } - - VStack(alignment: .leading, spacing: 10) { - Text("Delivery Context") - .font(.headline) - - Text(permissionState.summary) - .foregroundStyle(.secondary) - - Text(notification.isUnread ? "This alert is still asking for attention in the in-app feed." : "This alert has already been acknowledged in the mock inbox.") - .font(.headline) - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 26, style: .continuous)) - - if notification.isUnread { - Button { - onMarkRead() - } label: { - Label("Mark Read", systemImage: "checkmark") - } - .buttonStyle(.borderedProminent) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - private var accentColor: Color { - switch notification.kind { - case .approval: - .green - case .security: - .orange - case .system: - .blue - } - } -} - -private struct SectionCard: View { - let title: String - let subtitle: String - let compactLayout: Bool - let content: () -> Content - - init( - title: String, - subtitle: String, - compactLayout: Bool = false, - @ViewBuilder content: @escaping () -> Content - ) { - self.title = title - self.subtitle = subtitle - self.compactLayout = compactLayout - self.content = content - } - - var body: some View { - VStack(alignment: .leading, spacing: 18) { - VStack(alignment: .leading, spacing: 6) { - Text(title) - .font(.title2.weight(.semibold)) - Text(subtitle) - .foregroundStyle(.secondary) - } - - content() - } - .padding(compactLayout ? DashboardSpacing.compactSectionPadding : DashboardSpacing.regularSectionPadding) - .frame(maxWidth: .infinity, alignment: .leading) - .dashboardSurface(radius: compactLayout ? DashboardSpacing.compactRadius : DashboardSpacing.regularRadius) - } -} - -private struct BannerCard: View { - let message: String - let compactLayout: Bool - - var body: some View { - HStack(spacing: 12) { - Image(systemName: "sparkles") - .font(.title3) - .foregroundStyle(dashboardAccent) - Text(message) - .font(compactLayout ? .subheadline.weight(.semibold) : .headline) - } - .padding(.horizontal, 16) - .padding(.vertical, 12) - .dashboardSurface(radius: 999, fillOpacity: 0.84) - } -} - -private struct SmallMetricPill: View { - let title: String - let value: String - - var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(title.uppercased()) - .font(.caption2.weight(.semibold)) - .foregroundStyle(.secondary) - Text(value) - .font(.headline) - } - .padding(.horizontal, 12) - .padding(.vertical, 10) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) - } -} - -private struct HeroMetric: View { - let title: String - let value: String - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - Text(title.uppercased()) - .font(.caption.weight(.semibold)) - .foregroundStyle(.white.opacity(0.72)) - Text(value) - .font(.title2.weight(.bold)) - .foregroundStyle(.white) - } - .padding(.horizontal, 16) - .padding(.vertical, 14) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.white.opacity(0.12), in: RoundedRectangle(cornerRadius: 20, style: .continuous)) - } -} - -private struct GuidanceRow: View { - let icon: String - let title: String - let message: String - - var body: some View { - HStack(alignment: .top, spacing: 12) { - Image(systemName: icon) - .font(.title3) - .frame(width: 32) - .foregroundStyle(dashboardAccent) - - VStack(alignment: .leading, spacing: 4) { - Text(title) - .font(.headline) - Text(message) - .foregroundStyle(.secondary) - } - } - } -} - -private struct GuidanceCard: View { - let icon: String - let title: String - let message: String - - var body: some View { - VStack(alignment: .leading, spacing: 12) { - Image(systemName: icon) - .font(.title3) - .foregroundStyle(dashboardAccent) - - Text(title) - .font(.headline) - - Text(message) - .foregroundStyle(.secondary) - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 24, style: .continuous)) - } -} - -private struct FlowScopes: View { - let scopes: [String] - - var body: some View { - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - ForEach(scopes, id: \.self) { scope in - Text(scope) - .font(.caption.monospaced()) - .padding(.horizontal, 10) - .padding(.vertical, 8) - .background(.thinMaterial, in: Capsule()) } } } } + + private var compactLayout: Bool { + #if os(iOS) + horizontalSizeClass == .compact + #else + false + #endif + } + + private func passcode(at date: Date) -> String { + let timeSlot = Int(date.timeIntervalSince1970 / 30) + let digest = SHA256.hash(data: Data("\(session.pairingCode)|\(timeSlot)".utf8)) + let value = digest.prefix(4).reduce(UInt32(0)) { partialResult, byte in + (partialResult << 8) | UInt32(byte) + } + + return String(format: "%06d", locale: Locale(identifier: "en_US_POSIX"), Int(value % 1_000_000)) + } + + private func renewalCountdown(at date: Date) -> Int { + let elapsed = Int(date.timeIntervalSince1970) % 30 + return elapsed == 0 ? 30 : 30 - elapsed + } } private struct EmptyStateCopy: View { @@ -3073,67 +1150,3 @@ private struct EmptyStateCopy: View { .padding(.vertical, 10) } } - -private struct FactCard: View { - let label: String - let value: String - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - Text(label.uppercased()) - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - Text(value) - .font(.body) - } - .padding(14) - .frame(maxWidth: .infinity, alignment: .leading) - .dashboardSurface(radius: 18) - } -} - -private struct StatusBadge: View { - let title: String - let tone: Color - - var body: some View { - Text(title) - .font(.caption.weight(.semibold)) - .lineLimit(1) - .minimumScaleFactor(0.8) - .fixedSize(horizontal: true, vertical: false) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background(tone.opacity(0.14), in: Capsule()) - .foregroundStyle(tone) - } -} - -private struct DashboardBackdrop: View { - var body: some View { - LinearGradient( - colors: [ - Color(red: 0.98, green: 0.98, blue: 0.97), - Color.white, - Color(red: 0.97, green: 0.98, blue: 0.99) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - .overlay(alignment: .topLeading) { - Circle() - .fill(dashboardAccent.opacity(0.10)) - .frame(width: 360, height: 360) - .blur(radius: 70) - .offset(x: -120, y: -120) - } - .overlay(alignment: .bottomTrailing) { - Circle() - .fill(dashboardGold.opacity(0.12)) - .frame(width: 420, height: 420) - .blur(radius: 90) - .offset(x: 140, y: 160) - } - .ignoresSafeArea() - } -} diff --git a/WatchApp/App/IDPGlobalWatchApp.swift b/WatchApp/App/IDPGlobalWatchApp.swift new file mode 100644 index 0000000..57cf75a --- /dev/null +++ b/WatchApp/App/IDPGlobalWatchApp.swift @@ -0,0 +1,33 @@ +import SwiftUI + +@main +struct IDPGlobalWatchApp: App { + @StateObject private var model = AppViewModel() + + var body: some Scene { + WindowGroup { + WatchRootView(model: model) + .task { + await model.bootstrap() + } + .alert("Something went wrong", isPresented: errorPresented) { + Button("OK") { + model.errorMessage = nil + } + } message: { + Text(model.errorMessage ?? "") + } + } + } + + private var errorPresented: Binding { + Binding( + get: { model.errorMessage != nil }, + set: { isPresented in + if !isPresented { + model.errorMessage = nil + } + } + ) + } +} diff --git a/WatchApp/Features/WatchRootView.swift b/WatchApp/Features/WatchRootView.swift new file mode 100644 index 0000000..0f43c8c --- /dev/null +++ b/WatchApp/Features/WatchRootView.swift @@ -0,0 +1,479 @@ +import Foundation +import SwiftUI + +private let watchAccent = AppTheme.accent +private let watchGold = AppTheme.warmAccent + +struct WatchRootView: View { + @ObservedObject var model: AppViewModel + + var body: some View { + NavigationStack { + Group { + if model.session == nil { + WatchPairingView(model: model) + } else { + WatchDashboardView(model: model) + } + } + .navigationBarTitleDisplayMode(.inline) + } + .tint(watchAccent) + } +} + +private struct WatchPairingView: View { + @ObservedObject var model: AppViewModel + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 12) { + AppPanel(compactLayout: true, radius: 22) { + AppBadge(title: "Preview passport", tone: watchAccent) + + Text("Prove identity from your wrist") + .font(.title3.weight(.semibold)) + + Text("This preview connects directly to the mock service today.") + .font(.footnote) + .foregroundStyle(.secondary) + + HStack(spacing: 8) { + AppStatusTag(title: "Wrist-ready", tone: watchAccent) + AppStatusTag(title: "Preview sync", tone: watchGold) + } + } + + if model.isBootstrapping { + ProgressView("Preparing preview passport...") + .frame(maxWidth: .infinity, alignment: .leading) + } + + Button { + Task { + await model.signInWithSuggestedPayload() + } + } label: { + if model.isAuthenticating { + ProgressView() + .frame(maxWidth: .infinity) + } else { + Label("Use Preview Passport", systemImage: "qrcode") + .frame(maxWidth: .infinity) + } + } + .buttonStyle(.borderedProminent) + .disabled(model.isBootstrapping || model.suggestedPairingPayload.isEmpty || model.isAuthenticating) + + AppPanel(compactLayout: true, radius: 18) { + Text("What works today") + .font(.headline) + + Text("The watch shows pending identity checks, recent alerts, and quick actions.") + .font(.footnote) + .foregroundStyle(.secondary) + } + } + .padding(.horizontal, 8) + .padding(.bottom, 20) + } + .navigationTitle("Set Up Watch") + } +} + +private struct WatchInfoPill: View { + let title: String + let value: String + let tone: Color + + var body: some View { + VStack(alignment: .leading, spacing: 2) { + Text(title) + .font(.caption2) + .foregroundStyle(.secondary) + Text(value) + .font(.caption.weight(.semibold)) + .foregroundStyle(.primary) + } + .padding(.horizontal, 10) + .padding(.vertical, 8) + .frame(maxWidth: .infinity, alignment: .leading) + .background(tone.opacity(0.10), in: RoundedRectangle(cornerRadius: 16, style: .continuous)) + } +} + +private struct WatchDashboardView: View { + @ObservedObject var model: AppViewModel + + var body: some View { + List { + Section { + WatchPassportCard(model: model) + } + + Section("Pending") { + if model.pendingRequests.isEmpty { + Text("No checks waiting.") + .foregroundStyle(.secondary) + + Button("Seed Identity Check") { + Task { + await model.simulateIncomingRequest() + } + } + } else { + ForEach(model.pendingRequests) { request in + NavigationLink { + WatchRequestDetailView(model: model, requestID: request.id) + } label: { + WatchRequestRow(request: request) + } + } + } + } + + Section("Recent Activity") { + if model.notifications.isEmpty { + Text("No recent alerts.") + .foregroundStyle(.secondary) + } else { + ForEach(model.notifications.prefix(3)) { notification in + NavigationLink { + WatchNotificationDetailView(model: model, notificationID: notification.id) + } label: { + WatchNotificationRow(notification: notification) + } + } + } + } + + Section("Actions") { + Button("Refresh") { + Task { + await model.refreshDashboard() + } + } + .disabled(model.isRefreshing) + + Button("Send Test Alert") { + Task { + await model.sendTestNotification() + } + } + + if model.notificationPermission == .unknown || model.notificationPermission == .denied { + Button("Enable Alerts") { + Task { + await model.requestNotificationAccess() + } + } + } + } + + Section("Account") { + if let profile = model.profile { + VStack(alignment: .leading, spacing: 4) { + Text(profile.handle) + .font(.headline) + Text(profile.organization) + .font(.footnote) + .foregroundStyle(.secondary) + } + } + + VStack(alignment: .leading, spacing: 4) { + Text("Notifications") + .font(.headline) + Text(model.notificationPermission.title) + .font(.footnote) + .foregroundStyle(.secondary) + } + + Button("Sign Out", role: .destructive) { + model.signOut() + } + } + } + .navigationTitle("Passport") + .refreshable { + await model.refreshDashboard() + } + } +} + +private struct WatchPassportCard: View { + @ObservedObject var model: AppViewModel + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + VStack(alignment: .leading, spacing: 2) { + Text(model.profile?.name ?? "Preview Session") + .font(.headline) + Text(model.pairedDeviceSummary) + .font(.footnote) + .foregroundStyle(.secondary) + if let session = model.session { + Text("Via \(session.pairingTransport.title)") + .font(.caption2) + .foregroundStyle(.secondary) + } + } + + HStack(spacing: 8) { + WatchMetricPill(title: "Pending", value: "\(model.pendingRequests.count)", accent: watchAccent) + WatchMetricPill(title: "Unread", value: "\(model.unreadNotificationCount)", accent: watchGold) + } + } + .padding(.vertical, 6) + } +} + +private struct WatchMetricPill: View { + let title: String + let value: String + let accent: Color + + var body: some View { + VStack(alignment: .leading, spacing: 2) { + Text(value) + .font(.headline.monospacedDigit()) + Text(title) + .font(.caption2) + .foregroundStyle(.secondary) + } + .padding(.horizontal, 10) + .padding(.vertical, 8) + .frame(maxWidth: .infinity, alignment: .leading) + .background(accent.opacity(0.14), in: RoundedRectangle(cornerRadius: 14, style: .continuous)) + } +} + +private struct WatchRequestRow: View { + let request: ApprovalRequest + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + HStack(alignment: .top, spacing: 6) { + Text(request.title) + .font(.headline) + .lineLimit(2) + + Spacer(minLength: 6) + + Image(systemName: request.risk == .elevated ? "exclamationmark.shield.fill" : "checkmark.shield.fill") + .foregroundStyle(request.risk == .elevated ? .orange : watchAccent) + } + + Text(request.source) + .font(.footnote) + .foregroundStyle(.secondary) + + Text(request.createdAt.watchRelativeString) + .font(.caption2) + .foregroundStyle(.secondary) + } + .padding(.vertical, 2) + } +} + +private struct WatchNotificationRow: View { + let notification: AppNotification + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + HStack(alignment: .top, spacing: 6) { + Text(notification.title) + .font(.headline) + .lineLimit(2) + + Spacer(minLength: 6) + + if notification.isUnread { + Circle() + .fill(watchAccent) + .frame(width: 8, height: 8) + } + } + + Text(notification.message) + .font(.footnote) + .foregroundStyle(.secondary) + .lineLimit(2) + + Text(notification.sentAt.watchRelativeString) + .font(.caption2) + .foregroundStyle(.secondary) + } + .padding(.vertical, 2) + } +} + +private struct WatchRequestDetailView: View { + @ObservedObject var model: AppViewModel + let requestID: ApprovalRequest.ID + + private var request: ApprovalRequest? { + model.requests.first(where: { $0.id == requestID }) + } + + var body: some View { + Group { + if let request { + ScrollView { + VStack(alignment: .leading, spacing: 12) { + detailHeader( + title: request.title, + subtitle: request.source, + badge: request.status.title + ) + + Text(request.subtitle) + .font(.footnote) + .foregroundStyle(.secondary) + + VStack(alignment: .leading, spacing: 6) { + Text("Trust Summary") + .font(.headline) + Text(request.trustHeadline) + .font(.subheadline.weight(.semibold)) + Text(request.trustDetail) + .font(.footnote) + .foregroundStyle(.secondary) + Text(request.risk.guidance) + .font(.footnote) + .foregroundStyle(.secondary) + } + .padding(10) + .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) + + if !request.scopes.isEmpty { + VStack(alignment: .leading, spacing: 8) { + Text("Scopes") + .font(.headline) + + ForEach(request.scopes, id: \.self) { scope in + Label(scope, systemImage: "checkmark.seal.fill") + .font(.footnote) + } + } + } + + if request.status == .pending { + if model.activeRequestID == request.id { + ProgressView("Updating proof...") + } else { + Button("Verify") { + Task { + await model.approve(request) + } + } + .buttonStyle(.borderedProminent) + + Button("Decline", role: .destructive) { + Task { + await model.reject(request) + } + } + } + } + } + .padding(.horizontal, 8) + .padding(.bottom, 20) + } + } else { + Text("This request is no longer available.") + .foregroundStyle(.secondary) + } + } + .navigationTitle("Identity Check") + } + + private func detailHeader(title: String, subtitle: String, badge: String) -> some View { + VStack(alignment: .leading, spacing: 6) { + Text(title) + .font(.headline) + + Text(subtitle) + .font(.footnote) + .foregroundStyle(.secondary) + + Text(badge) + .font(.caption.weight(.semibold)) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background(watchAccent.opacity(0.14), in: Capsule()) + } + } +} + +private struct WatchNotificationDetailView: View { + @ObservedObject var model: AppViewModel + let notificationID: AppNotification.ID + + private var notification: AppNotification? { + model.notifications.first(where: { $0.id == notificationID }) + } + + var body: some View { + Group { + if let notification { + ScrollView { + VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 6) { + Text(notification.title) + .font(.headline) + Text(notification.kind.title) + .font(.footnote.weight(.semibold)) + .foregroundStyle(watchAccent) + Text(notification.sentAt.watchRelativeString) + .font(.caption2) + .foregroundStyle(.secondary) + } + + Text(notification.message) + .font(.footnote) + .foregroundStyle(.secondary) + + VStack(alignment: .leading, spacing: 6) { + Text("Alert posture") + .font(.headline) + Text(model.notificationPermission.summary) + .font(.footnote) + .foregroundStyle(.secondary) + } + .padding(10) + .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) + + if notification.isUnread { + Button("Mark Read") { + Task { + await model.markNotificationRead(notification) + } + } + } + } + .padding(.horizontal, 8) + .padding(.bottom, 20) + } + } else { + Text("This activity item has already been cleared.") + .foregroundStyle(.secondary) + } + } + .navigationTitle("Activity") + } +} + +private extension Date { + var watchRelativeString: String { + WatchFormatters.relative.localizedString(for: self, relativeTo: .now) + } +} + +private enum WatchFormatters { + static let relative: RelativeDateTimeFormatter = { + let formatter = RelativeDateTimeFormatter() + formatter.unitsStyle = .abbreviated + return formatter + }() +}