From 63634532cebab195a94736fabce9afaa1afe8d60 Mon Sep 17 00:00:00 2001 From: Rodger-Wang <1367893453@qq.com> Date: Sat, 12 Sep 2026 20:05:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=AD=E9=9F=B3=E7=BA=AA=E8=A6=81=E7=AD=89?= =?UTF-8?q?=E5=BE=85=E6=80=81=E6=8D=A2=E6=88=90=E8=87=AA=E7=BB=98=E5=8A=A8?= =?UTF-8?q?=E6=95=88=EF=BC=9B=E4=BF=AE=20tasktype=20=E5=AD=98=E4=B8=A4?= =?UTF-8?q?=E5=BC=A0=E8=A1=A8=E5=AF=BC=E8=87=B4=E9=87=8D=E8=BF=9B=E5=90=8E?= =?UTF-8?q?=E7=AD=89=E5=BE=85=E6=80=81=E6=B6=88=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 等待态 原来是 assets/lottie/meeting_wait.json —— 一张「JOIN」对话气泡插画,和本页在做的事 (把音频变成文稿)没有任何关系,配色也与全站的 222° 冷蓝灰不搭,深色主题下更是一块 突兀的白。改成自绘:上面一排声波表示音频正在被读,下面几条带流光的骨架行预告即将 生成的文稿形状,两者共用同一个 AnimationController。 自绘而不是再换一个 Lottie:① 不用为一个等待态再背一份 json 资源;② 颜色全部走 AppPalette,明暗主题自动跟随,插画做不到;③ 四个 tab(概览/发言/全文/思维导图) 共用同一个等待态,自绘好调。meeting_wait.json 一并删除(全仓零引用;assets/lottie/ 在 pubspec 里是按目录声明的,不用改配置)。 ## 重进后等待态消失 —— tasktype 在两张表里各存一份 真机上那条记录的实际状态是 meeting.tasktype=1 / meetingdetails.tasktype=0: 列表页读前者,显示「转写中」;详情页读后者,拿到 0,于是什么等待态都没有。 两张表分头写,而且中间态漏了: - submitTask / refreshTask / readTask 只调 editMeetingTitle,**只写 meeting** - _queryTask 里写 meetingdetails 的两次都藏在里程碑分支里(>=3、==5/6), 1→2(等待转写→转写中)这一跳、以及失败态 10002,meetingdetails 一次都不写 首次进入之所以有动画,靠的是详情控制器里那句内存赋值 meetingDetails.value.tasktype=1; 控制器一销毁,重进读库就是 0 —— 表现为「退出重进特效就不见了」。 改法: 1. SqfliteApi.setMeetingTaskType(id, type):一个事务同时写两张表,成为写 tasktype 的 **唯一入口**。⚠️ 别再直接 editMeetingTitle({'tasktype': x}),那只写一张。 2. 轮询里的状态推进从两个里程碑分支里提到分支之后无条件执行 —— 数据先落、状态最后推, 详情页的 ever(tasktype) 监听读到新状态时数据已经就位。tasktype.value 同样不再只在 分支里更新,1→2 这一跳现在也会通知 UI。 3. 详情页以 meeting 表那份为准(它是历史上唯一每次状态变化都会写的),给**存量**错位 数据兜底:不用等下一次状态跳变就能立刻正常。 真机验证(华为 ALN-AL80):用那条 details=0/meeting=1 的错位记录进详情,等待态正常 (改前是空白页);退出重进,等待态仍在;退出后查库两张表都是 1;轮询把状态推到失败态后 两张表都是 10002(改前 details 恒为 0);终态下等待态正确消失、显示「分析失败」。 Co-Authored-By: Claude Opus 5 (1M context) --- apps/client/assets/lottie/meeting_wait.json | 1 - .../lib/data/services/db/sqflite_api.dart | 19 ++ .../meeting/meeting_task_service.dart | 35 ++-- .../meeting_details_controller.dart | 6 + .../meeting/views/meeting_details_view.dart | 37 +--- .../widgets/transcribing_placeholder.dart | 175 ++++++++++++++++++ 6 files changed, 217 insertions(+), 56 deletions(-) delete mode 100644 apps/client/assets/lottie/meeting_wait.json create mode 100644 apps/client/lib/modules/meeting/views/widgets/transcribing_placeholder.dart diff --git a/apps/client/assets/lottie/meeting_wait.json b/apps/client/assets/lottie/meeting_wait.json deleted file mode 100644 index 49f02a46..00000000 --- a/apps/client/assets/lottie/meeting_wait.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"5.6.3","fr":24,"ip":0,"op":75,"w":1000,"h":1000,"nm":"step two","ddd":0,"assets":[],"fonts":{"list":[{"fName":"Lato-Heavy","fFamily":"Lato","fStyle":"Heavy","ascent":74.6490478515625}]},"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL CONTROL 2","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[288.769,691.391,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"ADD","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.142],"y":[1]},"o":{"x":[0.858],"y":[0]},"t":3,"s":[-360]},{"i":{"x":[0.142],"y":[1]},"o":{"x":[0.858],"y":[0]},"t":33,"s":[0]},{"t":69,"s":[360]}],"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2},"a":{"a":0,"k":[-229.438,165.533,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.344,0.344,0.344],"y":[1,1,1]},"o":{"x":[0.656,0.656,0.656],"y":[0,0,0]},"t":3,"s":[0,0,100]},{"i":{"x":[0.344,0.344,0.344],"y":[1,1,1]},"o":{"x":[0.656,0.656,0.656],"y":[0,0,0]},"t":31,"s":[78,78,100]},{"t":69,"s":[0,0,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-9.621,-0.032],[0,0]],"o":[[0,0],[9.621,0.032],[0,0]],"v":[[-247.707,182.908],[-229.219,168.377],[-211.951,183.186]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[50.984,50.984],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":11,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-228.399,158.129],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[42,42],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[50.984,50.984],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.341176470588,0.635294117647,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.772549019608,0.682352941176,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-229.438,165.533],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Artwork 30","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":":) 2","parent":5,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":48,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[100]},{"t":51,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.559,-25.807,0],"ix":2},"a":{"a":0,"k":[6.559,-25.807,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-19.941,-48.382],[-22.844,-48.382],[-22.844,3.97],[-19.941,3.97]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"},{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[35.961,-75.882],[4.156,-75.882],[4.156,24.269],[35.961,24.269]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 2"}],"t":{"d":{"k":[{"s":{"s":86.2156295776367,"f":"Lato-Heavy","t":":)","j":2,"tr":200,"lh":103.458755493164,"ls":0,"fc":[0.941,0.337,0.18]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":-1,"op":242,"st":2,"bm":0},{"ddd":0,"ind":5,"ty":5,"nm":":)","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":48,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[0]},{"t":51,"s":[100]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.227],"y":[1]},"o":{"x":[0.773],"y":[0]},"t":17,"s":[0]},{"i":{"x":[0.227],"y":[1]},"o":{"x":[0.773],"y":[0]},"t":30,"s":[90]},{"t":45,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.227,"y":1},"o":{"x":0.773,"y":0},"t":21,"s":[106.506,-57.313,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.227,"y":1},"o":{"x":0.773,"y":0},"t":30,"s":[106.506,-88.313,0],"to":[0,0,0],"ti":[0,0,0]},{"t":40,"s":[106.506,-57.313,0]}],"ix":2},"a":{"a":0,"k":[0.668,-27.007,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":86.2156295776367,"f":"Lato-Heavy","t":":)","j":2,"tr":200,"lh":103.458755493164,"ls":0,"fc":[0.941,0.337,0.18]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"NULL CONTROL 3","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.354,"y":1},"o":{"x":0.43,"y":0},"t":9,"s":[556.506,461.687,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":1},"o":{"x":0.773,"y":0},"t":16,"s":[556.506,330.687,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.227,"y":0.227},"o":{"x":0.773,"y":0.773},"t":30,"s":[556.506,392.687,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.227,"y":1},"o":{"x":0.773,"y":0},"t":52,"s":[556.506,392.687,0],"to":[0,0,0],"ti":[0,0,0]},{"t":68,"s":[556.506,461.687,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"step two 8","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-6.506,157.313,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.005,1.048],[0,0],[0.692,0],[0,0],[-0.918,-0.74],[0,0]],"o":[[0,0],[0.003,-0.692],[0,0],[-1.179,0],[0,0],[0.816,0.658]],"v":[[184.356,-111.238],[184.669,-183.522],[183.42,-184.777],[93.468,-184.777],[92.684,-182.554],[182.322,-110.27]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.772549033165,0.68235296011,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"step two 7","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-6.506,157.313,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.85,0],[0,0],[0,3.85],[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0]],"o":[[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0],[3.85,0],[0,0],[0,3.85]],"v":[[206.07,-147.589],[28.946,-147.589],[21.946,-154.589],[21.946,-240.144],[28.946,-247.144],[206.07,-247.144],[213.07,-240.144],[213.07,-154.589]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.772549033165,0.68235296011,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":5,"nm":"join","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204.454,-131.29,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":72,"f":"Lato-Heavy","t":"JOIN","j":2,"tr":200,"lh":86.4,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"step two 11","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[305.441,421.46,0],"ix":2},"a":{"a":0,"k":[-194.559,-78.54,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[14.074,15.148],[13.632,20.976],[17.827,15.159],[0,0]],"o":[[-13.495,-14.525],[-16.251,-25.007],[-20.723,-17.622],[0,0]],"v":[[-194.559,-78.54],[-204.608,-144.479],[-277.9,-152.525],[-274.454,-203.938]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.976470589638,0.905882358551,0.050980392843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":33,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.711],"y":[1]},"o":{"x":[0.289],"y":[0]},"t":54,"s":[0]},{"t":75,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.711],"y":[1]},"o":{"x":[0.289],"y":[0]},"t":41,"s":[0]},{"t":58,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"step two 6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[305.441,421.46,0],"ix":2},"a":{"a":0,"k":[-194.559,-78.54,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[14.074,15.148],[13.632,20.976],[17.827,15.159],[0,0]],"o":[[-13.495,-14.525],[-16.251,-25.007],[-20.723,-17.622],[0,0]],"v":[[-194.559,-78.54],[-204.608,-144.479],[-277.9,-152.525],[-274.454,-203.938]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.976470589638,0.905882358551,0.050980392843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":33,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.711],"y":[1]},"o":{"x":[0.289],"y":[0]},"t":13,"s":[0]},{"t":34,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.711],"y":[1]},"o":{"x":[0.289],"y":[0]},"t":0,"s":[2]},{"t":17,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":3,"nm":"NULL CONTROL 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.227],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[90]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":17,"s":[0]},{"i":{"x":[0.227],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":61,"s":[0]},{"t":72,"s":[90]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.227,"y":1},"o":{"x":0.167,"y":0.167},"t":7,"s":[338.345,780.854,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.227,"y":0.227},"o":{"x":0.167,"y":0.167},"t":15,"s":[338.345,701.854,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.227,"y":1},"o":{"x":0.167,"y":0},"t":59,"s":[338.345,701.854,0],"to":[0,0,0],"ti":[0,0,0]},{"t":70,"s":[338.345,780.854,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.227,0.227,0.227],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,16.667]},"t":3,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.227,0.227,0.227],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":62,"s":[100,100,100]},{"t":68,"s":[0,0,100]}],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"step two 5","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.291,49.482,0],"ix":2},"a":{"a":0,"k":[-162.363,201.337,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.005,1.048],[0,0],[-0.692,0],[0,0],[0.918,-0.74],[0,0]],"o":[[0,0],[-0.003,-0.692],[0,0],[1.179,0],[0,0],[-0.816,0.658]],"v":[[-161.724,200.09],[-162.363,52.431],[-161.113,51.175],[22.636,51.175],[23.42,53.398],[-159.689,201.058]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.250980407,0.341176480055,0.611764729023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"step two 4","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.709,50.518,0],"ix":2},"a":{"a":0,"k":[-160.946,202.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.85,0],[0,0],[0,3.85],[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0]],"o":[[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0],[3.85,0],[0,0],[0,3.85]],"v":[[261.5,102.5],[-261.5,102.5],[-268.5,95.5],[-268.5,-95.5],[-261.5,-102.5],[261.5,-102.5],[268.5,-95.5],[268.5,95.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.250980407,0.341176480055,0.635294139385,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"step two 10","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[337.637,701.337,0],"ix":2},"a":{"a":0,"k":[-162.363,201.337,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.005,1.048],[0,0],[-0.692,0],[0,0],[0.918,-0.74],[0,0]],"o":[[0,0],[-0.003,-0.692],[0,0],[1.179,0],[0,0],[-0.816,0.658]],"v":[[-161.724,200.09],[-162.363,52.431],[-161.113,51.175],[22.636,51.175],[23.42,53.398],[-159.689,201.058]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.949019607843,0.952941176471,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"step two 9","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[339.054,702.372,0],"ix":2},"a":{"a":0,"k":[-160.946,202.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.85,0],[0,0],[0,3.85],[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0]],"o":[[0,0],[-3.85,0],[0,0],[0,-3.85],[0,0],[3.85,0],[0,0],[0,3.85]],"v":[[261.5,102.5],[-261.5,102.5],[-268.5,95.5],[-268.5,-95.5],[-261.5,-102.5],[261.5,-102.5],[268.5,-95.5],[268.5,95.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.949019607843,0.952941176471,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"step two 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":7,"s":[360]},{"t":53,"s":[0]}],"ix":10},"p":{"a":0,"k":[601.542,678.252,0],"ix":2},"a":{"a":0,"k":[101.542,178.252,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-57.479,3.971],[0,0]],"o":[[0,0],[57.479,-3.971],[0,0]],"v":[[29.478,157.301],[104.912,207.014],[173.606,149.279]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.349019616842,0.494117647409,0.819607853889,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":33,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[0]},{"t":50,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":29,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":3,"nm":"NULL CONTROL ","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":186,"ix":10},"p":{"a":0,"k":[689.172,563.206,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"blue blob","parent":18,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.965,"y":1},"o":{"x":0.035,"y":0},"t":0,"s":[22.126,71.025,0],"to":[0.239,-28.368,0],"ti":[1.887,-29.086,0]},{"i":{"x":0.965,"y":1},"o":{"x":0.035,"y":0},"t":38,"s":[65.66,71.025,0],"to":[-1.887,29.086,0],"ti":[-0.261,29.632,0]},{"t":75,"s":[22.126,71.025,0]}],"ix":2},"a":{"a":0,"k":[-1857.74,12.368,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.777,"y":1},"o":{"x":0.223,"y":0},"t":0,"s":[{"i":[[27.446,17.506],[16.16,10.052],[29.683,-6.073],[16.027,-24.443],[6.9,-20.868],[-3.773,-18.47],[-20.293,-8.765],[-17.671,1.505],[-20.407,9.661],[-21.669,6.911],[-2.347,17.47]],"o":[[-12.631,-8.056],[-26.087,-16.227],[-29.134,5.96],[-6.796,10.365],[-5.987,18.109],[5.219,25.546],[20.293,8.765],[22.512,-1.917],[14.354,-6.795],[21.669,-6.911],[4.382,-32.611]],"v":[[-1724.939,-56.574],[-1817.205,-112.801],[-1903.685,-126.471],[-1973.523,-76.468],[-2025.428,24.858],[-2027.401,80.891],[-1980.293,139.235],[-1882.645,153.556],[-1820.841,137.199],[-1730.669,87.911],[-1686.101,23.648]],"c":true}]},{"i":{"x":0.777,"y":1},"o":{"x":0.223,"y":0},"t":23,"s":[{"i":[[28.205,16.095],[20.842,4.302],[30.35,-10.558],[19.526,-22.806],[6.9,-20.868],[-3.773,-18.47],[-18.807,-10.984],[-24.232,4.485],[-17.658,16.707],[-21.669,6.91],[-2.198,26.097]],"o":[[-18.441,-9.846],[-27.353,-8.444],[-27.861,9.175],[-7.857,9.36],[-5.987,18.109],[5.219,25.546],[20.293,12.431],[22.261,-3.306],[13.031,-13.299],[21.669,-6.91],[3.401,-32.698]],"v":[[-1713.272,-80.241],[-1804.205,-122.468],[-1891.351,-117.804],[-1959.523,-71.134],[-2007.094,13.858],[-2009.401,69.558],[-1965.96,134.902],[-1857.978,164.889],[-1794.174,137.532],[-1727.003,71.911],[-1672.434,2.982]],"c":true}]},{"i":{"x":0.777,"y":1},"o":{"x":0.223,"y":0},"t":48,"s":[{"i":[[30.699,16.525],[31.868,-6.819],[30.089,-8.801],[28.455,-17.137],[6.9,-20.869],[-3.773,-18.47],[-19.389,-10.115],[-28.694,-1.768],[-25.913,11.933],[-10.214,23.322],[-2.257,22.717]],"o":[[-20.415,-12.618],[-31.927,3.629],[-28.36,7.915],[-16.12,10.541],[-5.987,18.109],[5.219,25.546],[20.293,10.995],[23.438,-0.654],[16.095,-8.772],[8.992,-25.333],[3.786,-32.664]],"v":[[-1728.917,-134.042],[-1832.891,-163.458],[-1900.999,-119.274],[-1973.193,-96.817],[-2024.87,-14.091],[-2030.417,50.887],[-1979.761,112.526],[-1871.327,147.63],[-1762.655,136.243],[-1704.725,70.629],[-1688.381,-29.847]],"c":true}]},{"t":75,"s":[{"i":[[27.446,17.506],[16.16,10.052],[29.683,-6.073],[16.027,-24.443],[6.9,-20.868],[-3.773,-18.47],[-20.293,-8.765],[-17.671,1.505],[-20.407,9.661],[-21.669,6.911],[-2.347,17.47]],"o":[[-12.631,-8.056],[-26.087,-16.227],[-29.134,5.96],[-6.796,10.365],[-5.987,18.109],[5.219,25.546],[20.293,8.765],[22.512,-1.917],[14.354,-6.795],[21.669,-6.911],[4.382,-32.611]],"v":[[-1724.939,-56.574],[-1817.205,-112.801],[-1903.685,-126.471],[-1973.523,-76.468],[-2025.428,24.858],[-2027.401,80.891],[-1980.293,139.235],[-1882.645,153.556],[-1820.841,137.199],[-1730.669,87.911],[-1686.101,23.648]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.533333333333,0.870588295133,0.949019667682,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"pink blob","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":37,"s":[27]},{"t":75,"s":[4]}],"ix":10},"p":{"a":0,"k":[265.504,435.394,0],"ix":2},"a":{"a":0,"k":[-2262.496,-68.606,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.442,0.442,0.442],"y":[1,1,1]},"o":{"x":[0.558,0.558,0.558],"y":[0,0,0]},"t":0,"s":[90,90,100]},{"i":{"x":[0.442,0.442,0.442],"y":[1,1,1]},"o":{"x":[0.558,0.558,0.558],"y":[0,0,0]},"t":37,"s":[100,100,100]},{"t":75,"s":[90,90,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-10.555,-9.172],[-13.555,-5.11],[-7.874,-1.554],[-14.596,3.272],[-9.836,16.33],[0.511,14.237],[0.324,2.64],[-2.519,4.863],[1.197,15.338],[10.333,12.602],[23.942,1.318],[6.857,-0.997],[4.443,-1.608],[12.929,-10.601],[6.944,-20.538],[1.151,-10.762],[-2.972,-10.55]],"o":[[10.823,9.405],[7.424,2.799],[14.056,2.775],[19.151,-4.293],[7.574,-12.575],[-0.097,-2.697],[3.365,-4.366],[7.294,-14.084],[-1.297,-16.611],[-14.834,-18.091],[-6.872,-0.378],[-4.635,0.674],[-15.636,5.658],[-17.503,14.352],[-3.533,10.449],[-1.188,11.109],[3.73,13.241]],"v":[[-2339.774,9.371],[-2304.615,29.106],[-2281.567,35.38],[-2239.093,36.905],[-2192.857,1.703],[-2180.38,-40.346],[-2181.022,-48.352],[-2171.921,-62.034],[-2161.9,-104.994],[-2180.279,-147.675],[-2243.83,-175.734],[-2264.499,-173.911],[-2278.056,-170.548],[-2318.794,-147.466],[-2355.826,-91.68],[-2362.583,-59.405],[-2360.741,-25.801]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.945098042488,0.898039221764,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"J","size":72,"style":"Heavy","w":41.9,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.45,-1.816],[0.9,-1.133],[1.333,-0.5],[1.8,0],[0.883,0.2],[0.566,0],[0.533,-0.483],[0.1,-0.8],[0.133,-1.466],[0.133,-1.466],[-1.784,-0.217],[-1.834,0],[-3.034,1.266],[-2.017,2.35],[-1,3.284],[0,4.067]],"o":[[0,0],[0,0],[0,2.6],[-0.45,1.817],[-0.9,1.134],[-1.334,0.5],[-1.3,0],[-0.884,-0.2],[-1,0],[-0.534,0.484],[-0.134,1.467],[-0.134,1.467],[1.966,0.467],[1.783,0.216],[4.033,0],[3.033,-1.266],[2.016,-2.35],[1,-3.283],[0,0]],"v":[[36.3,-72.55],[21.3,-72.55],[21.3,-25.65],[20.625,-19.025],[18.6,-14.6],[15.25,-12.15],[10.55,-11.4],[7.275,-11.7],[5.1,-12],[2.8,-11.275],[1.85,-9.35],[1.45,-4.95],[1.05,-0.55],[6.675,0.475],[12.1,0.8],[22.7,-1.1],[30.275,-6.525],[34.8,-14.975],[36.3,-26]],"c":true},"ix":2},"nm":"J","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"J","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"},{"ch":"O","size":72,"style":"Heavy","w":81.1,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.783,4.517],[3.25,3.317],[4.566,1.884],[5.566,0],[4.566,-1.883],[3.266,-3.3],[1.783,-4.516],[0,-5.3],[-1.784,-4.533],[-3.267,-3.3],[-4.567,-1.883],[-5.567,0],[-4.567,1.884],[-3.25,3.3],[-1.784,4.534],[0,5.3]],"o":[[-1.784,-4.516],[-3.25,-3.316],[-4.567,-1.883],[-5.567,0],[-4.567,1.884],[-3.267,3.3],[-1.784,4.517],[0,5.3],[1.783,4.534],[3.266,3.3],[4.566,1.884],[5.566,0],[4.566,-1.883],[3.25,-3.3],[1.783,-4.533],[0,-5.266]],"v":[[75.025,-50.975],[67.475,-62.725],[55.75,-70.525],[40.55,-73.35],[25.35,-70.525],[13.6,-62.75],[6.025,-51.025],[3.35,-36.3],[6.025,-21.55],[13.6,-9.8],[25.35,-2.025],[40.55,0.8],[55.75,-2.025],[67.475,-9.8],[75.025,-21.55],[77.7,-36.3]],"c":true},"ix":2},"nm":"O","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1,-3.016],[1.883,-2.1],[2.683,-1.116],[3.4,0],[2.7,1.117],[1.883,2.1],[1,3.017],[0,3.834],[-1,3.017],[-1.884,2.117],[-2.7,1.117],[-3.4,0],[-2.684,-1.116],[-1.884,-2.116],[-1,-3.016],[0,-3.8]],"o":[[-1,3.017],[-1.884,2.1],[-2.684,1.117],[-3.4,0],[-2.7,-1.116],[-1.884,-2.1],[-1,-3.016],[0,-3.8],[1,-3.016],[1.883,-2.116],[2.7,-1.116],[3.4,0],[2.683,1.117],[1.883,2.117],[1,3.017],[0,3.834]],"v":[[60.85,-26.025],[56.525,-18.35],[49.675,-13.525],[40.55,-11.85],[31.4,-13.525],[24.525,-18.35],[20.2,-26.025],[18.7,-36.3],[20.2,-46.525],[24.525,-54.225],[31.4,-59.075],[40.55,-60.75],[49.675,-59.075],[56.525,-54.225],[60.85,-46.525],[62.35,-36.3]],"c":true},"ix":2},"nm":"O","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"O","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"},{"ch":"I","size":72,"style":"Heavy","w":30.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[22.7,-72.55],[7.6,-72.55],[7.6,0],[22.7,0]],"c":true},"ix":2},"nm":"I","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"I","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"},{"ch":"N","size":72,"style":"Heavy","w":77.35,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.067,-1.183],[-0.134,-1.266],[0,0],[0.333,0.3],[0.366,0.184],[0.45,0.05],[0.633,0],[0,0],[0,0],[0,0],[0,0],[0.05,1.134],[0.1,1.167],[0,0],[-0.8,-0.383],[-1.167,0],[0,0],[0,0]],"o":[[0,0],[0,1.067],[0.066,1.184],[0,0],[-0.4,-0.5],[-0.334,-0.3],[-0.367,-0.183],[-0.45,-0.05],[0,0],[0,0],[0,0],[0,0],[0,-0.966],[-0.05,-1.133],[0,0],[0.766,0.934],[0.8,0.384],[0,0],[0,0],[0,0]],"v":[[56.5,-72.55],[56.5,-31.05],[56.6,-27.675],[56.9,-24],[20.5,-70.2],[19.4,-71.4],[18.35,-72.125],[17.125,-72.475],[15.5,-72.55],[7.6,-72.55],[7.6,0],[20.85,0],[20.85,-41.95],[20.775,-45.1],[20.55,-48.55],[56.7,-2.55],[59.05,-0.575],[62,0],[69.75,0],[69.75,-72.55]],"c":true},"ix":2},"nm":"N","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"N","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"},{"ch":":","size":86.2156295776367,"style":"Heavy","w":26.1,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.417,-0.966],[-0.734,-0.716],[-0.984,-0.4],[-1.167,0],[-1,0.4],[-0.734,0.717],[-0.417,0.967],[0,1.134],[0.416,0.984],[0.733,0.717],[1,0.417],[1.133,0],[0.983,-0.416],[0.733,-0.716],[0.416,-0.983],[0,-1.1]],"o":[[0.416,0.967],[0.733,0.717],[0.983,0.4],[1.133,0],[1,-0.4],[0.733,-0.716],[0.416,-0.966],[0,-1.1],[-0.417,-0.983],[-0.734,-0.716],[-1,-0.416],[-1.167,0],[-0.984,0.417],[-0.734,0.717],[-0.417,0.984],[0,1.134]],"v":[[5.525,-4.1],[7.25,-1.575],[9.825,0.1],[13.05,0.7],[16.25,0.1],[18.85,-1.575],[20.575,-4.1],[21.2,-7.25],[20.575,-10.375],[18.85,-12.925],[16.25,-14.625],[13.05,-15.25],[9.825,-14.625],[7.25,-12.925],[5.525,-10.375],[4.9,-7.25]],"c":true},"ix":2},"nm":":","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.417,-0.966],[-0.734,-0.716],[-0.984,-0.4],[-1.167,0],[-1,0.4],[-0.734,0.717],[-0.417,0.967],[0,1.134],[0.416,0.984],[0.733,0.717],[1,0.417],[1.133,0],[0.983,-0.416],[0.733,-0.716],[0.416,-0.983],[0,-1.1]],"o":[[0.416,0.967],[0.733,0.717],[0.983,0.4],[1.133,0],[1,-0.4],[0.733,-0.716],[0.416,-0.966],[0,-1.1],[-0.417,-0.983],[-0.734,-0.716],[-1,-0.416],[-1.167,0],[-0.984,0.417],[-0.734,0.717],[-0.417,0.984],[0,1.134]],"v":[[5.525,-39.1],[7.25,-36.575],[9.825,-34.9],[13.05,-34.3],[16.25,-34.9],[18.85,-36.575],[20.575,-39.1],[21.2,-42.25],[20.575,-45.375],[18.85,-47.925],[16.25,-49.625],[13.05,-50.25],[9.825,-49.625],[7.25,-47.925],[5.525,-45.375],[4.9,-42.25]],"c":true},"ix":2},"nm":":","mn":"ADBE Vector Shape - Group","hd":false}],"nm":":","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"},{"ch":")","size":86.2156295776367,"style":"Heavy","w":27.75,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.583,-6.6],[2.933,-5.767],[0.05,-0.55],[-0.15,-0.434],[-0.317,-0.3],[-0.367,-0.234],[0,0],[-1.734,3.833],[-1.1,3.95],[-0.517,4.05],[0,4.234],[0.516,4.067],[1.1,3.934],[1.733,3.85],[2.433,3.767],[0,0],[0.316,-0.3],[0.15,-0.433],[-0.05,-0.566],[-0.4,-0.733],[-1.584,-6.6],[0,-6.766]],"o":[[-1.584,6.6],[-0.4,0.733],[-0.05,0.55],[0.15,0.433],[0.316,0.3],[0,0],[2.433,-3.8],[1.733,-3.834],[1.1,-3.95],[0.516,-4.05],[0,-4.2],[-0.517,-4.066],[-1.1,-3.933],[-1.734,-3.85],[0,0],[-0.367,0.234],[-0.317,0.3],[-0.15,0.434],[0.05,0.567],[2.933,5.734],[1.583,6.6],[0,6.767]],"v":[[10.125,-11.3],[3.35,7.25],[2.675,9.175],[2.825,10.65],[3.525,11.75],[4.55,12.55],[10.7,16.2],[16.95,4.75],[21.2,-6.925],[23.625,-18.925],[24.4,-31.35],[23.625,-43.75],[21.2,-55.75],[16.95,-67.425],[10.7,-78.85],[4.55,-75.25],[3.525,-74.45],[2.825,-73.35],[2.675,-71.85],[3.35,-69.9],[10.125,-51.4],[12.5,-31.35]],"c":true},"ix":2},"nm":")","mn":"ADBE Vector Shape - Group","hd":false}],"nm":")","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Lato"}]} \ No newline at end of file diff --git a/apps/client/lib/data/services/db/sqflite_api.dart b/apps/client/lib/data/services/db/sqflite_api.dart index 97224547..e76556a1 100644 --- a/apps/client/lib/data/services/db/sqflite_api.dart +++ b/apps/client/lib/data/services/db/sqflite_api.dart @@ -171,6 +171,25 @@ class SqfliteApi { await db.update('meeting', meeting, where: 'id = ?', whereArgs: [id]); } + /// 写任务状态。**tasktype 在 `meeting` 与 `meetingdetails` 两张表里各存了一份** + /// (列表页读前者、详情页读后者),所以只能从这一个入口写,两张表一次更新。 + /// + /// ⚠️ 别再直接 `editMeetingTitle(id, {'tasktype': x})`:那只写 `meeting`。 + /// 历史上 submitTask/refreshTask/readTask 都是这么写的,而 `meetingdetails` + /// 只在 `_queryTask` 的两个里程碑分支(>=3、==5/6)里才顺带更新一次 —— + /// 于是「等待转写中/转写中」这段 `meetingdetails.tasktype` 恒为 0, + /// 表现为**列表显示「正在转写…」,点进详情却没有等待态**(退出重进即复现, + /// 因为首次进入靠的是控制器里那次内存赋值,一离开就没了)。 + static Future setMeetingTaskType(int id, int tasktype) async { + final db = await DatabaseHelper().database; + await db.transaction((txn) async { + await txn.update('meeting', {'tasktype': tasktype}, + where: 'id = ?', whereArgs: [id]); + await txn.update('meetingdetails', {'tasktype': tasktype}, + where: 'meetingid = ?', whereArgs: [id]); + }); + } + // 删除商务会议助手 static Future deleteMeeting(id) async { final db = await DatabaseHelper().database; diff --git a/apps/client/lib/data/services/meeting/meeting_task_service.dart b/apps/client/lib/data/services/meeting/meeting_task_service.dart index 493156da..b1ef7680 100644 --- a/apps/client/lib/data/services/meeting/meeting_task_service.dart +++ b/apps/client/lib/data/services/meeting/meeting_task_service.dart @@ -121,10 +121,7 @@ class MeetingTaskService extends GetxService { 'id': id, 'tasktype': 1, }); - await SqfliteApi.editMeetingTitle( - id, - {'tasktype': 1}, - ); + await SqfliteApi.setMeetingTaskType(id, 1); updateListState.value++; _executeTask(); } @@ -141,20 +138,14 @@ class MeetingTaskService extends GetxService { 'id': id, 'tasktype': 3, }); - await SqfliteApi.editMeetingTitle( - id, - {'tasktype': 3}, - ); + await SqfliteApi.setMeetingTaskType(id, 3); updateListState.value++; _executeTask(); } Future readTask(int id) async { await Api.readRecordEchomeet({'id': id}); - await SqfliteApi.editMeetingTitle( - id, - {'tasktype': 6}, - ); + await SqfliteApi.setMeetingTaskType(id, 6); updateListState.value++; } @@ -254,14 +245,9 @@ class MeetingTaskService extends GetxService { } await SqfliteApi.deleteMeetingSpeaker(id); await SqfliteApi.insertMeetingSpeaker(speakerList); - await SqfliteApi.editMeeting( - id, - {'tasktype': newTasktype}, - ); if (id == meetingId) { List sqlSpeakerList = await SqfliteApi.getMeetingSpeaker(id); textList = List.from(sqlSpeakerList); - tasktype.value = newTasktype; } } // ⚠️ 判据用「正好是完成/已阅」而不是 >=5:失败态 SummarizFail=10001、 @@ -271,7 +257,6 @@ class MeetingTaskService extends GetxService { if (oldTasktype < 5 && (newTasktype == 5 || newTasktype == 6)) { // 总结完成 await SqfliteApi.editMeeting(id, { - 'tasktype': newTasktype, 'personnel': element['personnel'] ?? '', 'summary': element['summary'] ?? '', 'overview': element['overview'] ?? '', @@ -280,13 +265,17 @@ class MeetingTaskService extends GetxService { personnel = element['personnel'] ?? ''; summary = element['summary'] ?? ''; overview = element['overview'] ?? ''; - tasktype.value = newTasktype; } } - await SqfliteApi.editMeetingTitle( - id, - {'tasktype': newTasktype}, - ); + // 两张表一次落地。放在上面两个里程碑分支**之后**:分支里先把 + // speaker / summary 写好,最后这一下才把状态推进并通知 UI, + // 详情页的 ever(tasktype) 监听读到新状态时数据已经就位。 + await SqfliteApi.setMeetingTaskType(id, newTasktype); + // ⚠️ 这里原来也在两个分支里各写一次,于是 1→2(等待转写→转写中) + // 这一跳不通知任何人。状态本身要一直推,等待态才不会在中途变回旧值。 + if (id == meetingId) { + tasktype.value = newTasktype; + } taskData['tasktype'] = newTasktype; updateListState.value++; } diff --git a/apps/client/lib/modules/meeting/controllers/meeting_details_controller.dart b/apps/client/lib/modules/meeting/controllers/meeting_details_controller.dart index f9257708..93cdad10 100644 --- a/apps/client/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/apps/client/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -133,6 +133,12 @@ class MeetingDetailsController extends GetxController final data = await SqfliteApi.getMeetingDetails(id); meetingData.value = MeetingModel.fromJson(data); meetingDetails.value = MeetingDetailsModel.fromJson(data['details']); + // tasktype 在 meeting / meetingdetails 两张表里各存一份 + // (见 [SqfliteApi.setMeetingTaskType]),**以 meeting 表那份为准**: + // 它是历史上唯一每次状态变化都会写的,meetingdetails 那份在旧版本里 + // 只有里程碑才更新,存量记录可能还停在 0。不取这一份的话, + // 一条正在转写的记录点进来会既没有等待态、也没有内容,只剩空白。 + meetingDetails.value.tasktype = meetingData.value.tasktype; _everType = meetingDetails.value.tasktype + 1; _meetingTaskService.tasktype.value = meetingDetails.value.tasktype; if (meetingDetails.value.tasktype == 5) { diff --git a/apps/client/lib/modules/meeting/views/meeting_details_view.dart b/apps/client/lib/modules/meeting/views/meeting_details_view.dart index 58d5b336..1e794513 100644 --- a/apps/client/lib/modules/meeting/views/meeting_details_view.dart +++ b/apps/client/lib/modules/meeting/views/meeting_details_view.dart @@ -5,7 +5,6 @@ import 'package:common_utils/common_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:lottie/lottie.dart'; import '../../../core/theme/app_colors.dart'; import '../controllers/meeting_details_controller.dart'; @@ -16,6 +15,7 @@ import 'tabs/overview_tab.dart'; import 'bottomSheet/share_bottom_sheet.dart'; import 'tabs/speech_tab.dart'; import 'tabs/summary_tab.dart'; +import 'widgets/transcribing_placeholder.dart'; ///会议音频详情页面,提供会议音频播放、会议音频分享、会议音频更多操作 class MeetingDetailsView extends GetView { @@ -357,7 +357,7 @@ class MeetingDetailsView extends GetView { ? const SizedBox() : controller.meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 5 - ? _meetingWait( + ? TranscribingPlaceholder( controller.meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 3 @@ -368,13 +368,13 @@ class MeetingDetailsView extends GetView { Obx( () => controller.meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 3 - ? _meetingWait('transcribing'.tr) // 对应中文:正在转写... + ? TranscribingPlaceholder('transcribing'.tr) // 对应中文:正在转写... : const SpeechTab(), ), Obx( () => controller.meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 5 - ? _meetingWait( + ? TranscribingPlaceholder( controller.meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 3 ? 'transcribing'.tr // 对应中文:正在转写... @@ -385,7 +385,7 @@ class MeetingDetailsView extends GetView { ? const MindMapTab() : controller.meetingDetails.value.tasktype == 0 ? const SizedBox() - : _meetingWait(controller + : TranscribingPlaceholder(controller .meetingDetails.value.tasktype > 0 && controller.meetingDetails.value.tasktype < 3 @@ -400,33 +400,6 @@ class MeetingDetailsView extends GetView { ); } - Widget _meetingWait(String title) { - return Builder( - builder: (context) { - final isDarkMode = Theme.of(context).brightness == Brightness.dark; - return Stack( - alignment: Alignment.topCenter, - children: [ - Lottie.asset( - 'assets/lottie/meeting_wait.json', - ), - Positioned( - top: 320.w, - child: Text( - title, - style: TextStyle( - fontSize: 18.sp, - color: isDarkMode ? Colors.white : Colors.black87, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ); - }, - ); - } - Widget _soundWave(bool isDarkMode) { return Obx( () => Opacity( diff --git a/apps/client/lib/modules/meeting/views/widgets/transcribing_placeholder.dart b/apps/client/lib/modules/meeting/views/widgets/transcribing_placeholder.dart new file mode 100644 index 00000000..cd8a436f --- /dev/null +++ b/apps/client/lib/modules/meeting/views/widgets/transcribing_placeholder.dart @@ -0,0 +1,175 @@ +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import '../../../../core/theme/app_palette.dart'; + +/// 转写 / 分析进行中的等待态。 +/// +/// 取代原来的 `assets/lottie/meeting_wait.json`(一张「JOIN」对话气泡插画)—— +/// 那张图和本页在做的事(把音频变成文稿)没有任何关系,风格也与全站的 +/// 222° 冷蓝灰不搭。现在改成**自绘**:上面一排声波表示音频正在被读, +/// 下面几条带流光的骨架行预告即将生成的文稿形状,两者共用同一个 +/// [AnimationController]。 +/// +/// 自绘而不是再换一个 Lottie,是因为:① 不用为一个等待态再背一份 json 资源; +/// ② 颜色全部走 [AppPalette],明暗主题自动跟随,插画做不到; +/// ③ 四个 tab(概览/发言/全文/思维导图)共用同一个等待态,自绘好调。 +class TranscribingPlaceholder extends StatefulWidget { + const TranscribingPlaceholder(this.title, {super.key}); + + /// 状态文案,已含省略号(`transcribing` / `analyzing`),这里不要再补点。 + final String title; + + @override + State createState() => + _TranscribingPlaceholderState(); +} + +class _TranscribingPlaceholderState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _c; + + /// 骨架行的宽度占比,模拟一段自然段落的长短参差。 + static const List _lineWidths = [1.0, 0.94, 0.82, 0.62]; + + /// 声波柱数。奇数,让中间那根成为视觉锚点。 + static const int _barCount = 7; + + @override + void initState() { + super.initState(); + _c = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 1600), + )..repeat(); + } + + @override + void dispose() { + _c.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final bool isDark = Theme.of(context).brightness == Brightness.dark; + return Center( + child: Padding( + // 往上抬一点:等待态居中偏上比死居中更像「内容马上要从这里长出来」 + padding: EdgeInsets.only(bottom: 64.h, left: 24.w, right: 24.w), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _waveform(isDark), + SizedBox(height: 36.h), + _skeleton(isDark), + SizedBox(height: 32.h), + Text( + widget.title, + style: TextStyle( + fontSize: 15.sp, + fontWeight: FontWeight.w500, + color: AppPalette.textSecondary(isDark), + ), + ), + ], + ), + ), + ); + } + + /// 声波:每根柱子给一个固定相位差,整排看起来像一道行进的波而不是随机跳动。 + Widget _waveform(bool isDark) { + return SizedBox( + height: 40.h, + child: AnimatedBuilder( + animation: _c, + builder: (_, __) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: List.generate(_barCount, (int i) { + final double phase = i / _barCount; + // 0..1 的正弦,取绝对值让波谷也留一点高度,柱子不会缩到看不见 + final double v = + (math.sin((_c.value + phase) * 2 * math.pi) + 1) / 2; + return Padding( + padding: EdgeInsets.symmetric(horizontal: 3.w), + child: Container( + width: 4.w, + height: 10.h + 26.h * v, + decoration: BoxDecoration( + color: AppPalette.accent.withValues(alpha: 0.35 + 0.5 * v), + borderRadius: BorderRadius.circular(2.r), + ), + ), + ); + }), + ); + }, + ), + ); + } + + /// 骨架行 + 流光。流光用 [ShaderMask] 叠在实心色块上, + /// `srcATop` 保证亮带只出现在色块内部、不会溢到行与行之间的空隙。 + Widget _skeleton(bool isDark) { + final Color base = AppPalette.border(isDark); + final Color highlight = isDark + ? AppPalette.brand500.withValues(alpha: 0.85) + : Colors.white.withValues(alpha: 0.9); + + return AnimatedBuilder( + animation: _c, + builder: (_, __) { + return ShaderMask( + blendMode: BlendMode.srcATop, + shaderCallback: (Rect rect) => LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + highlight.withValues(alpha: 0), + highlight, + highlight.withValues(alpha: 0), + ], + stops: const [0.30, 0.50, 0.70], + transform: _SlideGradient(_c.value * 2 - 1), + ).createShader(rect), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (int i = 0; i < _lineWidths.length; i++) ...[ + if (i > 0) SizedBox(height: 14.h), + FractionallySizedBox( + widthFactor: _lineWidths[i], + child: Container( + height: 12.h, + decoration: BoxDecoration( + color: base, + borderRadius: BorderRadius.circular(6.r), + ), + ), + ), + ], + ], + ), + ); + }, + ); + } +} + +/// 把渐变横向平移 [dx](以自身宽度为单位)。 +/// +/// Flutter 只内置了 [GradientRotation],要让亮带扫过去只能自己写一个。 +class _SlideGradient extends GradientTransform { + const _SlideGradient(this.dx); + + final double dx; + + @override + Matrix4 transform(Rect bounds, {TextDirection? textDirection}) => + Matrix4.translationValues(bounds.width * dx, 0, 0); +}