Compare commits
No commits in common. "399374530e8d677f0029bd44e9b6f7992ea64784" and "898794e1c32335370340eb8b3883cb1c1dccf256" have entirely different histories.
399374530e
...
898794e1c3
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -1,4 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="32" height="32" rx="16" fill="#007EA7"/>
|
||||
<path d="M16 19C14.3125 19 13 17.6562 13 16V11C13 9.34375 14.3125 8 16 8C17.6562 8 19 9.34375 19 11V16C19 17.6875 17.6562 19 16 19ZM20.75 14C21.1562 14 21.5 14.3438 21.5 14.75V16C21.5 18.7812 19.4062 21.0938 16.75 21.4688V22.5H18C18.5625 22.5 19 23 18.9688 23.5625C18.9688 23.8125 18.75 24 18.5 24H13.5C13.2188 24 13 23.8125 13 23.5625C12.9688 23 13.4062 22.5 14 22.5H15.25V21.4062C12.4688 21.0312 10.5 18.5312 10.5 15.75V14.75C10.5 14.3438 10.8125 14 11.25 14C11.6562 14 12 14.3438 12 14.75V15.8438C12 17.9375 13.6562 19.875 15.7188 20C18.0625 20.1562 20 18.3125 20 16V14.75C20 14.3438 20.3125 14 20.75 14Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 781 B |
|
|
@ -1,3 +0,0 @@
|
|||
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.698 1.95539C24.8614 1.86748 25.053 1.84803 25.2307 1.90132C25.4084 1.95461 25.5577 2.07628 25.6458 2.23959C26.7434 4.27753 27.3165 6.55666 27.3132 8.87139C27.3169 11.186 26.7443 13.4651 25.6472 15.5032C25.5592 15.6667 25.4098 15.7887 25.232 15.8421C25.0541 15.8955 24.8623 15.8761 24.6987 15.7881C24.5351 15.7001 24.4132 15.5507 24.3598 15.3728C24.3064 15.195 24.3258 15.0031 24.4138 14.8396C25.4014 13.0055 25.9167 10.9544 25.9132 8.87139C25.9167 6.78835 25.4014 4.73724 24.4138 2.90319C24.3259 2.7398 24.3064 2.54819 24.3597 2.37047C24.413 2.19275 24.5347 2.04345 24.698 1.95539ZM21.443 4.71899C21.5278 4.68359 21.6188 4.66525 21.7108 4.66502C21.8027 4.66479 21.8938 4.68267 21.9788 4.71764C22.0638 4.75261 22.1411 4.80399 22.2063 4.86884C22.2715 4.93369 22.3232 5.01074 22.3586 5.09559C22.8573 6.2919 23.1138 7.57527 23.1132 8.87139C23.1138 10.1675 22.8573 11.4509 22.3586 12.6472C22.3259 12.7357 22.2756 12.8166 22.2107 12.8852C22.1459 12.9537 22.0679 13.0085 21.9814 13.0461C21.8949 13.0838 21.8016 13.1035 21.7073 13.1042C21.613 13.1049 21.5194 13.0866 21.4324 13.0502C21.3453 13.0138 21.2665 12.9603 21.2007 12.8927C21.1348 12.8251 21.0833 12.7449 21.0493 12.6569C21.0152 12.5689 20.9993 12.475 21.0025 12.3807C21.0057 12.2864 21.0279 12.1937 21.0678 12.1082C21.4949 11.0826 21.7142 9.98239 21.7132 8.87139C21.7132 7.72339 21.4836 6.63139 21.0678 5.63459C20.9962 5.46341 20.9955 5.27082 21.0659 5.09913C21.1362 4.92745 21.2719 4.79072 21.443 4.71899ZM7.7132 8.87139C7.7132 7.38618 8.3032 5.96179 9.3534 4.91159C10.4036 3.86139 11.828 3.27139 13.3132 3.27139C14.7984 3.27139 16.2228 3.86139 17.273 4.91159C18.3232 5.96179 18.9132 7.38618 18.9132 8.87139C18.9132 10.3566 18.3232 11.781 17.273 12.8312C16.2228 13.8814 14.7984 14.4714 13.3132 14.4714C11.828 14.4714 10.4036 13.8814 9.3534 12.8312C8.3032 11.781 7.7132 10.3566 7.7132 8.87139ZM3.5132 18.6714C3.5132 17.1132 4.7774 15.8714 6.3258 15.8714H20.3132C21.0558 15.8714 21.768 16.1664 22.2931 16.6915C22.8182 17.2166 23.1132 17.9288 23.1132 18.6714C23.1132 21.0388 21.947 22.8238 20.1242 23.9872C18.3294 25.131 15.9102 25.6714 13.3132 25.6714C10.7162 25.6714 8.297 25.131 6.5022 23.9872C4.6794 22.8252 3.5132 21.0374 3.5132 18.6714Z" fill="#195D80"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
|
@ -1,10 +0,0 @@
|
|||
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_8526_27248)">
|
||||
<path d="M24.5039 1.01508C24.7073 0.903585 24.9467 0.877453 25.1694 0.94243C25.3921 1.00741 25.5799 1.15817 25.6915 1.36158C26.9124 3.59232 27.5504 6.09512 27.5465 8.63808C27.5465 11.2724 26.8745 13.7527 25.6915 15.9134C25.5801 16.117 25.3924 16.268 25.1697 16.3332C24.947 16.3984 24.7075 16.3725 24.5039 16.2611C24.3003 16.1497 24.1493 15.962 24.0841 15.7393C24.0189 15.5165 24.0448 15.277 24.1562 15.0734C25.2364 13.1007 25.801 10.8872 25.7977 8.63808C25.7977 6.30475 25.2027 4.11141 24.1562 2.20275C24.101 2.10194 24.0663 1.99125 24.0539 1.877C24.0415 1.76276 24.0517 1.64719 24.084 1.5369C24.1163 1.42662 24.17 1.32377 24.242 1.23424C24.3141 1.1447 24.403 1.07023 24.5039 1.01508ZM20.8849 4.04141C21.0981 3.94986 21.3389 3.94673 21.5544 4.03271C21.7699 4.1187 21.9424 4.28675 22.034 4.49991C22.5938 5.80769 22.8819 7.21556 22.881 8.63808C22.8816 10.0598 22.5935 11.4669 22.034 12.7739C21.991 12.8827 21.9266 12.9818 21.8446 13.0653C21.7626 13.1488 21.6647 13.2149 21.5567 13.2599C21.4486 13.3049 21.3327 13.3277 21.2157 13.3271C21.0987 13.3265 20.983 13.3024 20.8755 13.2563C20.7679 13.2102 20.6707 13.143 20.5896 13.0586C20.5085 12.9743 20.4452 12.8745 20.4033 12.7652C20.3614 12.656 20.3419 12.5394 20.3458 12.4225C20.3498 12.3056 20.3772 12.1906 20.4264 12.0844C20.8917 10.9951 21.1311 9.82264 21.1299 8.63808C21.1307 7.45345 20.891 6.28098 20.4252 5.19175C20.3336 4.97855 20.3305 4.73773 20.4165 4.52223C20.5025 4.30672 20.6705 4.1342 20.8837 4.04258M21.7155 19.4286C21.7155 18.7328 21.4393 18.0655 20.9475 17.5732C20.4557 17.081 19.7886 16.8042 19.0929 16.8036H5.67386C4.97767 16.8036 4.30999 17.0801 3.8177 17.5724C3.32542 18.0647 3.04886 18.7324 3.04886 19.4286V20.1017C3.04886 21.1436 3.42219 22.1504 4.09886 22.9426C5.92469 25.0834 8.70953 26.1392 12.3787 26.1392C16.0479 26.1392 18.8339 25.0834 20.6644 22.9437C21.3426 22.1513 21.7154 21.1425 21.7155 20.0994V19.4286ZM5.67386 18.5536H19.0929C19.3245 18.5542 19.5465 18.6467 19.7101 18.8107C19.8737 18.9747 19.9655 19.1969 19.9655 19.4286V20.0994C19.9657 20.7253 19.7423 21.3306 19.3355 21.8062C17.869 23.5189 15.5742 24.3892 12.3787 24.3892C9.18319 24.3892 6.89069 23.5189 5.42886 21.8062C5.02288 21.3315 4.79951 20.7276 4.79886 20.1029V19.4286C4.79886 19.1965 4.89105 18.974 5.05514 18.8099C5.21923 18.6458 5.44179 18.5536 5.67386 18.5536ZM18.2132 8.64391C18.2132 7.09682 17.5986 5.61309 16.5046 4.51913C15.4107 3.42516 13.927 2.81058 12.3799 2.81058C10.8328 2.81058 9.34903 3.42516 8.25507 4.51913C7.16111 5.61309 6.54653 7.09682 6.54653 8.64391C6.54653 10.191 7.16111 11.6747 8.25507 12.7687C9.34903 13.8627 10.8328 14.4772 12.3799 14.4772C13.927 14.4772 15.4107 13.8627 16.5046 12.7687C17.5986 11.6747 18.2132 10.191 18.2132 8.64391ZM8.29653 8.64391C8.29653 8.10768 8.40214 7.5767 8.60735 7.08129C8.81256 6.58588 9.11333 6.13573 9.49251 5.75656C9.87168 5.37739 10.3218 5.07661 10.8172 4.87141C11.3126 4.6662 11.8436 4.56058 12.3799 4.56058C12.9161 4.56058 13.4471 4.6662 13.9425 4.87141C14.4379 5.07661 14.888 5.37739 15.2672 5.75656C15.6464 6.13573 15.9472 6.58588 16.1524 7.08129C16.3576 7.5767 16.4632 8.10768 16.4632 8.64391C16.4632 9.72688 16.033 10.7655 15.2672 11.5313C14.5014 12.297 13.4628 12.7272 12.3799 12.7272C11.2969 12.7272 10.2583 12.297 9.49251 11.5313C8.72673 10.7655 8.29653 9.72688 8.29653 8.64391Z" fill="#007EA7"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8526_27248">
|
||||
<rect width="28" height="28" fill="white" transform="translate(0.713196 0.471436)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
|
|
@ -1,4 +0,0 @@
|
|||
<svg width="53" height="52" viewBox="0 0 53 52" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.922806" y="0.642334" width="51.1544" height="51.1544" rx="25.5772" fill="#195D80"/>
|
||||
<path d="M33.3141 40.2195C34.8785 40.0682 36.44 39.889 37.9978 39.6817C38.5035 39.6162 38.9728 39.3862 39.332 39.0281C39.6912 38.6699 39.9198 38.2038 39.9819 37.7031C40.1678 36.2254 40.3513 34.688 40.5 33.1138M19.6882 12.2195C18.1238 12.3707 16.5623 12.55 15.0045 12.7572C14.4987 12.8222 14.0291 13.0516 13.6696 13.4094C13.31 13.7671 13.0808 14.2329 13.0181 14.7336C12.8218 16.2614 12.6491 17.7922 12.5 19.3252M33.3141 12.2195C34.9172 12.3712 36.4854 12.5596 37.9978 12.7572C38.5032 12.8227 38.9722 13.0523 39.3314 13.41C39.6905 13.7677 39.9193 14.2333 39.9819 14.7336C40.1678 16.2136 40.3513 17.751 40.5 19.3252M19.6882 40.2195C18.1239 40.0668 16.5625 39.8875 15.0045 39.6817C14.4984 39.6167 14.0285 39.3869 13.6689 39.0287C13.3093 38.6705 13.0803 38.2041 13.0181 37.7031C12.8219 36.176 12.6491 34.646 12.5 33.1138M26.5 21.9956V19.0425M26.5 21.9956C28.3284 21.9956 30.2265 21.9956 31.9109 22.2116C32.6172 22.2988 33.2753 22.6117 33.7853 23.1029C34.2953 23.594 34.6291 24.2365 34.736 24.9325C34.873 25.8587 34.873 26.7986 34.873 28.3981C34.873 29.9999 34.873 30.9398 34.7337 31.8636C34.627 32.559 34.2938 33.2009 33.7848 33.692C33.2758 34.1831 32.6187 34.4965 31.9132 34.5846C30.2288 34.8029 28.3307 34.8029 26.5023 34.8029C24.6762 34.8029 22.7781 34.8029 21.0938 34.5846C20.3875 34.4974 19.7293 34.1844 19.2193 33.6933C18.7094 33.2021 18.3756 32.5597 18.2687 31.8636C18.1316 30.9398 18.1316 29.9999 18.1316 28.3981C18.1316 26.7963 18.1316 25.8587 18.2687 24.9325C18.3756 24.2365 18.7094 23.594 19.2193 23.1029C19.7293 22.6117 20.3875 22.2988 21.0938 22.2116C22.7781 21.9956 24.6739 21.9956 26.5 21.9956ZM29.5133 28.8439V27.9522M23.4798 28.8439V27.9522M26.5 19.0127C27.9311 19.0127 28.7373 18.2152 28.7373 16.7996C28.7373 15.384 27.9311 14.5911 26.5 14.5911C25.0689 14.5911 24.265 15.3886 24.265 16.8019C24.265 18.2152 25.0712 19.0127 26.5 19.0127Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,11 +0,0 @@
|
|||
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_8526_27623)">
|
||||
<path d="M25.5347 6.59644H8.67511C6.81573 6.59644 5.28448 8.10089 5.28448 9.95042V23.3675C5.28448 25.217 6.81573 26.7214 8.67511 26.7214H25.5189C27.3782 26.7214 28.9095 25.2897 28.9095 23.4402V9.95042C28.9095 8.10089 27.3957 6.59644 25.5347 6.59644ZM21.3156 9.95097C21.8125 9.95399 22.2973 10.1041 22.709 10.3823C23.1207 10.6606 23.4407 11.0545 23.6288 11.5145C23.8168 11.9744 23.8645 12.4797 23.7657 12.9667C23.6669 13.4537 23.4261 13.9005 23.0737 14.2507C22.7213 14.601 22.273 14.8391 21.7854 14.9349C21.2979 15.0308 20.7929 14.9801 20.3341 14.7892C19.8753 14.5984 19.4833 14.2759 19.2076 13.8626C18.9318 13.4492 18.7846 12.9635 18.7846 12.4666C18.7872 11.7975 19.0552 11.1568 19.5297 10.6851C20.0042 10.2133 20.6465 9.94911 21.3156 9.95042V9.95097ZM8.65269 25.0447C7.723 25.0447 7.01972 24.2928 7.01972 23.368V19.8226L11.9668 15.4044C12.4504 14.979 13.0773 14.7528 13.7211 14.7713C14.365 14.7899 14.9778 15.0519 15.4361 15.5045L18.8617 18.9011L12.6821 25.0442L8.65269 25.0447ZM27.1595 23.3675C27.1594 23.5879 27.1159 23.8061 27.0314 24.0097C26.947 24.2132 26.8232 24.3982 26.6673 24.5539C26.5113 24.7096 26.3262 24.833 26.1224 24.9172C25.9187 25.0013 25.7004 25.0445 25.48 25.0442H15.0735L21.4764 18.6824C21.9307 18.2991 22.5056 18.0881 23.1001 18.0865C23.6945 18.0849 24.2706 18.2928 24.727 18.6736L27.1595 20.7381V23.3675Z" fill="#195D80"/>
|
||||
<path d="M21.9095 2.22144H4.40948C3.48123 2.22144 2.59099 2.59018 1.93461 3.24656C1.27823 3.90294 0.909485 4.79318 0.909485 5.72144L0.909485 19.7214C0.910125 20.4974 1.16818 21.2512 1.64321 21.8648C2.11824 22.4784 2.78341 22.9171 3.53448 23.1121V8.78394C3.53448 7.73965 3.94933 6.73813 4.68775 5.9997C5.42618 5.26128 6.42769 4.84644 7.47198 4.84644H25.3001C25.1051 4.09536 24.6665 3.43019 24.0529 2.95516C23.4393 2.48013 22.6855 2.22208 21.9095 2.22144Z" fill="#195D80"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8526_27623">
|
||||
<rect width="28" height="28" fill="white" transform="translate(0.909485 0.471436)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,13 +0,0 @@
|
|||
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_8526_27252)">
|
||||
<path d="M24.5345 6.59644V5.72144C24.5325 5.02586 24.2553 4.35936 23.7634 3.86751C23.2716 3.37567 22.6051 3.09846 21.9095 3.09644H4.40948C3.71391 3.09846 3.04741 3.37567 2.55556 3.86751C2.06372 4.35936 1.7865 5.02586 1.78448 5.72144V19.7214C1.7865 20.417 2.06372 21.0835 2.55556 21.5754C3.04741 22.0672 3.71391 22.3444 4.40948 22.3464H5.28448" stroke="#007EA7" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
<path d="M25.5194 7.47144H8.67456C7.28552 7.47144 6.15948 8.59747 6.15948 9.98651V23.3314C6.15948 24.7204 7.28552 25.8464 8.67456 25.8464H25.5194C26.9084 25.8464 28.0345 24.7204 28.0345 23.3314V9.98651C28.0345 8.59747 26.9084 7.47144 25.5194 7.47144Z" stroke="#007EA7" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
<path d="M21.3036 14.1537C22.2329 14.1537 22.9863 13.4057 22.9863 12.483C22.9863 11.5603 22.2329 10.8123 21.3036 10.8123C20.3742 10.8123 19.6208 11.5603 19.6208 12.483C19.6208 13.4057 20.3742 14.1537 21.3036 14.1537Z" stroke="#007EA7" stroke-width="1.5" stroke-miterlimit="10"/>
|
||||
<path d="M19.6208 20.8245L14.8548 16.1001C14.5501 15.799 14.1426 15.6248 13.7145 15.6125C13.2864 15.6002 12.8695 15.7508 12.5481 16.0339L6.15948 21.6705M15.4143 25.8465L21.8996 19.4081C22.1981 19.1138 22.595 18.9404 23.0137 18.9216C23.4324 18.9027 23.8433 19.0396 24.167 19.3058L28.0345 22.5056" stroke="#007EA7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8526_27252">
|
||||
<rect width="28" height="28" fill="white" transform="translate(0.909485 0.471436)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,3 +0,0 @@
|
|||
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.2868 2.22144C11.864 2.22144 9.49557 2.93989 7.48107 4.28593C5.46656 5.63198 3.89645 7.54517 2.96928 9.78356C2.0421 12.022 1.79951 14.485 2.27218 16.8613C2.74485 19.2376 3.91155 21.4203 5.62474 23.1335C7.33794 24.8467 9.52068 26.0134 11.8969 26.4861C14.2732 26.9587 16.7363 26.7161 18.9747 25.789C21.2131 24.8618 23.1263 23.2917 24.4723 21.2772C25.8183 19.2627 26.5368 16.8943 26.5368 14.4714C26.5331 11.2237 25.2413 8.10999 22.9448 5.81347C20.6482 3.51695 17.5346 2.22514 14.2868 2.22144ZM3.8043 14.8162L4.97505 15.2064L6.4118 17.3616V18.4842C6.41185 18.7162 6.50407 18.9388 6.66818 19.1028L9.0368 21.4714V23.5513C7.49529 22.6587 6.20621 21.3886 5.29085 19.8605C4.37548 18.3323 3.86392 16.5965 3.8043 14.8162ZM14.2868 24.9714C13.5298 24.9697 12.7753 24.8861 12.0363 24.7221L12.5368 23.2214L14.1162 19.2734C14.1688 19.1416 14.1886 18.999 14.1738 18.8578C14.159 18.7167 14.1101 18.5812 14.0313 18.4632L12.7967 16.6108C12.7167 16.491 12.6085 16.3928 12.4815 16.3249C12.3545 16.2569 12.2127 16.2214 12.0687 16.2214H7.75493L6.66293 14.5826L8.52405 12.7214H9.9118V14.4714H11.6618V12.0792L15.0463 6.15544L13.5273 5.28744L12.7792 6.59644H10.3799L9.43055 5.17106C10.7061 4.49787 12.108 4.09797 13.5468 3.99688C14.9856 3.89579 16.4296 4.09573 17.7868 4.58394V7.47144C17.7868 7.7035 17.879 7.92606 18.0431 8.09015C18.2072 8.25425 18.4297 8.34644 18.6618 8.34644H19.9437C20.0877 8.34646 20.2295 8.31093 20.3565 8.24301C20.4835 8.17508 20.5917 8.07686 20.6717 7.95706L21.4391 6.80556C22.439 7.73718 23.2474 8.85504 23.819 10.0964H20.2543C20.0521 10.0966 19.8562 10.1667 19.6998 10.295C19.5435 10.4232 19.4364 10.6017 19.3968 10.7999L18.7642 14.7112C18.7342 14.8953 18.7639 15.0842 18.8489 15.2503C18.9339 15.4164 19.0698 15.5509 19.2367 15.6343L22.1618 17.0964L22.7612 20.6454C21.79 21.9838 20.5159 23.0735 19.0431 23.8253C17.5702 24.5772 15.9404 24.9699 14.2868 24.9714Z" fill="#195D80"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
|
@ -1,11 +0,0 @@
|
|||
<svg width="30" height="31" viewBox="0 0 30 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_8526_27495)">
|
||||
<path d="M21.5298 13.0747L22.3405 15.4715H24.4092L20.9389 6.15271H18.5459L15.0905 15.4715H17.2655L18.0762 13.0747H21.5298ZM18.4844 11.703L19.7499 7.93446H19.8412L21.1067 11.703H18.4844Z" fill="#195D80"/>
|
||||
<path d="M30.0005 4.2889C30.0005 3.30031 29.6078 2.3522 28.9087 1.65316C28.2097 0.954119 27.2616 0.561401 26.273 0.561401L13.2267 0.561401C12.2382 0.561401 11.2901 0.954119 10.591 1.65316C9.89197 2.3522 9.49925 3.30031 9.49925 4.2889V9.88015H3.908C2.9194 9.88015 1.9713 10.2729 1.27226 10.9719C0.573219 11.671 0.1805 12.6191 0.1805 13.6077V26.6539C0.1805 27.6425 0.573219 28.5906 1.27226 29.2896C1.9713 29.9887 2.9194 30.3814 3.908 30.3814H16.9543C17.9428 30.3814 18.8909 29.9887 19.59 29.2896C20.289 28.5906 20.6817 27.6425 20.6817 26.6539V21.0627H26.273C27.2616 21.0627 28.2097 20.6699 28.9087 19.9709C29.6078 19.2718 30.0005 18.3237 30.0005 17.3352V4.2889ZM26.273 2.42515C26.7673 2.42515 27.2413 2.62151 27.5909 2.97103C27.9404 3.32055 28.1367 3.7946 28.1367 4.2889V17.3352C28.1367 17.8294 27.9404 18.3035 27.5909 18.653C27.2413 19.0025 26.7673 19.1989 26.273 19.1989H13.2267C12.7325 19.1989 12.2584 19.0025 11.9089 18.653C11.5594 18.3035 11.363 17.8294 11.363 17.3352V4.2889C11.363 3.7946 11.5594 3.32055 11.9089 2.97103C12.2584 2.62151 12.7325 2.42515 13.2267 2.42515H26.273ZM12.9696 21.0533C12.6105 21.6137 12.2191 22.1393 11.7954 22.6301C13.1895 23.7017 14.9134 24.4957 16.9543 25.038C16.6225 25.4425 16.1137 26.2215 15.9199 26.6539C13.8232 25.9848 12.0433 25.0809 10.5411 23.8695C9.09295 25.1089 7.30002 26.0407 5.0803 26.6129C4.83242 26.1395 4.30871 25.3586 3.908 24.9542C6.00472 24.4826 7.74173 23.6607 9.16377 22.5611C7.89456 21.1689 6.88627 19.4841 6.14264 17.4227H3.908V15.4714H9.49925V17.4227H8.07348C8.66615 18.9958 9.45266 20.3041 10.4442 21.3925C10.7182 21.1009 10.9764 20.7948 11.2176 20.4756C11.744 20.8119 12.3464 21.0106 12.9696 21.0533Z" fill="#195D80"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8526_27495">
|
||||
<rect width="29.82" height="29.82" fill="white" transform="matrix(-1 0 0 1 30.0005 0.561401)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,13 +0,0 @@
|
|||
<svg width="30" height="31" viewBox="0 0 30 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_8526_27232)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.2912 16.8916V7.30648C29.2912 6.4591 28.9546 5.64643 28.3554 5.04725C27.7562 4.44807 26.9435 4.11145 26.0962 4.11145H16.5111C15.6637 4.11145 14.8511 4.44807 14.2519 5.04725C13.6527 5.64643 13.3161 6.4591 13.3161 7.30648V16.8916C13.3161 17.7389 13.6527 18.5516 14.2519 19.1508C14.8511 19.75 15.6637 20.0866 16.5111 20.0866H26.0962C26.9435 20.0866 27.7562 19.75 28.3554 19.1508C28.9546 18.5516 29.2912 17.7389 29.2912 16.8916Z" stroke="#007EA7" stroke-width="1.81052" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.1211 13.7012H6.92606C6.07868 13.7012 5.26602 14.0378 4.66684 14.637C4.06765 15.2362 3.73104 16.0489 3.73104 16.8963V26.4813C3.73104 27.3287 4.06765 28.1414 4.66684 28.7406C5.26602 29.3397 6.07868 29.6764 6.92606 29.6764H6.93085L16.5159 29.6604C17.3624 29.6591 18.1739 29.3219 18.772 28.7229C19.3702 28.1238 19.7061 27.3119 19.7061 26.4654V23.2815M11.7186 20.0913H6.92606" stroke="#007EA7" stroke-width="1.81052" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.1149 22.483L12.5173 24.0805C11.9848 24.613 10.6536 25.4117 8.52357 26.4768" stroke="#007EA7" stroke-width="1.81052" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.52357 20.0914C9.05714 21.9551 9.85589 23.2858 10.9198 24.0835C12.5173 25.2785 13.3161 25.6779 14.9136 26.4766M16.5111 16.8915L21.3036 7.30646L26.0962 16.8915M24.4987 13.6965H18.1086" stroke="#007EA7" stroke-width="1.81052" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_8526_27232">
|
||||
<rect width="29.8203" height="29.8203" fill="white" transform="translate(0.180359 0.561279)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,3 +0,0 @@
|
|||
<svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.125 8.5C17.125 9.04688 16.6953 9.4375 16.1875 9.4375H9.9375V15.6875C9.9375 16.2344 9.50781 16.6641 9 16.6641C8.45312 16.6641 8.0625 16.2344 8.0625 15.6875V9.4375H1.8125C1.26562 9.4375 0.875 9.04688 0.875 8.53906C0.875 7.99219 1.26562 7.5625 1.8125 7.5625H8.0625V1.3125C8.0625 0.804688 8.45312 0.414062 9 0.414062C9.50781 0.414062 9.9375 0.804688 9.9375 1.3125V7.5625H16.1875C16.6953 7.5625 17.125 7.99219 17.125 8.5Z" fill="#007EA7"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 551 B |
|
|
@ -191,9 +191,6 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
|||
ChangeNotifierProvider<BotAssistantsState>(
|
||||
create: (context) => BotAssistantsState(),
|
||||
),
|
||||
// ChangeNotifierProvider<StoryViewerState>(
|
||||
// create: (context) => StoryViewerState(),
|
||||
// ),
|
||||
],
|
||||
child: Consumer<ThemeProvider>(
|
||||
builder: (context, themeProvider, child) => Container(
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum MediaType { image, video, gif }
|
||||
|
||||
// Represents a single story item (image, gif, or video)
|
||||
class StoryItem {
|
||||
final int id;
|
||||
final String url;
|
||||
final MediaType media;
|
||||
final Duration duration;
|
||||
final ValueNotifier<bool> isViewed;
|
||||
|
||||
StoryItem({
|
||||
required this.id,
|
||||
required this.url,
|
||||
required this.media,
|
||||
required this.duration,
|
||||
bool viewed = false,
|
||||
}) : isViewed = ValueNotifier(viewed);
|
||||
|
||||
factory StoryItem.fromJson(Map<String, dynamic> json) {
|
||||
MediaType mediaType;
|
||||
switch (json['mediaType']) {
|
||||
case 'VIDEO':
|
||||
mediaType = MediaType.video;
|
||||
break;
|
||||
case 'GIF':
|
||||
mediaType = MediaType.gif;
|
||||
break;
|
||||
case 'IMAGE':
|
||||
default:
|
||||
mediaType = MediaType.image;
|
||||
break;
|
||||
}
|
||||
|
||||
return StoryItem(
|
||||
id: json['id'],
|
||||
url: json['mediaUrl'],
|
||||
media: mediaType,
|
||||
// API doesn't provide duration for images/gifs, so we use a default.
|
||||
// For videos, the player controller will determine the duration.
|
||||
duration: const Duration(seconds: 10),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
final String name;
|
||||
final String profileImageUrl;
|
||||
final String createdAt;
|
||||
|
||||
const User({
|
||||
required this.name,
|
||||
required this.profileImageUrl,
|
||||
required this.createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
// This class will wrap the API response and fit it into the UI's expected structure.
|
||||
class UserStories {
|
||||
final int id; // The main story ID from the API
|
||||
final User user;
|
||||
final List<StoryItem> stories;
|
||||
|
||||
UserStories({
|
||||
required this.id,
|
||||
required this.user,
|
||||
required this.stories,
|
||||
});
|
||||
|
||||
factory UserStories.fromApiJson(Map<String, dynamic> json) {
|
||||
final List<dynamic> items = json['items'] ?? [];
|
||||
final List<dynamic> completedIds = json['completedStoryItemIds'] ?? [];
|
||||
|
||||
return UserStories(
|
||||
id: json['id'],
|
||||
user: User(
|
||||
name: json['title'], // Using title directly from the API
|
||||
profileImageUrl:
|
||||
_mapCategoryToIcon(json['category']), // Mapping category to an icon
|
||||
createdAt: json['createdAt'],
|
||||
),
|
||||
stories: items.map((item) {
|
||||
final storyItem = StoryItem.fromJson(item);
|
||||
// Check if this story item has been viewed.
|
||||
if (completedIds.contains(storyItem.id)) {
|
||||
storyItem.isViewed.value = true;
|
||||
}
|
||||
return storyItem;
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String _mapCategoryToIcon(String category) {
|
||||
switch (category) {
|
||||
case 'MACRO_TRENDS':
|
||||
return 'lib/assets/icons/MACRO_TRENDS_N.png';
|
||||
case 'INDUSTRY_ENVIRONMENT':
|
||||
return 'lib/assets/icons/INDUSTRY_ENVIRONMENT_N.png';
|
||||
case 'COMPETITION_ENVIRONMENT':
|
||||
return Assets.startup;
|
||||
case 'OPPORTUNITIES':
|
||||
return Assets.hugeideas;
|
||||
case 'THREATS':
|
||||
return Assets.risk;
|
||||
case 'TECHNOLOGY':
|
||||
return Assets.tech;
|
||||
case 'STARTUPS':
|
||||
return Assets.startup;
|
||||
case 'CONCEPTS':
|
||||
return 'lib/assets/icons/CONCEPTS_N.png';
|
||||
case 'MACRO_ENVIRONMENT':
|
||||
return 'lib/assets/icons/MACRO_ENVIRONMENT_N.png';
|
||||
case 'MODERN_INVESTMENTS':
|
||||
return 'lib/assets/icons/MODERN_INVESTMENTS_N.png';
|
||||
default:
|
||||
return Assets.stats;
|
||||
}
|
||||
}
|
||||
|
|
@ -67,8 +67,6 @@ class UserProvider extends CoreProvier {
|
|||
|
||||
await _registerFirebaseToken();
|
||||
|
||||
notifyListeners();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// ignore_for_file: unused_import, deprecated_member_use
|
||||
|
||||
import 'package:didvan/models/ai/ai_chat_args.dart';
|
||||
import 'package:didvan/models/story_model.dart';
|
||||
import 'package:didvan/views/ai/ai_chat_page.dart';
|
||||
import 'package:didvan/views/ai/ai_chat_state.dart';
|
||||
import 'package:didvan/views/ai_section/ai_section_page.dart';
|
||||
import 'package:didvan/views/ai/bot_assistants_page.dart';
|
||||
import 'package:didvan/views/ai/create_bot_assistants_page.dart';
|
||||
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
|
||||
import 'package:didvan/views/ai/history_ai_chat_page.dart';
|
||||
import 'package:didvan/views/ai/history_ai_chat_state.dart';
|
||||
import 'package:didvan/views/ai/info_page.dart';
|
||||
import 'package:didvan/views/ai/info_state.dart';
|
||||
import 'package:didvan/views/authentication/authentication.dart';
|
||||
|
|
@ -24,6 +25,7 @@ import 'package:didvan/views/home/infography/infography_screen.dart';
|
|||
import 'package:didvan/views/home/infography/infography_screen_state.dart';
|
||||
import 'package:didvan/views/home/main/main_page_state.dart';
|
||||
import 'package:didvan/views/home/home_state.dart';
|
||||
import 'package:didvan/views/home/new_statistic/new_statistic.dart';
|
||||
import 'package:didvan/views/home/new_statistic/new_statistics_state.dart';
|
||||
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_screen.dart';
|
||||
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_state.dart';
|
||||
|
|
@ -59,8 +61,6 @@ import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
|
|||
if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart';
|
||||
import 'package:didvan/views/splash/splash.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/story_viewer/story_viewer_page.dart';
|
||||
|
||||
import 'package:didvan/views/webview/web_view.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -80,12 +80,7 @@ class RouteGenerator {
|
|||
return _createRoute(
|
||||
const Splash(),
|
||||
);
|
||||
case Routes.aiSection:
|
||||
return _createRoute(
|
||||
const AiSectionPage(),
|
||||
);
|
||||
case Routes.notificationTime:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<NotificationTimeState>(
|
||||
create: (context) => NotificationTimeState(),
|
||||
|
|
@ -93,12 +88,8 @@ class RouteGenerator {
|
|||
pageData: settings.arguments as Map<String, dynamic>,
|
||||
)),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.favouritesStep:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||
create: (context) => CustomizeCategoryState(),
|
||||
|
|
@ -106,12 +97,13 @@ class RouteGenerator {
|
|||
pageData: settings.arguments as Map<String, dynamic>,
|
||||
)),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
// case Routes.newStatic:
|
||||
// return _createRoute(ChangeNotifierProvider<NewStatisticState>(
|
||||
// create: (context) => NewStatisticState(),
|
||||
// child: const NewStatistic()));
|
||||
|
||||
case Routes.notificationStatusStep:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||
create: (context) => CustomizeCategoryState(),
|
||||
|
|
@ -119,29 +111,14 @@ class RouteGenerator {
|
|||
pageData: settings.arguments as Map<String, dynamic>,
|
||||
)),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
case Routes.authenticaion:
|
||||
bool isResetPassword = false;
|
||||
if (settings.arguments is bool) {
|
||||
isResetPassword = settings.arguments as bool;
|
||||
} else if (settings.arguments != null) {
|
||||
print('Warning: Invalid argument type for isResetPassword. Expected bool, got ${settings.arguments.runtimeType}. Using default false.');
|
||||
}
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<AuthenticationState>(
|
||||
create: (context) => AuthenticationState(),
|
||||
child: Authentication(isResetPassword: isResetPassword),
|
||||
child: Authentication(isResetPassword: settings.arguments as bool),
|
||||
),
|
||||
);
|
||||
case Routes.home:
|
||||
bool? showDialogsArg;
|
||||
if (settings.arguments is bool?) {
|
||||
showDialogsArg = settings.arguments as bool?;
|
||||
} else if (settings.arguments != null) {
|
||||
print('Warning: Invalid argument type for showDialogs. Expected bool?, got ${settings.arguments.runtimeType}. Using default null.');
|
||||
}
|
||||
return _createRoute(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
|
|
@ -161,7 +138,7 @@ class RouteGenerator {
|
|||
create: (context) => NewStatisticState())
|
||||
],
|
||||
child: Home(
|
||||
showDialogs: showDialogsArg,
|
||||
showDialogs: settings.arguments as bool?,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -218,7 +195,6 @@ class RouteGenerator {
|
|||
));
|
||||
|
||||
case Routes.radarDetails:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<RadarDetailsState>(
|
||||
create: (context) => RadarDetailsState(),
|
||||
|
|
@ -227,12 +203,7 @@ class RouteGenerator {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.statGeneral:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<StatGeneralScreenState>(
|
||||
|
|
@ -243,13 +214,8 @@ class RouteGenerator {
|
|||
child: StatGeneralScreen(
|
||||
pageData: settings.arguments as Map<String, dynamic>),
|
||||
));
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
|
||||
case Routes.newsDetails:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<NewsDetailsState>(
|
||||
create: (context) => NewsDetailsState(),
|
||||
|
|
@ -258,24 +224,14 @@ class RouteGenerator {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.studioDetails:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
StudioDetails(
|
||||
pageData: settings.arguments as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
|
||||
case Routes.statisticDetails:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<StatisticDetailsState>(
|
||||
create: (context) => StatisticDetailsState(),
|
||||
|
|
@ -284,10 +240,6 @@ class RouteGenerator {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
|
||||
case Routes.stock:
|
||||
return _createRoute(MultiProvider(
|
||||
|
|
@ -307,20 +259,13 @@ class RouteGenerator {
|
|||
),
|
||||
);
|
||||
case Routes.direct:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<DirectState>(
|
||||
create: (context) => DirectState(),
|
||||
child:
|
||||
Direct(pageData: settings.arguments as Map<String, dynamic>),
|
||||
child: Direct(pageData: settings.arguments as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.comments:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<CommentsState>(
|
||||
create: (context) => CommentsState(),
|
||||
|
|
@ -329,12 +274,7 @@ class RouteGenerator {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.mentions:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<MentionsState>(
|
||||
create: (context) => MentionsState(),
|
||||
|
|
@ -343,10 +283,6 @@ class RouteGenerator {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
case Routes.bookmarks:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<BookmarksState>(
|
||||
|
|
@ -355,55 +291,36 @@ class RouteGenerator {
|
|||
),
|
||||
);
|
||||
case Routes.hashtag:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<HashtagState>(
|
||||
create: (context) => HashtagState(),
|
||||
child: Hashtag(
|
||||
pageData: settings.arguments as Map<String, dynamic>),
|
||||
child:
|
||||
Hashtag(pageData: settings.arguments as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||
|
||||
|
||||
case Routes.filteredBookmarks:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
final args = settings.arguments as Map<String, dynamic>;
|
||||
if (args['type'] is int) {
|
||||
final type = args['type'] as int;
|
||||
final onDeleted = args['onDeleted'] as void Function(int id)?;
|
||||
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<FilteredBookmarksState>(
|
||||
create: (context) => FilteredBookmarksState(type),
|
||||
create: (context) => FilteredBookmarksState(
|
||||
type,
|
||||
),
|
||||
child: FilteredBookmarks(
|
||||
onDeleted: onDeleted,
|
||||
type: type,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: "type" key is missing or not an int.');
|
||||
}
|
||||
} else {
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected a Map.');
|
||||
}
|
||||
|
||||
case Routes.aiChat:
|
||||
if (settings.arguments is AiChatArgs) {
|
||||
return _createRoute(ChangeNotifierProvider<AiChatState>(
|
||||
create: (context) => AiChatState(),
|
||||
child: AiChatPage(
|
||||
args: settings.arguments as AiChatArgs,
|
||||
)));
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected AiChatArgs.');
|
||||
|
||||
|
||||
case Routes.aiHistory:
|
||||
return _createRoute(HistoryAiChatPage(
|
||||
archived: settings.arguments as bool?,
|
||||
|
|
@ -437,42 +354,22 @@ class RouteGenerator {
|
|||
child: const InfoPage()));
|
||||
|
||||
case Routes.web:
|
||||
if (settings.arguments is String) {
|
||||
return _createRoute(WebView(
|
||||
src: settings.arguments as String,
|
||||
));
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected String.');
|
||||
|
||||
case Routes.storyViewer:
|
||||
if (settings.arguments is Map<String, dynamic>) {
|
||||
final args = settings.arguments as Map<String, dynamic>;
|
||||
final stories = args['stories'] as List<UserStories>;
|
||||
final tappedIndex = args['tappedIndex'] as int;
|
||||
return _createRoute(
|
||||
StoryViewerPage(
|
||||
stories: stories,
|
||||
tappedIndex: tappedIndex,
|
||||
),
|
||||
);
|
||||
}
|
||||
return _errorRoute(
|
||||
'Invalid arguments for ${settings.name}: Expected Map with stories and tappedIndex.');
|
||||
|
||||
default:
|
||||
return _errorRoute(settings.name ?? 'Unknown route');
|
||||
return _errorRoute(settings.name ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
static Route<dynamic> _errorRoute(String message) {
|
||||
static Route<dynamic> _errorRoute(String name) {
|
||||
return MaterialPageRoute(builder: (_) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('خطا در مسیریابی'),
|
||||
title: const Text('Error'),
|
||||
),
|
||||
body: Center(
|
||||
child: Text('مسیر "$message" معتبر نیست یا آرگومانهای نادرستی ارسال شده است.'),
|
||||
child: Text('$name is not valid'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ class Routes {
|
|||
static const String info = '/info-page';
|
||||
|
||||
static const String home = '/home';
|
||||
static const String aiSection = '/ai-section';
|
||||
|
||||
static const String radars = '/radars';
|
||||
static const String news = '/news';
|
||||
static const String infography = '/infography';
|
||||
|
|
@ -40,5 +38,4 @@ class Routes {
|
|||
static const String widgetSetting = '/widget-setting';
|
||||
static const String newStatic = '/new-static';
|
||||
static const String web = '/web';
|
||||
static const String storyViewer = '/story-viewer';
|
||||
}
|
||||
|
|
@ -68,6 +68,7 @@ class AiApiService {
|
|||
// bytes = reader.result as Uint8List;
|
||||
}
|
||||
} else {
|
||||
// For other platforms
|
||||
bytes = await file.main.readAsBytes();
|
||||
}
|
||||
if (file.isRecorded) {
|
||||
|
|
@ -97,19 +98,20 @@ class AiApiService {
|
|||
Future<Stream<List<int>>> getResponse(http.MultipartRequest req) async {
|
||||
try {
|
||||
final response = await http.Client().send(req);
|
||||
if (response.statusCode != 200) {
|
||||
final errorBody = await response.stream.bytesToString();
|
||||
print(
|
||||
'body: ${req.url} sc: ${response.statusCode}');
|
||||
print('res: $errorBody');
|
||||
throw Exception(
|
||||
'sc is ${response.statusCode}');
|
||||
if (response.statusCode == 400) {
|
||||
// Handle 400 response
|
||||
final errorResponse = await response.stream.bytesToString();
|
||||
final errorJson = jsonDecode(errorResponse);
|
||||
throw Exception(errorJson['error'] ?? 'Bad Request');
|
||||
} else if (response.statusCode != 200) {
|
||||
// Handle other non-200 responses
|
||||
throw Exception('Failed to load data');
|
||||
} else {
|
||||
return response.stream.asBroadcastStream();
|
||||
}
|
||||
} catch (e) {
|
||||
print('req ${req.url}: $e');
|
||||
throw Exception('Failed to load data due to an exception.');
|
||||
// Handle any other errors
|
||||
throw Exception('Failed to load data');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import 'package:didvan/models/requests/studio.dart';
|
|||
class RequestHelper {
|
||||
static const String baseUrl = 'https://api.didvan.app';
|
||||
static const String baseUrl2 = 'http://opportunity-threat.didvan.com';
|
||||
static const String storiesV1 = '$baseUrl2/api/v1/stories';
|
||||
static const String storyActivity = '$baseUrl2/api/v1/stories/activity';
|
||||
static const String _baseUserUrl = '$baseUrl/user';
|
||||
static const String _baseRadarUrl = '$baseUrl/radar';
|
||||
static const String _baseNewsUrl = '$baseUrl/news';
|
||||
|
|
@ -20,7 +18,6 @@ class RequestHelper {
|
|||
static const String _baseHomeUrl = '$baseUrl/home';
|
||||
static const String _baseNewStats = '$baseUrl/home/statistic';
|
||||
static const String _baseNewStatsSearch = '$baseUrl/home/statistic/search';
|
||||
static const String checkHasPassword = '$_baseUserUrl/checkHasPassword';
|
||||
|
||||
static const String mainPageContent = _baseHomeUrl;
|
||||
static String searchAll({
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'package:didvan/main.dart';
|
||||
import 'package:didvan/models/story_model.dart';
|
||||
import 'package:didvan/providers/user.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class StoryService {
|
||||
static Future<List<UserStories>> getStories() async {
|
||||
// دریافت UserProvider از طریق navigatorKey
|
||||
final userProvider =
|
||||
Provider.of<UserProvider>(navigatorKey.currentContext!, listen: false);
|
||||
final userId = userProvider.user.id;
|
||||
final token = RequestService.token;
|
||||
|
||||
// اضافه کردن userId به عنوان پارامتر به URL
|
||||
final uri = Uri.parse(RequestHelper.storiesV1).replace(queryParameters: {
|
||||
'userId': userId.toString(),
|
||||
});
|
||||
|
||||
final response = await http.get(
|
||||
uri, // استفاده از uri جدید
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
// ... بقیه کد بدون تغییر باقی میماند
|
||||
if (response.statusCode == 200) {
|
||||
final decodedBody = utf8.decode(response.bodyBytes);
|
||||
final dynamic jsonData = json.decode(decodedBody);
|
||||
|
||||
List<dynamic> storyList;
|
||||
|
||||
if (jsonData is List) {
|
||||
storyList = jsonData;
|
||||
} else if (jsonData is Map<String, dynamic> &&
|
||||
jsonData.containsKey('content')) {
|
||||
storyList = jsonData['content'];
|
||||
} else {
|
||||
throw Exception('Unexpected JSON structure for stories response');
|
||||
}
|
||||
|
||||
return storyList.map((json) => UserStories.fromApiJson(json)).toList();
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to load stories with status code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> markStoryAsViewed(int storyId, int storyItemId) async {
|
||||
final userProvider =
|
||||
Provider.of<UserProvider>(navigatorKey.currentContext!, listen: false);
|
||||
final userId = userProvider.user.id;
|
||||
|
||||
final service = RequestService(
|
||||
RequestHelper.storyActivity,
|
||||
body: {
|
||||
'userId': userId,
|
||||
'storyId': storyId,
|
||||
'storyItemId': storyItemId,
|
||||
},
|
||||
);
|
||||
|
||||
await service.post();
|
||||
return service.isSuccess;
|
||||
}
|
||||
}
|
||||
|
|
@ -159,24 +159,24 @@ class DateTimeUtils {
|
|||
double interval = seconds / 31536000;
|
||||
|
||||
if (interval > 1) {
|
||||
return "منتشر شده در ${interval.floor()} سال پیش";
|
||||
return "${interval.floor()} سال پیش";
|
||||
}
|
||||
interval = seconds / 2592000;
|
||||
if (interval > 1) {
|
||||
return "منتشر شده در ${interval.floor()} ماه پیش";
|
||||
return "${interval.floor()} ماه پیش";
|
||||
}
|
||||
interval = seconds / 86400;
|
||||
if (interval > 1) {
|
||||
if (interval.floor() == 1) return 'دیروز';
|
||||
return "منتشر شده در ${interval.floor()} روز پیش";
|
||||
return "${interval.floor()} روز پیش";
|
||||
}
|
||||
interval = seconds / 3600;
|
||||
if (interval > 1) {
|
||||
return "منتشر شده در ${interval.floor()} ساعت پیش";
|
||||
return "${interval.floor()} ساعت پیش";
|
||||
}
|
||||
interval = seconds / 60;
|
||||
if (interval > 1) {
|
||||
return "منتشر شده در ${interval.floor()} دقیقه پیش";
|
||||
return "${interval.floor()} دقیقه پیش";
|
||||
}
|
||||
return 'هم اکنون';
|
||||
// return seconds.floor().toString() + " ثانیه پیش";
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: library_private_types_in_public_api
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
|
|
@ -8,20 +10,22 @@ import 'package:didvan/utils/action_sheet.dart';
|
|||
import 'package:didvan/views/ai/ai_state.dart';
|
||||
import 'package:didvan/views/ai/history_ai_chat_state.dart';
|
||||
import 'package:didvan/views/ai/tool_screen.dart';
|
||||
|
||||
import 'package:didvan/views/ai/widgets/message_bar_btn.dart';
|
||||
import 'package:didvan/views/home/home.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||
import 'package:didvan/views/widgets/state_handlers/empty_connection.dart';
|
||||
import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Ai extends StatefulWidget {
|
||||
const Ai({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
// ignore: library_private_types_in_public_api
|
||||
_AiState createState() => _AiState();
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +100,81 @@ class _AiState extends State<Ai> {
|
|||
);
|
||||
}
|
||||
|
||||
return const SizedBox();
|
||||
return GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
childAspectRatio: 1 / 1,
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8),
|
||||
itemCount: tools.length,
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.all(16),
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
final tool = tools[index];
|
||||
return InkWell(
|
||||
onTap: () => context
|
||||
.read<AiState>()
|
||||
.goToToolBox(tool: tool),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig
|
||||
.lowBorderRadius,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surface,
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.border,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.network(
|
||||
tool.image!,
|
||||
width: 48,
|
||||
height: 48,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
DidvanText(
|
||||
tool.name ?? '',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall,
|
||||
maxLines: 2,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
),
|
||||
Flexible(
|
||||
child: DidvanText(
|
||||
tool.description ?? '',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.caption,
|
||||
maxLines: 2,
|
||||
textAlign:
|
||||
TextAlign.center,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
@ -111,55 +189,45 @@ class _AiState extends State<Ai> {
|
|||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
final historyState =
|
||||
context.read<HistoryAiChatState>();
|
||||
if (historyState.bots.isEmpty) {
|
||||
historyState.getBots();
|
||||
}
|
||||
ActionSheetUtils(context)
|
||||
.botsDialogSelect(context: context);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: const SizedBox(),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// vertical: 8.0, horizontal: 12.0),
|
||||
// child: Row(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment:
|
||||
// CrossAxisAlignment.center,
|
||||
// mainAxisAlignment: MainAxisAlignment.start,
|
||||
// children: [
|
||||
// Icon(DidvanIcons.angle_down_light,
|
||||
// size: 16,
|
||||
// color: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .title),
|
||||
// const SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// DidvanText(
|
||||
// bot.name.toString(),
|
||||
// color: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .title,
|
||||
// style: const TextStyle(
|
||||
// fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 12,
|
||||
// ),
|
||||
// SkeletonImage(
|
||||
// width: 28,
|
||||
// height: 28,
|
||||
// imageUrl: bot.image.toString(),
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(360),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
onTap: () => ActionSheetUtils(context)
|
||||
.botsDialogSelect(context: context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
DidvanIcons.caret_down_solid,
|
||||
color:
|
||||
Theme.of(context).colorScheme.title,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
DidvanText(
|
||||
bot.name.toString(),
|
||||
color:
|
||||
Theme.of(context).colorScheme.title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
SkeletonImage(
|
||||
width: 28,
|
||||
height: 28,
|
||||
imageUrl: bot.image.toString(),
|
||||
borderRadius:
|
||||
BorderRadius.circular(360),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => Navigator.of(context)
|
||||
|
|
@ -174,12 +242,17 @@ class _AiState extends State<Ai> {
|
|||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: DesignConfig
|
||||
.defaultShadow,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surface,
|
||||
border: Border.all(
|
||||
color: const Color.fromARGB(255, 0, 126, 167),width: 1.5),
|
||||
borderRadius: BorderRadius.circular(50)),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.border),
|
||||
borderRadius: DesignConfig
|
||||
.highBorderRadius),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
|
@ -218,7 +291,7 @@ class _AiState extends State<Ai> {
|
|||
InputBorder
|
||||
.none,
|
||||
hintText:
|
||||
'بنویسید یا پیام صوتی بگذارید...',
|
||||
'بنویسید...',
|
||||
hintStyle: Theme.of(
|
||||
context)
|
||||
.textTheme
|
||||
|
|
@ -245,7 +318,7 @@ class _AiState extends State<Ai> {
|
|||
},
|
||||
enable: false,
|
||||
icon: Icons
|
||||
.add),
|
||||
.attach_file_rounded),
|
||||
],
|
||||
))))
|
||||
],
|
||||
|
|
@ -259,7 +332,7 @@ class _AiState extends State<Ai> {
|
|||
EdgeInsets.fromLTRB(8, 8, 8, 4),
|
||||
child: FittedBox(
|
||||
child: DidvanText(
|
||||
'مدلهای هوش مصنوعی میتوانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید.',style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'مدلهای هوش مصنوعی میتوانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید.',
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -281,7 +354,7 @@ class _AiState extends State<Ai> {
|
|||
top: 32,
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
onTap: () => Scaffold.of(context).openDrawer(),
|
||||
onTap: () => homeScaffKey.currentState!.openDrawer(),
|
||||
child: Container(
|
||||
width: 46,
|
||||
height: 46,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class _AiChatPageState extends State<AiChatPage> {
|
|||
state.chatId = widget.args.chat!.id!;
|
||||
state.chat = widget.args.chat;
|
||||
}
|
||||
// JsInteropService().showAlert();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (state.chatId != null) {
|
||||
state.getAllMessages(state.chatId!).then((value) => Future.delayed(
|
||||
|
|
@ -428,104 +429,103 @@ class _AiChatPageState extends State<AiChatPage> {
|
|||
.toString()
|
||||
.contains('user') &&
|
||||
widget.args.assistantsName == null)
|
||||
// PopupMenuButton(
|
||||
// offset: const Offset(0, 46),
|
||||
// onSelected: (value) async {
|
||||
// navigatorKey.currentState!.pushNamed(
|
||||
// Routes.aiChat,
|
||||
// arguments: AiChatArgs(
|
||||
// bot: value,
|
||||
// prompts: message,
|
||||
// isTool: widget.args.isTool ??
|
||||
// context
|
||||
// .read<
|
||||
// HistoryAiChatState>()
|
||||
// .bots));
|
||||
// },
|
||||
// itemBuilder: (BuildContext context) {
|
||||
// final bots = widget.args.isTool ??
|
||||
// context
|
||||
// .read<HistoryAiChatState>()
|
||||
// .bots;
|
||||
// return <PopupMenuEntry>[
|
||||
// ...List.generate(
|
||||
// bots.length,
|
||||
// (index) => PopupMenuItem(
|
||||
// value: bots[index],
|
||||
// height: 72,
|
||||
// child: Container(
|
||||
// constraints:
|
||||
// const BoxConstraints(
|
||||
// maxWidth: 200),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// SkeletonImage(
|
||||
// imageUrl: bots[index]
|
||||
// .image
|
||||
// .toString(),
|
||||
// width: 42,
|
||||
// height: 42,
|
||||
// borderRadius:
|
||||
// BorderRadius
|
||||
// .circular(360),
|
||||
// ),
|
||||
// const SizedBox(width: 12),
|
||||
// Expanded(
|
||||
// child: Directionality(
|
||||
// textDirection:
|
||||
// TextDirection.ltr,
|
||||
// child: DidvanText(
|
||||
// bots[index]
|
||||
// .name
|
||||
// .toString(),
|
||||
// maxLines: 1,
|
||||
// overflow:
|
||||
// TextOverflow
|
||||
// .ellipsis,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ];
|
||||
// },
|
||||
// // child: Container(
|
||||
// // alignment: Alignment.center,
|
||||
// // margin: const EdgeInsets.all(8),
|
||||
// // padding: const EdgeInsets.symmetric(
|
||||
// // horizontal: 8),
|
||||
// // constraints: const BoxConstraints(
|
||||
// // maxWidth: 100),
|
||||
// // decoration: BoxDecoration(
|
||||
// // borderRadius:
|
||||
// // DesignConfig.lowBorderRadius,
|
||||
// // border: Border.all(
|
||||
// // color: Theme.of(context)
|
||||
// // .colorScheme
|
||||
// // .title)),
|
||||
// // child: Row(
|
||||
// // children: [
|
||||
// // Expanded(
|
||||
// // child: Directionality(
|
||||
// // textDirection:
|
||||
// // TextDirection.ltr,
|
||||
// // child: DidvanText(
|
||||
// // '${widget.args.assistantsName ?? widget.args.bot.name}',
|
||||
// // maxLines: 1,
|
||||
// // overflow:
|
||||
// // TextOverflow.ellipsis,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // const Icon(
|
||||
// // DidvanIcons.angle_down_light),
|
||||
// // ],
|
||||
// // ),
|
||||
// // )
|
||||
// ),
|
||||
PopupMenuButton(
|
||||
offset: const Offset(0, 46),
|
||||
onSelected: (value) async {
|
||||
navigatorKey.currentState!.pushNamed(
|
||||
Routes.aiChat,
|
||||
arguments: AiChatArgs(
|
||||
bot: value,
|
||||
prompts: message,
|
||||
isTool: widget.args.isTool ??
|
||||
context
|
||||
.read<
|
||||
HistoryAiChatState>()
|
||||
.bots));
|
||||
},
|
||||
itemBuilder: (BuildContext context) {
|
||||
final bots = widget.args.isTool ??
|
||||
context
|
||||
.read<HistoryAiChatState>()
|
||||
.bots;
|
||||
return <PopupMenuEntry>[
|
||||
...List.generate(
|
||||
bots.length,
|
||||
(index) => PopupMenuItem(
|
||||
value: bots[index],
|
||||
height: 72,
|
||||
child: Container(
|
||||
constraints:
|
||||
const BoxConstraints(
|
||||
maxWidth: 200),
|
||||
child: Row(
|
||||
children: [
|
||||
SkeletonImage(
|
||||
imageUrl: bots[index]
|
||||
.image
|
||||
.toString(),
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(360),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Directionality(
|
||||
textDirection:
|
||||
TextDirection.ltr,
|
||||
child: DidvanText(
|
||||
bots[index]
|
||||
.name
|
||||
.toString(),
|
||||
maxLines: 1,
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
];
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
margin: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8),
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 100),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
DesignConfig.lowBorderRadius,
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.title)),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Directionality(
|
||||
textDirection:
|
||||
TextDirection.ltr,
|
||||
child: DidvanText(
|
||||
'${widget.args.assistantsName ?? widget.args.bot.name}',
|
||||
maxLines: 1,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
DidvanIcons.angle_down_light),
|
||||
],
|
||||
),
|
||||
)),
|
||||
if (message.role
|
||||
.toString()
|
||||
.contains('user') &&
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ class AiChatState extends CoreProvier {
|
|||
await ActionSheetUtils(navigatorKey.currentContext!).showAlert(AlertData(
|
||||
message: 'خطا در برقراری ارتباط', aLertType: ALertType.error));
|
||||
update();
|
||||
print("error is ${e.toString()}");
|
||||
}
|
||||
|
||||
Future<RequestService> getChatId() async {
|
||||
|
|
@ -196,6 +195,7 @@ class AiChatState extends CoreProvier {
|
|||
if (kIsWeb) {
|
||||
try {
|
||||
int startIndex = responseMessgae.indexOf('{{{');
|
||||
// + 3 to include the }}} characters
|
||||
|
||||
String slicedText =
|
||||
responseMessgae.substring(startIndex, responseMessgae.length);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ class AiState extends CoreProvier {
|
|||
bool loading = true;
|
||||
List<Tools>? tools;
|
||||
|
||||
|
||||
void getTools() async {
|
||||
final service = RequestService(
|
||||
RequestHelper.tools(),
|
||||
|
|
|
|||
|
|
@ -61,14 +61,6 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final state = context.read<CreateBotAssistantsState>();
|
||||
if (widget.id != null) {
|
||||
state.getAnAssistant(id: widget.id!);
|
||||
} else {
|
||||
state.getImageToolsBots();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void onConfirm(CreateBotAssistantsState state) async {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,123 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/ai/ai_chat_args.dart';
|
||||
import 'package:didvan/models/ai/tools_model.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/ai/ai_state.dart';
|
||||
import 'package:didvan/views/ai/widgets/tool_category_view_widget.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ToolScreen extends StatelessWidget {
|
||||
class ToolScreen extends StatefulWidget {
|
||||
const ToolScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Tools? tool = context.watch<AiState>().tool;
|
||||
State<ToolScreen> createState() => _ToolScreenState();
|
||||
}
|
||||
|
||||
if (tool == null) {
|
||||
return const Center(child: Text("ابزاری انتخاب نشده است."));
|
||||
}
|
||||
return ToolCategoryViewWidget(tool: tool);
|
||||
class _ToolScreenState extends State<ToolScreen> {
|
||||
late Tools tool = context.read<AiState>().tool!;
|
||||
|
||||
get itemBuilder => null;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 32),
|
||||
SvgPicture.network(
|
||||
tool.image!,
|
||||
width: 64,
|
||||
height: 64,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
DidvanText(
|
||||
tool.name!,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.checkFav,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: DidvanText(
|
||||
tool.guide!,
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.caption,
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: tool.bots!.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: 1 / 1,
|
||||
crossAxisSpacing: 18,
|
||||
mainAxisSpacing: 18),
|
||||
itemBuilder: (context, index) {
|
||||
final bot = tool.bots![index];
|
||||
return InkWell(
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.aiChat,
|
||||
arguments: AiChatArgs(bot: bot, isTool: tool.bots)),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
border: Border.all(color: const Color(0xffbbbbbb))),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SkeletonImage(
|
||||
imageUrl: bot.image!,
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: BorderRadius.circular(360),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
DidvanText(
|
||||
bot.name ?? '',
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.text,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (bot.short != null)
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
DidvanText(
|
||||
bot.short!,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: const Color(0xffA8A6AC),
|
||||
// maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -248,10 +248,8 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
boxShadow: DesignConfig.defaultShadow,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border.all(
|
||||
color: const Color.fromARGB(255, 0, 126, 167),
|
||||
width: 1.5),
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
color: Theme.of(context).colorScheme.border),
|
||||
borderRadius: DesignConfig.highBorderRadius),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
|
|
@ -296,11 +294,10 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
),
|
||||
MediaQuery.of(context).viewInsets.bottom == 0
|
||||
? const Padding(
|
||||
padding: EdgeInsets.fromLTRB(3, 8, 3, 4),
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 4),
|
||||
child: DidvanText(
|
||||
'مدلهای هوش مصنوعی میتوانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید.',
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
)
|
||||
: const SizedBox(
|
||||
|
|
@ -409,7 +406,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
enable: false,
|
||||
icon: openAttach || state.file != null
|
||||
? DidvanIcons.close_regular
|
||||
: Icons.add,
|
||||
: Icons.attach_file_outlined,
|
||||
click: () {
|
||||
if (_mPlayer!.isPlaying) {
|
||||
stopPlayer();
|
||||
|
|
@ -560,10 +557,11 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
|
||||
if (kIsWeb) {
|
||||
Uint8List? bytes = result
|
||||
.files.first.bytes;
|
||||
.files.first.bytes; // Access the bytes property
|
||||
|
||||
// Store bytes and file name directly in your state or model
|
||||
state.file = FilesModel(
|
||||
'',
|
||||
'', // No need for a file path on web
|
||||
name: name,
|
||||
bytes: bytes,
|
||||
audio: false,
|
||||
|
|
@ -665,7 +663,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
|
||||
|
||||
state.file = FilesModel(
|
||||
blobUrl,
|
||||
blobUrl, // No need for a file path on web
|
||||
name: name,
|
||||
bytes: bytes,
|
||||
audio: true,
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ class _AiMessageBarIOSState extends State<AiMessageBarIOS> {
|
|||
},
|
||||
enable: false,
|
||||
icon: Icons
|
||||
.add,
|
||||
.attach_file_rounded,
|
||||
)
|
||||
: const SizedBox(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -28,15 +28,10 @@ class HoshanDrawer extends StatefulWidget {
|
|||
|
||||
class _HoshanDrawerState extends State<HoshanDrawer> {
|
||||
@override
|
||||
void initState() {
|
||||
initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final historyState = context.read<HistoryAiChatState>();
|
||||
if (historyState.chats.isEmpty && !historyState.loadinggetAll) {
|
||||
historyState.getChats(archived: false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
|
|
@ -155,6 +150,7 @@ class _HoshanDrawerState extends State<HoshanDrawer> {
|
|||
state: state,
|
||||
centerEmptyState: false,
|
||||
emptyState: const EmptyList(),
|
||||
// enableEmptyState: state.chats.isEmpty,
|
||||
placeholder: chatRowPlaceholder(),
|
||||
placeholderCount: 10,
|
||||
builder: (context, state, index) {
|
||||
|
|
@ -290,6 +286,7 @@ class _HoshanDrawerState extends State<HoshanDrawer> {
|
|||
color: enable
|
||||
? Theme.of(context).colorScheme.title
|
||||
: Theme.of(context).colorScheme.disabledText),
|
||||
// if (!enable) Text('در حال توسعه ...')
|
||||
],
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,178 +0,0 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/ai/ai_chat_args.dart';
|
||||
import 'package:didvan/models/ai/tools_model.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class ToolCategoryViewWidget extends StatelessWidget {
|
||||
final Tools tool;
|
||||
const ToolCategoryViewWidget({Key? key, required this.tool}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const Color customBackgroundColor = Color.fromRGBO(0, 126, 167, 1.0);
|
||||
|
||||
return SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.only(top: 32, bottom: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
if (tool.image != null)
|
||||
SvgPicture.network(
|
||||
tool.image!,
|
||||
width: 64,
|
||||
height: 64,
|
||||
placeholderBuilder: (BuildContext context) => const SizedBox(
|
||||
width: 64,
|
||||
height: 64,
|
||||
child: Center(child: CircularProgressIndicator(strokeWidth: 2.0)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: DidvanText(
|
||||
tool.name ?? "ابزار هوش مصنوعی",
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.checkFav,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (tool.guide != null && tool.guide!.isNotEmpty) ...[
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: DidvanText(
|
||||
tool.guide!,
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.caption,
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
if (tool.bots != null && tool.bots!.isNotEmpty)
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: tool.bots!.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: 1 / 1.1,
|
||||
crossAxisSpacing: 18,
|
||||
mainAxisSpacing: 18),
|
||||
itemBuilder: (context, index) {
|
||||
final bot = tool.bots![index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(Routes.aiChat,
|
||||
arguments: AiChatArgs(bot: bot, isTool: tool.bots));
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: DesignConfig.highBorderRadius.topLeft,
|
||||
topRight: DesignConfig.highBorderRadius.topRight,
|
||||
bottomRight: DesignConfig.highBorderRadius.bottomRight,
|
||||
bottomLeft: DesignConfig.highBorderRadius.bottomLeft,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border.all(color: Theme.of(context).colorScheme.border)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Container(
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: customBackgroundColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: DesignConfig.highBorderRadius.topLeft,
|
||||
topRight: DesignConfig.highBorderRadius.topRight,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 8, 12, 12),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (bot.image != null)
|
||||
SkeletonImage(
|
||||
imageUrl: bot.image!,
|
||||
width: 70,
|
||||
height: 70,
|
||||
borderRadius: BorderRadius.circular(360),
|
||||
)
|
||||
else
|
||||
Icon(DidvanIcons.ai_solid, size: 50, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
color: customBackgroundColor,
|
||||
),
|
||||
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: DidvanText(
|
||||
bot.name ?? '',
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (bot.short != null && bot.short!.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: DidvanText(
|
||||
bot.short!,
|
||||
fontSize: 10,
|
||||
color: Theme.of(context).colorScheme.caption,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
] else const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
else
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
child: Center(child: DidvanText("هیچ رباتی برای ابزار '${tool.name ?? "انتخابی"}' موجود نیست.")),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
import 'package:didvan/models/ai/tools_model.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/views/ai/ai.dart';
|
||||
import 'package:didvan/views/ai/widgets/hoshan_drawer.dart';
|
||||
import 'package:didvan/views/ai_section/widgets/ai_section_bnb.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/hoshan_app_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:didvan/views/ai/history_ai_chat_state.dart';
|
||||
import 'package:didvan/views/ai/ai_state.dart';
|
||||
import 'package:didvan/views/ai/widgets/tool_category_view_widget.dart';
|
||||
|
||||
class ImageGenerationScreen extends StatelessWidget {
|
||||
const ImageGenerationScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final aiState = context.watch<AiState>();
|
||||
|
||||
if (aiState.tools == null || aiState.tools!.isEmpty) {
|
||||
if (aiState.loading || aiState.appState == AppState.busy) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return const Center(
|
||||
child: DidvanText('لیست ابزارها هنوز بارگذاری نشده یا خالی است.'));
|
||||
}
|
||||
final Tools imageGenToolCategory = aiState.tools![0];
|
||||
return ToolCategoryViewWidget(tool: imageGenToolCategory);
|
||||
}
|
||||
}
|
||||
|
||||
class VoiceChatScreen extends StatelessWidget {
|
||||
const VoiceChatScreen({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final aiState = context.watch<AiState>();
|
||||
|
||||
if (aiState.tools == null || aiState.tools!.isEmpty) {
|
||||
if (aiState.loading || aiState.appState == AppState.busy) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return const Center(
|
||||
child: DidvanText('لیست ابزارها هنوز بارگذاری نشده یا خالی است.'));
|
||||
}
|
||||
final Tools voiceChatToolCategory = aiState.tools!.last;
|
||||
|
||||
return ToolCategoryViewWidget(tool: voiceChatToolCategory);
|
||||
}
|
||||
}
|
||||
|
||||
class ChartAnalysisScreen extends StatelessWidget {
|
||||
const ChartAnalysisScreen({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final aiState = context.watch<AiState>();
|
||||
|
||||
if (aiState.tools == null || aiState.tools!.isEmpty) {
|
||||
if (aiState.loading || aiState.appState == AppState.busy) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return const Center(
|
||||
child: DidvanText('لیست ابزارها هنوز بارگذاری نشده یا خالی است.'));
|
||||
}
|
||||
|
||||
if (aiState.tools!.length < 2) {
|
||||
return const Center(
|
||||
child:
|
||||
DidvanText('ابزار کافی برای "تحلیل نمودار" وجود ندارد.'));
|
||||
}
|
||||
final Tools chartAnalysisToolCategory = aiState.tools![1];
|
||||
|
||||
return ToolCategoryViewWidget(tool: chartAnalysisToolCategory);
|
||||
}
|
||||
}
|
||||
|
||||
class TranslationScreen extends StatelessWidget {
|
||||
const TranslationScreen({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final aiState = context.watch<AiState>();
|
||||
|
||||
if (aiState.tools == null || aiState.tools!.isEmpty) {
|
||||
if (aiState.loading || aiState.appState == AppState.busy) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return const Center(
|
||||
child: DidvanText('لیست ابزارها هنوز بارگذاری نشده یا خالی است.'));
|
||||
}
|
||||
|
||||
if (aiState.tools!.length < 3) {
|
||||
return const Center(
|
||||
child: DidvanText('ابزار کافی برای "ترجمه" وجود ندارد.'));
|
||||
}
|
||||
final Tools translationToolCategory = aiState.tools![2];
|
||||
|
||||
return ToolCategoryViewWidget(tool: translationToolCategory);
|
||||
}
|
||||
}
|
||||
|
||||
class AiSectionPage extends StatefulWidget {
|
||||
const AiSectionPage({super.key});
|
||||
|
||||
@override
|
||||
State<AiSectionPage> createState() => _AiSectionPageState();
|
||||
}
|
||||
|
||||
class _AiSectionPageState extends State<AiSectionPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late TabController _tabController;
|
||||
int _currentTabIndex = 2;
|
||||
final GlobalKey<ScaffoldState> _aiSectionScaffoldKey =
|
||||
GlobalKey<ScaffoldState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabController = TabController(length: 5, vsync: this, initialIndex: 2);
|
||||
_tabController.addListener(() {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentTabIndex = _tabController.index;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final historyAiChatState = context.read<HistoryAiChatState>();
|
||||
if (historyAiChatState.bots.isEmpty) {
|
||||
historyAiChatState.getBots();
|
||||
}
|
||||
|
||||
final aiState = context.read<AiState>();
|
||||
aiState.page = 0;
|
||||
if (aiState.tools == null) {
|
||||
aiState.getTools();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _aiSectionScaffoldKey,
|
||||
appBar: HoshanAppBar(
|
||||
onBack: () {
|
||||
final aiState = context.read<AiState>();
|
||||
if (aiState.page != 0) {
|
||||
aiState.goToAi();
|
||||
} else {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
withActions: true,
|
||||
),
|
||||
drawer: HoshanDrawer(scaffKey: _aiSectionScaffoldKey),
|
||||
body: TabBarView(
|
||||
controller: _tabController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: const [
|
||||
ImageGenerationScreen(),
|
||||
VoiceChatScreen(),
|
||||
Ai(),
|
||||
ChartAnalysisScreen(),
|
||||
TranslationScreen(),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: AiSectionBNB(
|
||||
currentTabIndex: _currentTabIndex,
|
||||
onTabChanged: (index) {
|
||||
_tabController.animateTo(index);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/ai/ai_chat_args.dart';
|
||||
import 'package:didvan/models/ai/tools_model.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/services/webview.dart';
|
||||
import 'package:didvan/views/ai/ai_state.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AiSectionBNB extends StatelessWidget {
|
||||
final int currentTabIndex;
|
||||
final void Function(int index) onTabChanged;
|
||||
|
||||
const AiSectionBNB(
|
||||
{Key? key, required this.currentTabIndex, required this.onTabChanged})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const String cameraSolid = 'lib/assets/icons/houshanNav/imagegeneratorS.svg';
|
||||
const String cameraRegular = 'lib/assets/icons/houshanNav/imagegeneratorU.svg';
|
||||
const String micSolid = 'lib/assets/icons/houshanNav/aichatS.svg';
|
||||
const String micRegular = 'lib/assets/icons/houshanNav/aichatU.svg';
|
||||
const String aiSolid = 'lib/assets/icons/houshanNav/houshan.svg';
|
||||
const String aiRegular = 'lib/assets/icons/houshanNav/houshan.svg';
|
||||
const String searchSolid = 'lib/assets/icons/houshanNav/searchS.svg';
|
||||
const String searchRegular = 'lib/assets/icons/houshanNav/searchU.svg';
|
||||
const String translateSolid = 'lib/assets/icons/houshanNav/translateS.svg';
|
||||
const String translateRegular = 'lib/assets/icons/houshanNav/translateU.svg';
|
||||
|
||||
return Container(
|
||||
height: 72,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: const Color(0XFF1B3C59).withValues(alpha: 0.15),
|
||||
blurRadius: 8,
|
||||
spreadRadius: 0,
|
||||
offset: const Offset(0, -8),
|
||||
)
|
||||
],
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
_AiNavBarItem(
|
||||
isSelected: currentTabIndex == 0,
|
||||
title: 'عکس ساز',
|
||||
selectedIcon: cameraSolid,
|
||||
unselectedIcon: cameraRegular,
|
||||
onTap: () {
|
||||
final aiState = context.read<AiState>();
|
||||
if (aiState.tools != null && aiState.tools!.isNotEmpty) {
|
||||
final Tools imageGenTool = aiState.tools![0]; // ابزار عکس ساز
|
||||
if (imageGenTool.bots != null && imageGenTool.bots!.isNotEmpty) {
|
||||
final bot = imageGenTool.bots!.first;
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.aiChat,
|
||||
arguments: AiChatArgs(bot: bot, isTool: imageGenTool.bots),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('ابزار عکس ساز در حال بارگذاری است...')),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
_AiNavBarItem(
|
||||
isSelected: currentTabIndex == 1,
|
||||
title: 'چت صوتی',
|
||||
selectedIcon: micSolid,
|
||||
unselectedIcon: micRegular,
|
||||
onTap: () {
|
||||
NativeWebViewLauncher.openWebView(
|
||||
'https://www.aisada.ir/app/page1.html');
|
||||
},
|
||||
),
|
||||
_AiNavBarItem(
|
||||
isSelected: currentTabIndex == 2,
|
||||
title: '',
|
||||
selectedIcon: aiSolid,
|
||||
unselectedIcon: aiRegular,
|
||||
onTap: () => onTabChanged(2),
|
||||
),
|
||||
_AiNavBarItem(
|
||||
isSelected: currentTabIndex == 3,
|
||||
title: 'جست و جو',
|
||||
selectedIcon: searchSolid,
|
||||
unselectedIcon: searchRegular,
|
||||
onTap: () {
|
||||
final aiState = context.read<AiState>();
|
||||
// نکته: طبق کد شما، تب جستجو (اندیس ۳) ویجت تحلیل نمودار را نمایش میدهد
|
||||
// که از ابزار اندیس ۱ استفاده میکند.
|
||||
if (aiState.tools != null && aiState.tools!.length > 1) {
|
||||
final Tools chartAnalysisTool = aiState.tools![1];
|
||||
if (chartAnalysisTool.bots != null && chartAnalysisTool.bots!.isNotEmpty) {
|
||||
final bot = chartAnalysisTool.bots!.first;
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.aiChat,
|
||||
arguments: AiChatArgs(bot: bot, isTool: chartAnalysisTool.bots),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('ابزار جستجو در حال بارگذاری است...')),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
_AiNavBarItem(
|
||||
isSelected: currentTabIndex == 4,
|
||||
title: 'ترجمه',
|
||||
selectedIcon: translateSolid,
|
||||
unselectedIcon: translateRegular,
|
||||
onTap: () {
|
||||
final aiState = context.read<AiState>();
|
||||
if (aiState.tools != null && aiState.tools!.length > 2) {
|
||||
final Tools translationToolCategory = aiState.tools![2];
|
||||
if (translationToolCategory.bots != null && translationToolCategory.bots!.isNotEmpty) {
|
||||
final gptTranslatorBot = translationToolCategory.bots!.first;
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.aiChat,
|
||||
arguments: AiChatArgs(bot: gptTranslatorBot, isTool: translationToolCategory.bots),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('ابزار ترجمه در حال بارگذاری است...')),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class _AiNavBarItem extends StatelessWidget {
|
||||
final VoidCallback onTap;
|
||||
final bool isSelected;
|
||||
final String title;
|
||||
final String selectedIcon;
|
||||
final String unselectedIcon;
|
||||
|
||||
const _AiNavBarItem({
|
||||
Key? key,
|
||||
required this.isSelected,
|
||||
required this.title,
|
||||
required this.selectedIcon,
|
||||
required this.unselectedIcon,
|
||||
required this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
final double iconSize = title.isEmpty ? 50.0 : 32.0;
|
||||
|
||||
return Expanded(
|
||||
child: Tooltip(
|
||||
message: title,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
borderRadius: DesignConfig.highBorderRadius,
|
||||
boxShadow: DesignConfig.defaultShadow,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
padding: const EdgeInsets.all(4),
|
||||
duration: DesignConfig.lowAnimationDuration,
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
isSelected ? selectedIcon : unselectedIcon,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
),
|
||||
),
|
||||
if (title.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2.0),
|
||||
child: DidvanText(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -26,22 +26,14 @@ class AuthenticationState extends CoreProvier {
|
|||
Future<void> confirmUsername() async {
|
||||
appState = AppState.isolatedBusy;
|
||||
final RequestService service = RequestService(
|
||||
RequestHelper.checkHasPassword,
|
||||
RequestHelper.confirmUsername,
|
||||
useAutherization: false,
|
||||
body: {'username': username},
|
||||
);
|
||||
await service.post();
|
||||
|
||||
if (service.isSuccess) {
|
||||
if (service.isSuccess && service.result['confirmed']) {
|
||||
appState = AppState.idle;
|
||||
|
||||
final bool hasPassword = service.result['hasPassword'];
|
||||
|
||||
if (hasPassword) {
|
||||
currentPageIndex = 1;
|
||||
} else {
|
||||
currentPageIndex = 2;
|
||||
}
|
||||
currentPageIndex++;
|
||||
} else {
|
||||
appState = AppState.failed;
|
||||
ActionSheetUtils(navigatorKey.currentContext!)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:didvan/providers/server_data.dart';
|
||||
import 'package:didvan/providers/user.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||
|
|
@ -50,29 +49,25 @@ class _ResetPasswordState extends State<ResetPassword> {
|
|||
const Spacer(),
|
||||
DidvanButton(
|
||||
onPressed: () async {
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
final result = await context
|
||||
.read<AuthenticationState>()
|
||||
.resetPassword(_password);
|
||||
if (!mounted) return;
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() {
|
||||
if (result && context.read<UserProvider>().isAuthenticated) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
return;
|
||||
}
|
||||
|
||||
final authState = context.read<AuthenticationState>();
|
||||
final userProvider = context.read<UserProvider>();
|
||||
|
||||
final bool resetSuccess =
|
||||
await authState.resetPassword(_password);
|
||||
|
||||
if (resetSuccess && mounted) {
|
||||
authState.password = _password;
|
||||
final String? token = await authState.login(userProvider);
|
||||
|
||||
if (token != null && mounted) {
|
||||
await ServerDataProvider.getData();
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
Routes.home,
|
||||
(_) => false,
|
||||
arguments: true,
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.authenticaion,
|
||||
arguments: false,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
title: 'تغییر رمز عبور',
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:didvan/utils/extension.dart';
|
||||
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||
import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
|
||||
import 'package:didvan/views/widgets/didvan/button.dart';
|
||||
|
|
@ -45,7 +44,7 @@ class _UsernameInputState extends State<UsernameInput> {
|
|||
return null;
|
||||
},
|
||||
onChanged: (value) {
|
||||
state.username = value.convertToEnglishNumber();
|
||||
state.username = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// ignore_for_file: deprecated_member_use
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:didvan/main.dart';
|
||||
import 'package:didvan/models/notification_message.dart';
|
||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||
|
|
@ -9,6 +10,7 @@ import 'package:didvan/providers/theme.dart';
|
|||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/services/app_initalizer.dart';
|
||||
import 'package:didvan/utils/action_sheet.dart';
|
||||
import 'package:didvan/views/ai/ai.dart';
|
||||
import 'package:didvan/views/ai/ai_state.dart';
|
||||
import 'package:didvan/views/ai/history_ai_chat_state.dart';
|
||||
import 'package:didvan/views/ai/widgets/hoshan_drawer.dart';
|
||||
|
|
@ -25,7 +27,6 @@ import 'package:didvan/views/widgets/didvan/bnb.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../services/app_home_widget/home_widget_repository.dart';
|
||||
|
||||
|
|
@ -48,34 +49,19 @@ class _HomeState extends State<Home>
|
|||
ActionSheetUtils(context)
|
||||
.openDialog(
|
||||
data: ActionSheetData(
|
||||
hasDismissButton: false,
|
||||
hasConfirmButton: false,
|
||||
withoutButtonMode: true,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
InkWrapper(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Icon(DidvanIcons.close_solid, size: 24),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
SvgPicture.asset(Assets.horizontalLogoWithText, height: 80),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
DidvanText(
|
||||
'به دیدوان، چشم همیشه باز مدیران خوش آمدید',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
content: const DidvanText(
|
||||
'خوش آمدید!\nبرای امنیت بیشتر، رمز عبور خود را تغییر دهید.',
|
||||
),
|
||||
onConfirmed: () {
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => Navigator.of(context)
|
||||
.pushNamed(Routes.authenticaion, arguments: true),
|
||||
);
|
||||
},
|
||||
isBackgroundDropBlur: false,
|
||||
confrimTitle: 'تغییر رمز عبور',
|
||||
dismissTitle: 'بعدا',
|
||||
),
|
||||
)
|
||||
.then((value) => ActionSheetUtils(context).openDialog(
|
||||
|
|
@ -120,6 +106,7 @@ class _HomeState extends State<Home>
|
|||
"کاربر گرامی\nلطفا جهت شخصیسازی و استفاده بهتر از برنامه، دستهبندیهای مورد علاقه خود و زمان دریافت اعلانات را انتخاب نمایید.")
|
||||
],
|
||||
),
|
||||
// hasDismissButton: false,
|
||||
onConfirmed: () {
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
|
|
@ -250,7 +237,10 @@ class _HomeState extends State<Home>
|
|||
children: const [
|
||||
MainPage(),
|
||||
CategoriesPage(),
|
||||
Ai(),
|
||||
NewStatistic(),
|
||||
//Statistic(),
|
||||
// Bookmarks(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -262,12 +252,10 @@ class _HomeState extends State<Home>
|
|||
builder: (context, state, child) => DidvanBNB(
|
||||
currentTabIndex: state.currentPageIndex,
|
||||
onTabChanged: (index) {
|
||||
if (index < _tabController.length) {
|
||||
state.currentPageIndex = index;
|
||||
FocusScope.of(context).unfocus();
|
||||
state.resetFilters(false);
|
||||
_tabController.animateTo(index);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ class HomeState extends CoreProvier {
|
|||
MenuItemType(
|
||||
label: 'هوشان',
|
||||
asset: Assets.ai,
|
||||
link: Routes.aiSection,
|
||||
link: 'tab-2',
|
||||
),
|
||||
MenuItemType(
|
||||
label: 'فرصت و تهدید',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import 'package:didvan/views/home/main/widgets/banner.dart';
|
|||
import 'package:didvan/views/home/main/widgets/general_item.dart';
|
||||
import 'package:didvan/views/home/main/widgets/main_content.dart';
|
||||
import 'package:didvan/views/home/main/widgets/podcast_item.dart';
|
||||
import 'package:didvan/views/home/main/widgets/story_section.dart';
|
||||
import 'package:didvan/views/widgets/didvan/slider.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
||||
|
|
@ -46,22 +45,13 @@ class _MainPageState extends State<MainPage> {
|
|||
builder: (context, state) => ListView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
children: [
|
||||
if (state.stories.isNotEmpty) StorySection(stories: state.stories),
|
||||
const SizedBox(height: 12),
|
||||
// محتوای اصلی صفحه
|
||||
const MainPageMainContent(),
|
||||
|
||||
Builder(builder: (context) {
|
||||
final List<Widget> pageContent = [];
|
||||
if (state.content != null && state.content!.lists.isNotEmpty) {
|
||||
final lists = state.content!.lists;
|
||||
|
||||
for (int i = 0; i < lists.length; i++) {
|
||||
final currentList = lists[i];
|
||||
|
||||
if (i == 4) {
|
||||
pageContent.add(
|
||||
Padding(
|
||||
// آیتمهای لیستها
|
||||
...List.generate(state.content.lists.length + 1, (index) {
|
||||
if (index == 4) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 32),
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -78,22 +68,17 @@ class _MainPageState extends State<MainPage> {
|
|||
const InfoTitle(),
|
||||
GestureDetector(
|
||||
onTap: () => {
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.infography)
|
||||
Navigator.of(context).pushNamed(Routes.infography)
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
DidvanText(
|
||||
"همه",
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Icon(
|
||||
DidvanIcons.angle_left_light,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -106,34 +91,21 @@ class _MainPageState extends State<MainPage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
pageContent.add(_MainPageSection(
|
||||
list: currentList,
|
||||
isLast: i == lists.length - 1,
|
||||
));
|
||||
|
||||
if (currentList.type == 'startup') {
|
||||
pageContent.add(const _SwotSection());
|
||||
int listIndex = index > 4 ? index - 1 : index;
|
||||
if (listIndex >= state.content.lists.length) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Column(children: pageContent);
|
||||
return _MainPageSection(
|
||||
list: state.content.lists[listIndex],
|
||||
isLast: listIndex == state.content.lists.length - 1,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SwotSection extends StatelessWidget {
|
||||
const _SwotSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<List<SwotItem>>(
|
||||
// کانتینر زیر کل لیستها
|
||||
FutureBuilder<List<SwotItem>>(
|
||||
future: SwotService.fetchSwotItems(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
|
|
@ -190,11 +162,13 @@ class _SwotSection extends StatelessWidget {
|
|||
children: [
|
||||
DidvanText(
|
||||
"همه",
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Icon(
|
||||
DidvanIcons.angle_left_light,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -223,6 +197,9 @@ class _SwotSection extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,61 +4,40 @@ import 'package:didvan/models/home_page_content/home_page_content.dart';
|
|||
import 'package:didvan/models/requests/infography.dart';
|
||||
import 'package:didvan/models/requests/news.dart';
|
||||
import 'package:didvan/models/requests/radar.dart';
|
||||
import 'package:didvan/models/story_model.dart';
|
||||
import 'package:didvan/providers/core.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/services/app_initalizer.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'package:didvan/services/story_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
// import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class MainPageState extends CoreProvier {
|
||||
MainPageContent? content;
|
||||
late MainPageContent content;
|
||||
int unread = 0;
|
||||
List<UserStories> stories = [];
|
||||
|
||||
Future<void> _getMainPageContent() async {
|
||||
final service = RequestService(RequestHelper.mainPageContent);
|
||||
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
content = MainPageContent.fromJson(service.result);
|
||||
unread = service.result['unread'];
|
||||
} else {
|
||||
throw Exception('Failed to load main page content');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchStories() async {
|
||||
try {
|
||||
stories = await StoryService.getStories();
|
||||
// [اضافه شود] تعداد استوری های دریافت شده را چاپ کنید
|
||||
print("Fetched ${stories.length} stories.");
|
||||
} catch (e) {
|
||||
stories = [];
|
||||
// [اضافه شود] خطای رخ داده را چاپ کنید
|
||||
debugPrint("Could not fetch stories: $e");
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
void init() {
|
||||
Future.delayed(Duration.zero, () async {
|
||||
appState = AppState.busy;
|
||||
try {
|
||||
await Future.wait([
|
||||
_getMainPageContent(),
|
||||
_fetchStories(),
|
||||
]);
|
||||
appState = AppState.idle;
|
||||
} catch (e) {
|
||||
appState = AppState.failed;
|
||||
}
|
||||
Future.delayed(Duration.zero, () {
|
||||
_getMainPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
void markChangeHandler(String type, int id, bool value) {
|
||||
content?.lists
|
||||
content.lists
|
||||
.firstWhere((element) => element.type == type)
|
||||
.contents
|
||||
.firstWhere((element) => element.id == id)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:didvan/views/widgets/skeleton_image.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
// import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class MainPageBanner extends StatelessWidget {
|
||||
final bool isFirst;
|
||||
|
|
@ -15,7 +16,7 @@ class MainPageBanner extends StatelessWidget {
|
|||
final state = context.read<MainPageState>();
|
||||
return DidvanSlider(
|
||||
itemBuilder: (context, index, realIndex) {
|
||||
final item = state.content!.banners[isFirst ? 0 : 1][index];
|
||||
final item = state.content.banners[isFirst ? 0 : 1][index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: GestureDetector(
|
||||
|
|
@ -29,7 +30,7 @@ class MainPageBanner extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
},
|
||||
itemCount: state.content!.banners[isFirst ? 0 : 1].length,
|
||||
itemCount: state.content.banners[isFirst ? 0 : 1].length,
|
||||
viewportFraction: 1,
|
||||
enableIndicator: true,
|
||||
height: (MediaQuery.of(context).size.width - 8) * 9.0 / 16.0,
|
||||
|
|
|
|||
|
|
@ -1,132 +0,0 @@
|
|||
import 'package:didvan/models/story_model.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class StorySection extends StatelessWidget {
|
||||
final List<UserStories> stories;
|
||||
|
||||
const StorySection({super.key, required this.stories});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 110.0,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
reverse: true,
|
||||
itemCount: stories.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final userStories = stories[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: _StoryCircle(
|
||||
userStories: userStories,
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.storyViewer,
|
||||
arguments: {
|
||||
'stories': stories,
|
||||
'tappedIndex': index,
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _StoryCircle extends StatelessWidget {
|
||||
final UserStories userStories;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _StoryCircle({required this.userStories, required this.onTap});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final allStoriesViewed = ValueNotifier<bool>(
|
||||
userStories.stories.every((story) => story.isViewed.value));
|
||||
|
||||
for (var story in userStories.stories) {
|
||||
story.isViewed.addListener(() {
|
||||
allStoriesViewed.value =
|
||||
userStories.stories.every((s) => s.isViewed.value);
|
||||
});
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ValueListenableBuilder<bool>(
|
||||
valueListenable: allStoriesViewed,
|
||||
builder: (context, isViewed, child) {
|
||||
return Container(
|
||||
width: 80.0,
|
||||
height: 80.0,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: isViewed
|
||||
? const LinearGradient(
|
||||
colors: [
|
||||
Color.fromARGB(255, 184, 184, 184),
|
||||
Color.fromARGB(255, 184, 184, 184)
|
||||
],
|
||||
)
|
||||
: const LinearGradient(
|
||||
colors: [
|
||||
Color.fromARGB(255, 27, 60, 79),
|
||||
Color.fromARGB(255, 27, 60, 79)
|
||||
],
|
||||
begin: Alignment.topRight,
|
||||
end: Alignment.bottomLeft,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: CircleAvatar(
|
||||
backgroundColor:
|
||||
const Color.fromARGB(255, 230, 242, 246),
|
||||
child: ClipOval(
|
||||
child: Image.asset(
|
||||
userStories.user
|
||||
.profileImageUrl,
|
||||
fit: BoxFit.cover,
|
||||
width: 50.0,
|
||||
height: 50.0,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return const Icon(Icons.person,
|
||||
color: Colors.grey, size: 40.0);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 6.0),
|
||||
Text(
|
||||
userStories.user.name,
|
||||
style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,407 +0,0 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:didvan/models/story_model.dart';
|
||||
import 'package:didvan/services/story_service.dart';
|
||||
import 'package:didvan/utils/date_time.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
// Main PageViewer to swipe between users
|
||||
class StoryViewerPage extends StatefulWidget {
|
||||
final List<UserStories> stories;
|
||||
final int tappedIndex;
|
||||
|
||||
const StoryViewerPage({
|
||||
super.key,
|
||||
required this.stories,
|
||||
required this.tappedIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
State<StoryViewerPage> createState() => _StoryViewerPageState();
|
||||
}
|
||||
|
||||
class _StoryViewerPageState extends State<StoryViewerPage> {
|
||||
late PageController _pageController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_pageController = PageController(initialPage: widget.tappedIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pageController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: PageView.builder(
|
||||
controller: _pageController,
|
||||
itemCount: widget.stories.length,
|
||||
itemBuilder: (context, index) {
|
||||
final userStories = widget.stories[index];
|
||||
return UserStoryViewer(
|
||||
key: ValueKey(userStories.user.name + index.toString()),
|
||||
userStories: userStories,
|
||||
onComplete: () {
|
||||
if (index < widget.stories.length - 1) {
|
||||
_pageController.nextPage(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
} else {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserStoryViewer extends StatefulWidget {
|
||||
final UserStories userStories;
|
||||
final VoidCallback onComplete;
|
||||
|
||||
const UserStoryViewer({
|
||||
super.key,
|
||||
required this.userStories,
|
||||
required this.onComplete,
|
||||
});
|
||||
|
||||
@override
|
||||
State<UserStoryViewer> createState() => _UserStoryViewerState();
|
||||
}
|
||||
|
||||
class _UserStoryViewerState extends State<UserStoryViewer>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
VideoPlayerController? _videoController;
|
||||
int _currentStoryIndex = 0;
|
||||
bool _isLongPressing = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(vsync: this);
|
||||
_loadStory(story: widget.userStories.stories.first);
|
||||
|
||||
_animationController.addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
_nextStory();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
_videoController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _loadStory({required StoryItem story}) {
|
||||
if (!story.isViewed.value) {
|
||||
StoryService.markStoryAsViewed(widget.userStories.id, story.id);
|
||||
story.isViewed.value = true;
|
||||
}
|
||||
|
||||
_animationController.stop();
|
||||
_animationController.reset();
|
||||
_videoController?.dispose();
|
||||
_videoController = null;
|
||||
|
||||
switch (story.media) {
|
||||
case MediaType.image:
|
||||
case MediaType.gif:
|
||||
_animationController.duration = story.duration;
|
||||
_animationController.forward();
|
||||
break;
|
||||
case MediaType.video:
|
||||
_videoController =
|
||||
VideoPlayerController.networkUrl(Uri.parse(story.url));
|
||||
_videoController!.initialize().then((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (_videoController!.value.isInitialized &&
|
||||
_videoController!.value.duration > Duration.zero) {
|
||||
_animationController.duration =
|
||||
_videoController!.value.duration;
|
||||
_videoController!.play();
|
||||
// _animationController.forward();
|
||||
} else {
|
||||
print(
|
||||
"Video failed to initialize or has zero duration. Skipping.");
|
||||
_nextStory();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catchError((error) {
|
||||
print("Error loading video: $error. Skipping.");
|
||||
if (mounted) {
|
||||
_nextStory();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _nextStory() {
|
||||
if (_currentStoryIndex < widget.userStories.stories.length - 1) {
|
||||
setState(() {
|
||||
_currentStoryIndex++;
|
||||
});
|
||||
_loadStory(story: widget.userStories.stories[_currentStoryIndex]);
|
||||
} else {
|
||||
widget.onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
void _previousStory() {
|
||||
if (_currentStoryIndex > 0) {
|
||||
setState(() {
|
||||
_currentStoryIndex--;
|
||||
});
|
||||
_loadStory(story: widget.userStories.stories[_currentStoryIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void _pauseStory() {
|
||||
_animationController.stop();
|
||||
_videoController?.pause();
|
||||
}
|
||||
|
||||
void _resumeStory() {
|
||||
_animationController.forward();
|
||||
_videoController?.play();
|
||||
}
|
||||
|
||||
void _handleTap(TapUpDetails details) {
|
||||
if (_isLongPressing) {
|
||||
_isLongPressing = false;
|
||||
_resumeStory();
|
||||
return;
|
||||
}
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
final double dx = details.globalPosition.dx;
|
||||
|
||||
if (dx > screenWidth / 2) {
|
||||
_nextStory();
|
||||
} else {
|
||||
_previousStory();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final story = widget.userStories.stories[_currentStoryIndex];
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
body: GestureDetector(
|
||||
onTapUp: _handleTap,
|
||||
onLongPressStart: (_) {
|
||||
_isLongPressing = true;
|
||||
_pauseStory();
|
||||
},
|
||||
onLongPressEnd: (_) {
|
||||
_isLongPressing = false;
|
||||
_resumeStory();
|
||||
},
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
_buildMediaViewer(story),
|
||||
_buildStoryHeader(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMediaViewer(StoryItem story) {
|
||||
switch (story.media) {
|
||||
case MediaType.image:
|
||||
return CachedNetworkImage(
|
||||
imageUrl: story.url,
|
||||
fit: BoxFit.cover,
|
||||
width: double.infinity,
|
||||
height: double.infinity);
|
||||
case MediaType.gif:
|
||||
return Image.network(story.url,
|
||||
fit: BoxFit.cover, width: double.infinity, height: double.infinity);
|
||||
case MediaType.video:
|
||||
if (_videoController?.value.isInitialized ?? false) {
|
||||
return FittedBox(
|
||||
fit: BoxFit.cover,
|
||||
child: SizedBox(
|
||||
width: _videoController!.value.size.width,
|
||||
height: _videoController!.value.size.height,
|
||||
child: VideoPlayer(_videoController!)));
|
||||
}
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildStoryHeader() {
|
||||
return Positioned(
|
||||
top: 35.0,
|
||||
left: 10.0,
|
||||
right: 10.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Row(
|
||||
children: widget.userStories.stories
|
||||
.asMap()
|
||||
.map((i, e) {
|
||||
return MapEntry(
|
||||
i,
|
||||
_AnimatedBar(
|
||||
animationController: _animationController,
|
||||
position: i,
|
||||
currentIndex: _currentStoryIndex,
|
||||
),
|
||||
);
|
||||
})
|
||||
.values
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: _UserInfo(user: widget.userStories.user),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AnimatedBar extends StatelessWidget {
|
||||
final AnimationController animationController;
|
||||
final int position;
|
||||
final int currentIndex;
|
||||
|
||||
const _AnimatedBar({
|
||||
required this.animationController,
|
||||
required this.position,
|
||||
required this.currentIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 1.5),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
height: 6.0,
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: position < currentIndex
|
||||
? Colors.white
|
||||
: Colors.white.withOpacity(0.5),
|
||||
border: Border.all(color: Colors.black26, width: 0.8),
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
),
|
||||
),
|
||||
if (position == currentIndex)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: AnimatedBuilder(
|
||||
animation: animationController,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
height: 6.0,
|
||||
width:
|
||||
constraints.maxWidth * animationController.value,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _UserInfo extends StatelessWidget {
|
||||
final User user;
|
||||
|
||||
const _UserInfo({required this.user});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
CircleAvatar(
|
||||
radius: 20.0,
|
||||
backgroundColor: Colors.grey[300],
|
||||
child: ClipOval(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
child: Image.asset(
|
||||
user.profileImageUrl,
|
||||
width: 40.0,
|
||||
height: 40.0,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return const Icon(Icons.person,
|
||||
color: Colors.grey, size: 40.0);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
user.name,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
DidvanText(
|
||||
DateTimeUtils.momentGenerator(user.createdAt),
|
||||
style: const TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, size: 30.0, color: Colors.white),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,8 @@ class AiBanner extends StatelessWidget {
|
|||
NativeWebViewLauncher.openWebView(
|
||||
'https://www.aisada.ir/app/page1.html');
|
||||
},
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Stack(
|
||||
children: [
|
||||
Icon(Icons.insert_comment_sharp),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -59,18 +58,18 @@ class DidvanBNB extends StatelessWidget {
|
|||
onTap: () => onTabChanged(1),
|
||||
),
|
||||
_NavBarItem(
|
||||
isSelected: false,
|
||||
isSelected: currentTabIndex == 2,
|
||||
title: 'هوشان',
|
||||
selectedIcon: DidvanIcons.ai_solid,
|
||||
unselectedIcon: DidvanIcons.ai_regular,
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.aiSection),
|
||||
onTap: () => onTabChanged(2),
|
||||
),
|
||||
_NavBarItem(
|
||||
isSelected: currentTabIndex == 2,
|
||||
isSelected: currentTabIndex == 3,
|
||||
title: 'آمار و داده',
|
||||
selectedIcon: DidvanIcons.stats__solid,
|
||||
unselectedIcon: DidvanIcons.stats__light,
|
||||
onTap: () => onTabChanged(2),
|
||||
onTap: () => onTabChanged(3),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class DidvanTextField extends StatefulWidget {
|
|||
final bool acceptSpace;
|
||||
final String? Function(String value)? validator;
|
||||
final TextInputType? textInputType;
|
||||
final TextInputAction? textInputAction;
|
||||
final TextInputAction? textInputAction; // پارامتر جدید
|
||||
final bool disableBorders;
|
||||
final bool isSmall;
|
||||
final int? maxLine;
|
||||
|
|
@ -38,7 +38,7 @@ class DidvanTextField extends StatefulWidget {
|
|||
this.initialValue,
|
||||
this.validator,
|
||||
this.textInputType,
|
||||
this.textInputAction,
|
||||
this.textInputAction, // اضافه کردن به سازنده
|
||||
this.textAlign,
|
||||
this.obsecureText = false,
|
||||
this.autoFocus = false,
|
||||
|
|
@ -111,13 +111,13 @@ class _DidvanTextFieldState extends State<DidvanTextField> {
|
|||
inputFormatters: <TextInputFormatter>[
|
||||
if (!widget.acceptSpace)
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp("[0-9a-zA-Z\u0600-\u06FF]")),
|
||||
RegExp("[0-9a-zA-Z]")),
|
||||
],
|
||||
autofocus: widget.autoFocus,
|
||||
obscureText: _hideContent,
|
||||
textAlign: widget.textAlign ?? TextAlign.start,
|
||||
keyboardType: widget.textInputType,
|
||||
textInputAction: widget.textInputAction,
|
||||
textInputAction: widget.textInputAction, // پاس دادن به TextFormField
|
||||
focusNode: _focusNode,
|
||||
controller: _controller,
|
||||
onFieldSubmitted: widget.onSubmitted,
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ flutter:
|
|||
- lib/assets/icons/
|
||||
- lib/assets/animations/
|
||||
- lib/assets/js/
|
||||
- lib/assets/icons/houshanNav/
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
|
|
|||