Repository: widget-js/widgets Branch: master Commit: a934b6864603 Files: 111 Total size: 331.0 KB Directory structure: gitextract_ovu0z3vr/ ├── .eslintcache ├── .github/ │ └── workflows/ │ └── github-page.yml ├── .gitignore ├── .npmrc ├── README.md ├── components.json ├── eslint.config.js ├── index.html ├── package.json ├── src/ │ ├── api/ │ │ ├── ai.ts │ │ ├── pay.ts │ │ ├── supabase.ts │ │ └── web-widget-api.ts │ ├── app.css │ ├── app.tsx │ ├── components/ │ │ ├── app-sidebar.tsx │ │ ├── dashboard-layout.tsx │ │ ├── login-check.tsx │ │ ├── manager/ │ │ │ ├── deployed-widget-card.tsx │ │ │ └── deployed-widget-list.tsx │ │ ├── nav-main.tsx │ │ ├── nav-user.tsx │ │ ├── purchase-dialog.tsx │ │ ├── setting-section.tsx │ │ ├── team-switcher.tsx │ │ ├── tray/ │ │ │ ├── social-links.tsx │ │ │ └── tray-menu-item.tsx │ │ ├── ui/ │ │ │ ├── alert-dialog.tsx │ │ │ ├── avatar.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── command.tsx │ │ │ ├── dialog.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── empty.tsx │ │ │ ├── field.tsx │ │ │ ├── input.tsx │ │ │ ├── item.tsx │ │ │ ├── label.tsx │ │ │ ├── pagination.tsx │ │ │ ├── popover.tsx │ │ │ ├── progress.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── sheet.tsx │ │ │ ├── sidebar.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── slider.tsx │ │ │ ├── sonner.tsx │ │ │ ├── spinner.tsx │ │ │ ├── switch.tsx │ │ │ ├── table.tsx │ │ │ ├── tabs.tsx │ │ │ ├── textarea.tsx │ │ │ └── tooltip.tsx │ │ ├── user-avatar.tsx │ │ └── widget-sync-item.tsx │ ├── hooks/ │ │ ├── use-app-broadcast.ts │ │ ├── use-app-language.ts │ │ ├── use-app-runtime-info.ts │ │ ├── use-cell-size-config.ts │ │ ├── use-debounce.ts │ │ ├── use-debug-config.ts │ │ ├── use-ipc-listener.ts │ │ ├── use-launch-at-startup-config.ts │ │ ├── use-mobile.ts │ │ ├── use-supabase-channel.ts │ │ ├── use-user.ts │ │ └── use-widget-package.ts │ ├── i18n/ │ │ ├── config.ts │ │ └── locales/ │ │ ├── en/ │ │ │ └── translation.json │ │ └── zh/ │ │ └── translation.json │ ├── index.css │ ├── lib/ │ │ ├── request.ts │ │ └── utils.ts │ ├── main.tsx │ ├── model/ │ │ └── app-version.ts │ ├── pages/ │ │ ├── add/ │ │ │ ├── add-widget-page.tsx │ │ │ └── components/ │ │ │ ├── feature-wall-list.tsx │ │ │ ├── search-item.tsx │ │ │ ├── widget-container.tsx │ │ │ ├── widget-tags.tsx │ │ │ └── zoom-image.tsx │ │ ├── ai/ │ │ │ └── ai-page.tsx │ │ ├── dev/ │ │ │ └── dev-page.tsx │ │ ├── error-page.tsx │ │ ├── packages/ │ │ │ ├── components/ │ │ │ │ └── widget-package-item.tsx │ │ │ └── widget-package-manager-page.tsx │ │ ├── settings/ │ │ │ ├── app-info-page.tsx │ │ │ ├── components/ │ │ │ │ ├── app-theme-form.tsx │ │ │ │ ├── font-family-picker.tsx │ │ │ │ ├── theme-preview.tsx │ │ │ │ └── theme-tags.tsx │ │ │ ├── general-page.tsx │ │ │ ├── proxy-page.tsx │ │ │ └── theme-page.tsx │ │ ├── size/ │ │ │ └── size-page.tsx │ │ ├── tray/ │ │ │ └── tray-page.tsx │ │ └── user/ │ │ └── profile-page.tsx │ ├── router/ │ │ └── index.tsx │ └── utils/ │ ├── version-utils.ts │ └── widget-util.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintcache ================================================ [{"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\pay.ts":"1","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\purchase-dialog.tsx":"2","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\ai\\ai-page.tsx":"3","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\eslint.config.js":"4","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\ai.ts":"5","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\supabase.ts":"6","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\web-widget-api.ts":"7","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\app.tsx":"8","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\app-sidebar.tsx":"9","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\dashboard-layout.tsx":"10","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\login-check.tsx":"11","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\manager\\deployed-widget-card.tsx":"12","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\manager\\deployed-widget-list.tsx":"13","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\nav-main.tsx":"14","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\nav-user.tsx":"15","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\setting-section.tsx":"16","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\team-switcher.tsx":"17","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\tray\\social-links.tsx":"18","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\tray\\tray-menu-item.tsx":"19","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\user-avatar.tsx":"20","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\widget-sync-item.tsx":"21","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-broadcast.ts":"22","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-language.ts":"23","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-runtime-info.ts":"24","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-cell-size-config.ts":"25","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-debounce.ts":"26","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-debug-config.ts":"27","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-ipc-listener.ts":"28","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-launch-at-startup-config.ts":"29","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-mobile.ts":"30","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-supabase-channel.ts":"31","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-user.ts":"32","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-widget-package.ts":"33","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\i18n\\config.ts":"34","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\lib\\request.ts":"35","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\lib\\utils.ts":"36","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\main.tsx":"37","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\model\\app-version.ts":"38","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\add-widget-page.tsx":"39","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\feature-wall-list.tsx":"40","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\search-item.tsx":"41","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\widget-container.tsx":"42","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\widget-tags.tsx":"43","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\zoom-image.tsx":"44","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\dev\\dev-page.tsx":"45","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\error-page.tsx":"46","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\packages\\components\\widget-package-item.tsx":"47","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\packages\\widget-package-manager-page.tsx":"48","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\app-info-page.tsx":"49","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\app-theme-form.tsx":"50","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\font-family-picker.tsx":"51","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\theme-preview.tsx":"52","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\theme-tags.tsx":"53","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\general-page.tsx":"54","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\proxy-page.tsx":"55","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\theme-page.tsx":"56","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\tray\\tray-page.tsx":"57","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\user\\profile-page.tsx":"58","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\router\\index.tsx":"59","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\utils\\version-utils.ts":"60","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\utils\\widget-util.ts":"61","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\vite.config.ts":"62","C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\size\\size-page.tsx":"63"},{"size":1300,"mtime":1775124929188,"results":"64","hashOfConfig":"65"},{"size":4878,"mtime":1775124610329,"results":"66","hashOfConfig":"65"},{"size":10222,"mtime":1775274604419,"results":"67","hashOfConfig":"65"},{"size":756,"mtime":1773145200570,"results":"68","hashOfConfig":"69"},{"size":1682,"mtime":1772368162180,"results":"70","hashOfConfig":"65"},{"size":515,"mtime":1771899559889,"results":"71","hashOfConfig":"65"},{"size":258,"mtime":1772368162182,"results":"72","hashOfConfig":"65"},{"size":682,"mtime":1773144567704,"results":"73","hashOfConfig":"65"},{"size":3763,"mtime":1772421333067,"results":"74","hashOfConfig":"65"},{"size":1636,"mtime":1773144571201,"results":"75","hashOfConfig":"65"},{"size":2640,"mtime":1772368162186,"results":"76","hashOfConfig":"65"},{"size":6005,"mtime":1772368162186,"results":"77","hashOfConfig":"65"},{"size":1484,"mtime":1772368162186,"results":"78","hashOfConfig":"65"},{"size":955,"mtime":1772368162186,"results":"79","hashOfConfig":"65"},{"size":2849,"mtime":1772368162186,"results":"80","hashOfConfig":"65"},{"size":550,"mtime":1772368162189,"results":"81","hashOfConfig":"65"},{"size":3101,"mtime":1772368162190,"results":"82","hashOfConfig":"65"},{"size":2660,"mtime":1772371236947,"results":"83","hashOfConfig":"65"},{"size":844,"mtime":1772368162192,"results":"84","hashOfConfig":"65"},{"size":658,"mtime":1772368162213,"results":"85","hashOfConfig":"65"},{"size":1696,"mtime":1772368162214,"results":"86","hashOfConfig":"65"},{"size":824,"mtime":1772368162216,"results":"87","hashOfConfig":"65"},{"size":1451,"mtime":1772368162217,"results":"88","hashOfConfig":"65"},{"size":856,"mtime":1772368162217,"results":"89","hashOfConfig":"65"},{"size":585,"mtime":1772368162218,"results":"90","hashOfConfig":"65"},{"size":392,"mtime":1772368162218,"results":"91","hashOfConfig":"65"},{"size":644,"mtime":1772368162219,"results":"92","hashOfConfig":"65"},{"size":606,"mtime":1772368162220,"results":"93","hashOfConfig":"65"},{"size":748,"mtime":1772368162221,"results":"94","hashOfConfig":"65"},{"size":584,"mtime":1772368162221,"results":"95","hashOfConfig":"65"},{"size":1550,"mtime":1772368162222,"results":"96","hashOfConfig":"65"},{"size":2933,"mtime":1772368162223,"results":"97","hashOfConfig":"65"},{"size":4035,"mtime":1772368162224,"results":"98","hashOfConfig":"65"},{"size":655,"mtime":1775274383807,"results":"99","hashOfConfig":"65"},{"size":804,"mtime":1772368162227,"results":"100","hashOfConfig":"65"},{"size":195,"mtime":1772368162227,"results":"101","hashOfConfig":"65"},{"size":315,"mtime":1772420673037,"results":"102","hashOfConfig":"65"},{"size":144,"mtime":1772368162233,"results":"103","hashOfConfig":"65"},{"size":6054,"mtime":1772368162234,"results":"104","hashOfConfig":"65"},{"size":766,"mtime":1772368162236,"results":"105","hashOfConfig":"65"},{"size":7667,"mtime":1775184463071,"results":"106","hashOfConfig":"65"},{"size":2709,"mtime":1773150161576,"results":"107","hashOfConfig":"65"},{"size":2019,"mtime":1772368162238,"results":"108","hashOfConfig":"65"},{"size":1010,"mtime":1773150362366,"results":"109","hashOfConfig":"65"},{"size":2604,"mtime":1773146651982,"results":"110","hashOfConfig":"65"},{"size":1051,"mtime":1772421315890,"results":"111","hashOfConfig":"65"},{"size":3208,"mtime":1772368162241,"results":"112","hashOfConfig":"65"},{"size":1534,"mtime":1772368162242,"results":"113","hashOfConfig":"65"},{"size":5656,"mtime":1772368162242,"results":"114","hashOfConfig":"65"},{"size":9310,"mtime":1775013855943,"results":"115","hashOfConfig":"65"},{"size":5502,"mtime":1775013918653,"results":"116","hashOfConfig":"65"},{"size":5771,"mtime":1774959028330,"results":"117","hashOfConfig":"65"},{"size":6422,"mtime":1775013672434,"results":"118","hashOfConfig":"65"},{"size":4458,"mtime":1772368162257,"results":"119","hashOfConfig":"65"},{"size":4277,"mtime":1772368162258,"results":"120","hashOfConfig":"65"},{"size":6389,"mtime":1775012528499,"results":"121","hashOfConfig":"65"},{"size":7144,"mtime":1772368162260,"results":"122","hashOfConfig":"65"},{"size":7541,"mtime":1772368162261,"results":"123","hashOfConfig":"65"},{"size":3831,"mtime":1775356510301,"results":"124","hashOfConfig":"65"},{"size":1109,"mtime":1772368162264,"results":"125","hashOfConfig":"65"},{"size":984,"mtime":1772368162265,"results":"126","hashOfConfig":"65"},{"size":447,"mtime":1772368162268,"results":"127","hashOfConfig":"128"},{"size":4664,"mtime":1775443912214,"results":"129","hashOfConfig":"65"},{"filePath":"130","messages":"131","suppressedMessages":"132","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"6w5kbo",{"filePath":"133","messages":"134","suppressedMessages":"135","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"136","messages":"137","suppressedMessages":"138","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"139","messages":"140","suppressedMessages":"141","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"hzg01x",{"filePath":"142","messages":"143","suppressedMessages":"144","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"145","messages":"146","suppressedMessages":"147","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"148","messages":"149","suppressedMessages":"150","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"151","messages":"152","suppressedMessages":"153","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"154","messages":"155","suppressedMessages":"156","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"157","messages":"158","suppressedMessages":"159","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"160","messages":"161","suppressedMessages":"162","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"163","messages":"164","suppressedMessages":"165","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"166","messages":"167","suppressedMessages":"168","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"169","messages":"170","suppressedMessages":"171","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"172","messages":"173","suppressedMessages":"174","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"175","messages":"176","suppressedMessages":"177","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"178","messages":"179","suppressedMessages":"180","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"181","messages":"182","suppressedMessages":"183","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"184","messages":"185","suppressedMessages":"186","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"187","messages":"188","suppressedMessages":"189","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"190","messages":"191","suppressedMessages":"192","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"193","messages":"194","suppressedMessages":"195","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"196","messages":"197","suppressedMessages":"198","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"199","messages":"200","suppressedMessages":"201","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"202","messages":"203","suppressedMessages":"204","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"205","messages":"206","suppressedMessages":"207","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"208","messages":"209","suppressedMessages":"210","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"211","messages":"212","suppressedMessages":"213","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"214","messages":"215","suppressedMessages":"216","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"217","messages":"218","suppressedMessages":"219","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"220","messages":"221","suppressedMessages":"222","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"223","messages":"224","suppressedMessages":"225","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"226","messages":"227","suppressedMessages":"228","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"229","messages":"230","suppressedMessages":"231","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"232","messages":"233","suppressedMessages":"234","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"235","messages":"236","suppressedMessages":"237","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"238","messages":"239","suppressedMessages":"240","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"241","messages":"242","suppressedMessages":"243","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"244","messages":"245","suppressedMessages":"246","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"247","messages":"248","suppressedMessages":"249","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"250","messages":"251","suppressedMessages":"252","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"253","messages":"254","suppressedMessages":"255","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"256","messages":"257","suppressedMessages":"258","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"259","messages":"260","suppressedMessages":"261","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"262","messages":"263","suppressedMessages":"264","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"265","messages":"266","suppressedMessages":"267","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"268","messages":"269","suppressedMessages":"270","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"271","messages":"272","suppressedMessages":"273","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"274","messages":"275","suppressedMessages":"276","errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"277","messages":"278","suppressedMessages":"279","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"280","messages":"281","suppressedMessages":"282","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"283","messages":"284","suppressedMessages":"285","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"286","messages":"287","suppressedMessages":"288","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"289","messages":"290","suppressedMessages":"291","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"292","messages":"293","suppressedMessages":"294","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"295","messages":"296","suppressedMessages":"297","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"298","messages":"299","suppressedMessages":"300","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"301","messages":"302","suppressedMessages":"303","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"304","messages":"305","suppressedMessages":"306","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"307","messages":"308","suppressedMessages":"309","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"310","messages":"311","suppressedMessages":"312","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"313","messages":"314","suppressedMessages":"315","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"19g2b6m",{"filePath":"316","messages":"317","suppressedMessages":"318","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\pay.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\purchase-dialog.tsx",["319","320","321"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\ai\\ai-page.tsx",["322","323"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\eslint.config.js",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\ai.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\supabase.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\api\\web-widget-api.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\app.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\app-sidebar.tsx",["324"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\dashboard-layout.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\login-check.tsx",["325"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\manager\\deployed-widget-card.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\manager\\deployed-widget-list.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\nav-main.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\nav-user.tsx",["326"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\setting-section.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\team-switcher.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\tray\\social-links.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\tray\\tray-menu-item.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\user-avatar.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\components\\widget-sync-item.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-broadcast.ts",["327","328"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-language.ts",["329"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-app-runtime-info.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-cell-size-config.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-debounce.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-debug-config.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-ipc-listener.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-launch-at-startup-config.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-mobile.ts",["330"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-supabase-channel.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-user.ts",["331","332","333"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\hooks\\use-widget-package.ts",["334","335","336"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\i18n\\config.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\lib\\request.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\lib\\utils.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\main.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\model\\app-version.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\add-widget-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\feature-wall-list.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\search-item.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\widget-container.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\widget-tags.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\add\\components\\zoom-image.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\dev\\dev-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\error-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\packages\\components\\widget-package-item.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\packages\\widget-package-manager-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\app-info-page.tsx",["337","338","339","340"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\app-theme-form.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\font-family-picker.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\theme-preview.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\components\\theme-tags.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\general-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\proxy-page.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\settings\\theme-page.tsx",["341","342"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\tray\\tray-page.tsx",["343"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\user\\profile-page.tsx",["344","345"],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\router\\index.tsx",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\utils\\version-utils.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\utils\\widget-util.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\vite.config.ts",[],[],"C:\\Users\\rtuge\\Desktop\\workspace\\widgetjs\\packages\\widgets\\src\\pages\\size\\size-page.tsx",[],[],{"ruleId":"346","severity":1,"message":"347","line":56,"column":6,"nodeType":"348","endLine":56,"endColumn":13,"suggestions":"349"},{"ruleId":"350","severity":1,"message":"351","line":98,"column":7,"nodeType":"352","messageId":"353","endLine":98,"endColumn":21},{"ruleId":"346","severity":1,"message":"354","line":100,"column":6,"nodeType":"348","endLine":100,"endColumn":23,"suggestions":"355"},{"ruleId":"346","severity":1,"message":"356","line":63,"column":6,"nodeType":"348","endLine":63,"endColumn":12,"suggestions":"357"},{"ruleId":"346","severity":1,"message":"358","line":87,"column":6,"nodeType":"348","endLine":87,"endColumn":18,"suggestions":"359"},{"ruleId":"360","severity":1,"message":"361","line":102,"column":27,"nodeType":"362","messageId":"353","endLine":102,"endColumn":32},{"ruleId":"350","severity":1,"message":"363","line":29,"column":24,"nodeType":"352","messageId":"353","endLine":29,"endColumn":50},{"ruleId":"350","severity":1,"message":"363","line":35,"column":24,"nodeType":"352","messageId":"353","endLine":35,"endColumn":50},{"ruleId":"346","severity":1,"message":"364","line":21,"column":6,"nodeType":"348","endLine":21,"endColumn":30,"suggestions":"365"},{"ruleId":"346","severity":1,"message":"366","line":21,"column":7,"nodeType":"352","endLine":21,"endColumn":29},{"ruleId":"346","severity":1,"message":"367","line":21,"column":6,"nodeType":"348","endLine":21,"endColumn":8,"suggestions":"368"},{"ruleId":"350","severity":1,"message":"369","line":14,"column":5,"nodeType":"352","messageId":"353","endLine":14,"endColumn":55},{"ruleId":"350","severity":1,"message":"370","line":67,"column":7,"nodeType":"352","messageId":"353","endLine":67,"endColumn":26},{"ruleId":"350","severity":1,"message":"371","line":76,"column":5,"nodeType":"352","messageId":"353","endLine":76,"endColumn":21},{"ruleId":"350","severity":1,"message":"371","line":81,"column":7,"nodeType":"352","messageId":"353","endLine":81,"endColumn":24},{"ruleId":"350","severity":1,"message":"372","line":43,"column":7,"nodeType":"352","messageId":"353","endLine":43,"endColumn":57},{"ruleId":"350","severity":1,"message":"373","line":44,"column":7,"nodeType":"352","messageId":"353","endLine":44,"endColumn":55},{"ruleId":"346","severity":1,"message":"374","line":126,"column":6,"nodeType":"348","endLine":126,"endColumn":34,"suggestions":"375"},{"ruleId":"350","severity":1,"message":"371","line":23,"column":5,"nodeType":"352","messageId":"353","endLine":23,"endColumn":21},{"ruleId":"350","severity":1,"message":"376","line":24,"column":5,"nodeType":"352","messageId":"353","endLine":24,"endColumn":19},{"ruleId":"350","severity":1,"message":"377","line":25,"column":5,"nodeType":"352","messageId":"353","endLine":25,"endColumn":24},{"ruleId":"350","severity":1,"message":"378","line":26,"column":5,"nodeType":"352","messageId":"353","endLine":26,"endColumn":28},{"ruleId":"379","severity":1,"message":"380","line":60,"column":54,"nodeType":"381","messageId":"353","endLine":60,"endColumn":68},{"ruleId":"382","severity":1,"message":"383","line":63,"column":9,"nodeType":"362","messageId":"384","endLine":63,"endColumn":19},{"ruleId":"350","severity":1,"message":"363","line":37,"column":24,"nodeType":"352","messageId":"353","endLine":37,"endColumn":50},{"ruleId":"350","severity":1,"message":"385","line":43,"column":21,"nodeType":"352","messageId":"353","endLine":43,"endColumn":46},{"ruleId":"350","severity":1,"message":"386","line":44,"column":19,"nodeType":"352","messageId":"353","endLine":44,"endColumn":40},"react-hooks/exhaustive-deps","React Hook useEffect has missing dependencies: 'onOpenChange' and 'onSuccess'. Either include them or remove the dependency array. If 'onOpenChange' changes too often, find the parent component that defines it and wrap that definition in useCallback.","ArrayExpression",["387"],"react-hooks-extra/no-direct-set-state-in-use-effect","Do not call the 'set' function 'setOrder' of 'useState' directly in 'useEffect'.","CallExpression","default","React Hook useEffect has a missing dependency: 'initPurchase'. Either include it or remove the dependency array.",["388"],"React Hook useEffect has a missing dependency: 'loadPackages'. Either include it or remove the dependency array.",["389"],"React Hook useEffect has a missing dependency: 'loadHistory'. Either include it or remove the dependency array.",["390"],"react/no-array-index-key","Do not use item index in the array as its key.","Identifier","Do not call the 'set' function 'setLoginState' of 'useState' directly in 'useEffect'.","React Hook useEffect has a missing dependency: 'events'. Either include it or remove the dependency array.",["391"],"React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.","React Hook useEffect has a missing dependency: 'options'. Either include it or remove the dependency array.",["392"],"Do not call the 'set' function 'setIsMobile' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setUser' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setLoading' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setUpgradable' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setUpgrading' of 'useState' directly in 'useEffect'.","React Hook useCallback has a missing dependency: 't'. Either include it or remove the dependency array.",["393"],"Do not call the 'set' function 'setError' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setAppVersion' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setHasNewVersion' of 'useState' directly in 'useEffect'.","react/prefer-use-state-lazy-initialization","To prevent re-computation, consider using lazy initial state for useState calls that involve function calls. Ex: 'useState(() => getValue())'.","NewExpression","react-naming-convention/ref-name","A ref identifier must be named 'ref' or ending in 'Ref'.","invalidRefName","Do not call the 'set' function 'setNicknameEdit' of 'useState' directly in 'useEffect'.","Do not call the 'set' function 'setAvatarEdit' of 'useState' directly in 'useEffect'.",{"desc":"394","fix":"395"},{"desc":"396","fix":"397"},{"desc":"398","fix":"399"},{"desc":"400","fix":"401"},{"desc":"402","fix":"403"},{"desc":"404","fix":"405"},{"desc":"406","fix":"407"},"Update the dependencies array to be: [onOpenChange, onSuccess, order]",{"range":"408","text":"409"},"Update the dependencies array to be: [initPurchase, open, productId]",{"range":"410","text":"411"},"Update the dependencies array to be: [loadPackages, user]",{"range":"412","text":"413"},"Update the dependencies array to be: [loadHistory, page, user]",{"range":"414","text":"415"},"Update the dependencies array to be: [events]",{"range":"416","text":"417"},"Update the dependencies array to be: [options]",{"range":"418","text":"419"},"Update the dependencies array to be: [packageName, remoteUrlInfo, t]",{"range":"420","text":"421"},[1683,1690],"[onOpenChange, onSuccess, order]",[2691,2708],"[initPurchase, open, productId]",[1731,1737],"[loadPackages, user]",[2253,2265],"[loadHistory, page, user]",[600,624],"[events]",[727,729],"[options]",[3909,3937],"[packageName, remoteUrlInfo, t]"] ================================================ FILE: .github/workflows/github-page.yml ================================================ # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs name: Deploy CI permissions: id-token: write pages: write on: push: branches: [ "master" ] pull_request: branches: [ "master" ] jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: node-version: '22.x' - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 8 - name: Build static files id: build run: | pnpm install pnpm run build - name: Upload static files as artifact id: deployment uses: actions/upload-pages-artifact@v3 with: path: dist/ deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* node_modules dist dist-ssr *.local # Editor directories and files .vscode/* !.vscode/extensions.json .idea .DS_Store *.suo *.ntvs* *.njsproj *.sln *.sw? ================================================ FILE: .npmrc ================================================ #proxy=http://127.0.0.1:7890 ================================================ FILE: README.md ================================================

Widgets - Capable and ergonomic widgets.
桌面组件

Chat bilibili Feedback discord

![png](screenshot/screenshot.jpg) ![png](https://github.com/rtugeek/stock/raw/master/public/screenshot.png) ## 🔗预览所有组件 https://widget-js.github.io/widgets/#/ ![png](screenshot/react.png) ## 📖说明 这是桌面组件前端开源组件,项目还在持续完善中 Windows 10/11 客户端下载地址: - https://www.microsoft.com/store/productId/9NPR50GQ7T53 - https://widgetjs.cn ## ▶️运行项目 1. 下载并运行桌面组件客户端 2. 克隆代码 ```shell git clone https://github.com/widget-js/widget.git ``` 3. 到项目目录下载依赖 ```shell pnpm run install ``` 4. 运行 ```shell pnpm run dev ``` ## 📋组件列表 ### AI组件包 https://github.com/rtugeek/ai ### 一键呼出AI DeepSeek/ChatGPT/Gemini ![png](https://raw.githubusercontent.com/rtugeek/ai/refs/heads/master/screenshot/ai.png) ### 监控组件包 | 监控组件包 | |:------------------------------------------------------------------------------------------------------------------:| | ![监控面板](https://github.com/rtugeek/monitor/blob/master/public/image/preview_base_panel.png?raw=true)
监控面板 | | ![监控面板](https://github.com/rtugeek/monitor/blob/master/public/image/preview_energy_label.png?raw=true)
打工能耗标签 | | ![监控面板](https://github.com/rtugeek/monitor/blob/master/public/image/preview_server.png?raw=true)
服务器监控面板 | ### 默认组件包 | 默认组件包 | https://github.com/widget-js/widgets | |:-----:|:--------------------------------------------------------------------------------------------------------:| | 倒计时 | ![gif](screenshot/widget_countdown.png) | | 灵动通知 | ![gif](screenshot/dynamic_island.gif) | | 打工进度 | ![screenshot/labor_progress.gif](screenshot/labor_progress.gif) | | 时间进度 | | ### 文件夹 https://github.com/rtugeek/grid ![png](https://raw.githubusercontent.com/rtugeek/grid/refs/heads/master/public/preview_grid.png) ### iTime组件包 | iTime组件包 | https://github.com/rtugeek/itime-web | |:--------:|:-------------------------------------------------------------------------------------------------------------------:| | 待办事项 | ![image](https://raw.githubusercontent.com/rtugeek/itime-web/refs/heads/master/public/images/preview_todo_list.png) | | Deadline | ![gif](https://raw.githubusercontent.com/rtugeek/itime-web/refs/heads/master/public/images/preview_deadline.png) | | 番茄钟 | ![gif](https://raw.githubusercontent.com/rtugeek/itime-web/refs/heads/master/public/images/preview_pomodoro.png) | | 日历 | ![gif](https://raw.githubusercontent.com/rtugeek/itime-web/refs/heads/master/public/images/preview_calendar.png) | ### 剪切板组件包 | 剪切板组件包 | https://github.com/rtugeek/clipboard | |:------:|:------------------------------------------------------------------------------------------------------------:| | 剪切板 | ![Clipboard](https://raw.githubusercontent.com/rtugeek/clipboard/master/public/images/preview_clipboard.png) | ### 天气组件包 | 天气组件包 | https://github.com/rtugeek/weather | |:-----:|:------------------------------------------------------------------------------------------:| | 2x2 | ![2x2](https://raw.githubusercontent.com/rtugeek/weather/master/public/preview_small.png) | | 4x2 | ![4x2](https://raw.githubusercontent.com/rtugeek/weather/master/public/preview_medium.png) | | 4x4 | ![4x4](https://raw.githubusercontent.com/rtugeek/weather/master/public/preview_large.png) | ### 热点组件包 | 热点组件包 | https://github.com/widget-js/hotspot | |:------------------------------------------------------------------------------------------------------------------:|-------------------------------------------------------------------------------------------------------------| | ![bilibili](https://raw.githubusercontent.com/widget-js/hotspot/master/public/images/bilibili_hot_search.png) | ![weibo.png](https://raw.githubusercontent.com/widget-js/hotspot/master/public/images/weibo_hot_search.png) | | ![douyin](https://raw.githubusercontent.com/widget-js/hotspot/master/public/images/preview_douyin.png) | ![zhihu.png](https://raw.githubusercontent.com/widget-js/hotspot/master/public/images/preview_zhihu.png) | | ![douyin](https://raw.githubusercontent.com/widget-js/hotspot/master/public/images/preview_bangumi.png)
追番助手 | | ### 时钟组件包 | 时钟组件包 | https://github.com/rtugeek/clock | |:-------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------:| | ![Flip Clock](https://raw.githubusercontent.com/rtugeek/clock/master/public/images/preview_flip_clock.png)
翻页时钟 | ![Clock](https://raw.githubusercontent.com/rtugeek/clock/master/public/images/preview_clock.png)
时钟 | | ![Glitch Clock](https://raw.githubusercontent.com/rtugeek/clock/master/public/images/preview_glitch_clock.png)
故障时钟 | ![Micky Clock](https://raw.githubusercontent.com/rtugeek/clock/master/public/images/preview_micky_clock.png)
米奇时钟 | ### 相册组件包 | 相册组件包 | https://github.com/rtugeek/photo | |:---------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------:| | ![大头贴](https://raw.githubusercontent.com/rtugeek/photo/master/public/images/preview_sticker.png)
大头贴 | ![Clock](https://raw.githubusercontent.com/rtugeek/photo/master/public/images/preview_photo.png)
轮播相册 | ### 趣味组件包 | 趣味组件包 | https://github.com/rtugeek/fun | |:-------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------:| | ![电子木鱼](https://raw.githubusercontent.com/rtugeek/fun/master/public/images/preview_wooden_fish.png)
电子木鱼 | ![preview_hitler.png](https://raw.githubusercontent.com/rtugeek/fun/refs/heads/master/public/images/preview_hitler.png)
仪表盘 | ================================================ FILE: components.json ================================================ { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": false, "tsx": true, "tailwind": { "config": "", "css": "src/index.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "iconLibrary": "lucide", "rtl": false, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": {} } ================================================ FILE: eslint.config.js ================================================ import antfu from '@antfu/eslint-config' export default antfu({ type: 'lib', stylistic: { indent: 2, // 4, or 'tab' quotes: 'single', // or 'double' }, typescript: true, react: true, jsx: true, vue: false, jsonc: false, yaml: false, markdown: false, ignores: [ '**/fixtures', 'src/components/ui/**', ], rules: { 'curly': ['error', 'multi-line'], 'no-use-before-define': 'off', 'eqeqeq': 'off', 'unused-imports/no-unused-vars': ['error', { caughtErrors: 'none', argsIgnorePattern: '^_', varsIgnorePattern: '^_', }], 'ts/explicit-function-return-type': 'off', 'style/max-statements-per-line': ['error', { max: 2, }], }, }) ================================================ FILE: index.html ================================================ Widget Hub
================================================ FILE: package.json ================================================ { "name": "@widget-js/react-app", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc -b && vite build", "preview": "vite preview", "lint": "eslint --cache .", "lint:fix": "eslint --cache . --fix", "prepare": "simple-git-hooks" }, "dependencies": { "@icons-pack/react-simple-icons": "^13.11.2", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-popover": "^1.1.15", "@supabase/auth-js": "^2.86.0", "@supabase/supabase-js": "^2.84.0", "@tailwindcss/vite": "^4.2.0", "@uiw/react-color": "^2.9.5", "@widget-js/core": "latest", "@widget-js/react": "latest", "@widget-js/web-api": "24.1.1-beta.70", "axios": "^1.13.5", "baseline-browser-mapping": "^2.10.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "consola": "^3.4.2", "driver.js": "^1.4.0", "framer-motion": "^12.34.3", "i18next": "^25.8.13", "i18next-browser-languagedetector": "^8.2.1", "lucide-react": "^0.575.0", "next-themes": "^0.4.6", "qrcode.react": "^4.2.0", "radix-ui": "^1.4.3", "react": "^19.2.0", "react-dom": "^19.2.0", "react-dropzone": "^15.0.0", "react-i18next": "^16.5.4", "react-medium-image-zoom": "^5.4.1", "react-router-dom": "^7.1.5", "react-use": "^17.6.0", "semver": "^7.7.4", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "tailwindcss": "^4.2.0" }, "devDependencies": { "@antfu/eslint-config": "^7.6.1", "@eslint-react/eslint-plugin": "^2.13.0", "@types/node": "^24.10.13", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "@types/semver": "^7.7.1", "@vitejs/plugin-react": "^5.1.1", "@widget-js/vite-plugin-widget": "24.1.1-beta.72", "eslint": "^10.0.2", "eslint-plugin-format": "^2.0.1", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.26", "eslint-plugin-unicorn": "^63.0.0", "globals": "^16.5.0", "lint-staged": "^16.3.0", "shadcn": "^3.8.5", "simple-git-hooks": "^2.13.1", "tw-animate-css": "^1.4.0", "typescript": "~5.9.3", "vite": "^7.3.1" }, "simple-git-hooks": { "pre-commit": "npx lint-staged" }, "lint-staged": { "*.{js,ts,tsx,vue,md}": [ "eslint --cache --fix" ] } } ================================================ FILE: src/api/ai.ts ================================================ import request from '@/lib/request' export interface AiTokenHistory { id: string user_id: string change_amount: number token_remain_after: number | null model: string | null prompt_tokens: number | null completion_tokens: number | null total_tokens: number | null cost: number | null request_type: string | null input_token_details: any | null output_token_details: any | null raw_usage: any | null related_id: string | null remark: string | null create_time: string sourcePackage?: string | null sourcePackageName?: string | null } export interface AiTokenPackage { id: string name: string userId: string maxToken: number usedToken: number expireTime: string | null createTime: string productId: number | null enable: boolean | null updateTime: string | null } interface PaginationResult { data: T[] page: string | number pageSize: string | number totalPage: number total: number } export const AiApi = { async getPackages(params?: { page?: number, limit?: number }): Promise<{ items: AiTokenPackage[], total: number }> { const res = await request.get('/ai/package', { params }) const data = res as unknown as PaginationResult return { items: data.data, total: data.total, } }, async getUsage(params?: { page?: number, limit?: number }): Promise<{ items: AiTokenHistory[], total: number }> { const res = await request.get('/ai/usage', { params }) const data = res as unknown as PaginationResult return { items: data.data, total: data.total, } }, } ================================================ FILE: src/api/pay.ts ================================================ import request from '@/lib/request' export interface PayVirtualProduct { id: number createTime: string updateTime: string | null name: string description: string | null coverUrl: string | null price: number category: string metadata: string | null enable: boolean } export interface WxOrderResult { codeUrl: string product: PayVirtualProduct orderId: string } export interface AlipayOrderResult { orderId: string product: PayVirtualProduct form: string } export const PayApi = { async getProducts(category: string = 'ai'): Promise { return request.get('https://widgetjs.cn/pay/products', { params: { category }, }) }, async createWxOrder(productId: number): Promise { return request.get('https://widgetjs.cn/pay/wx/order', { params: { productId }, }) }, async createAlipayOrder(productId: number, returnUrl: string = 'https://widgetjs.cn'): Promise { return request.post('https://widgetjs.cn/pay/alipay/order/page', null, { params: { productId, returnUrl }, }) }, async getAlipayUrl(orderId: string): Promise { return `https://widgetjs.cn/pay/alipay/order/page?orderId=${orderId}` }, } ================================================ FILE: src/api/supabase.ts ================================================ import { createClient } from '@supabase/supabase-js' const anonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzY0MDAwMDAwLCJleHAiOjE5MjE3NjY0MDB9.3nGFAW2q2bzxWmx1T-ycnmklITh9OcEvA1kZPXz4dBs' const supabaseUrl = 'https://supabase.widgetjs.cn' const supabase = createClient(supabaseUrl, anonKey) function getStorageLink(fullPath: string) { return `https://supabase.widgetjs.cn/storage/v1/object/public/${fullPath}` } export { getStorageLink, supabase } ================================================ FILE: src/api/web-widget-api.ts ================================================ import type { WidgetSearchOptions } from '@widget-js/web-api' import request from '@/lib/request' export const WebWidgetApi = { search: (options: WidgetSearchOptions) => { return request.get('/widget', { params: options, }) }, } ================================================ FILE: src/app.css ================================================ /* App.css cleared for Tailwind compatibility */ *{ /*user-select: none;*/ } /* Global Scrollbar Styling matching src/components/ui/scroll-area.tsx */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background-color: var(--border); border-radius: 9999px; border: 1px solid transparent; background-clip: content-box; } ::-webkit-scrollbar-corner { background: transparent; } ================================================ FILE: src/app.tsx ================================================ import consola from 'consola' import { useTranslation } from 'react-i18next' import { RouterProvider } from 'react-router-dom' import { useAppLanguage } from './hooks/use-app-language' import { router } from './router' import '@widget-js/react/style.css' import './app.css' function App() { const { i18n } = useTranslation() useAppLanguage({ onLoad: (lang) => { consola.log('App language loaded:', lang) i18n.changeLanguage(lang) }, onChange: (lang) => { consola.log('App language onChange:', lang) i18n.changeLanguage(lang) }, }) return ( ) } export default App ================================================ FILE: src/components/app-sidebar.tsx ================================================ 'use client' import { User, } from 'lucide-react' import * as React from 'react' import { useTranslation } from 'react-i18next' import { useLocation, useNavigate } from 'react-router-dom' import logo from '@/assets/images/logo.png' import { NavMain } from '@/components/nav-main' import { NavUser } from '@/components/nav-user' import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarRail, } from '@/components/ui/sidebar' import { useAppRuntimeInfo } from '@/hooks/use-app-runtime-info' import { useUser } from '@/hooks/use-user' import { routes } from '@/router' interface RouteHandle { title: string icon?: any sidebarGroup?: boolean sidebarMenu?: boolean } export function AppSidebar({ ...props }: React.ComponentProps) { const { t } = useTranslation() const location = useLocation() const navigate = useNavigate() const { simpleInfo } = useAppRuntimeInfo() const { user, nickname, avatar } = useUser() const userData = { name: nickname, email: user?.email ?? '', avatar: user ? (avatar || logo) : undefined, icon: !user ? User : undefined, } const rootRoute = routes[0] const sidebarGroups = rootRoute.children ?.filter(route => (route.handle as RouteHandle | undefined)?.sidebarGroup) .map((route) => { const handle = route.handle as RouteHandle // Handle nested routes logic const groupPath = route.path === '/' ? '' : route.path || '' const items = route.children ?.filter(child => (child.handle as RouteHandle | undefined)?.sidebarMenu) .map((child) => { const childHandle = child.handle as RouteHandle // Handle child path: '/' as root of group const childPath = child.path === '/' ? '' : child.path || '' const url = `/${groupPath}${childPath ? `/${childPath}` : ''}`.replace(/\/+/g, '/') return { title: t(childHandle.title), url, icon: childHandle.icon, isActive: location.pathname === url, } }) || [] return { label: t(handle.title), items, } }) || [] return ( <> navigate('/setting/info')} className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" >
Widget Hub
{t('sidebar.widgetHub')} {(simpleInfo?.app as any)?.version ?? (simpleInfo?.app ? String(simpleInfo.app) : t('sidebar.loading'))}
{sidebarGroups.map((group, index) => ( ))}
) } ================================================ FILE: src/components/dashboard-layout.tsx ================================================ import { WindowControls } from '@widget-js/react' import { useTranslation } from 'react-i18next' import { Outlet, useMatches } from 'react-router-dom' import { AppSidebar } from '@/components/app-sidebar' import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbPage, } from '@/components/ui/breadcrumb' import { SidebarInset, SidebarProvider, } from '@/components/ui/sidebar' export function DashboardLayout() { const { t } = useTranslation() const matches = useMatches() // Get title from the last match that has a handle with a title const currentMatch = matches.findLast(match => (match.handle as any)?.title) const titleKey = (currentMatch?.handle as any)?.title const title = titleKey ? t(titleKey) : t('dashboard.dashboard') return (
{title}
) } ================================================ FILE: src/components/login-check.tsx ================================================ import { BrowserWindowApi, NotificationApi } from '@widget-js/core' import consola from 'consola' import { Lock } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' import { supabase } from '@/api/supabase' import { Button } from '@/components/ui/button' import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from '@/components/ui/empty' import { useSupabaseChannel } from '@/hooks/use-supabase-channel' import { useUser } from '@/hooks/use-user' interface LoginCheckProps { children: React.ReactNode } export function LoginCheck({ children }: LoginCheckProps) { const { user, loading: userLoading } = useUser() const [loginState, setLoginState] = useState('') useEffect(() => { const storedState = localStorage.getItem('wechat_login_state') if (storedState) { setLoginState(storedState) } }, []) // Handle Supabase channel for login useSupabaseChannel(loginState ? `wechat-login-${loginState}` : '', async (payload: any) => { consola.info(payload) const currentSession = payload.payload.session const loginRes = await supabase.auth.setSession(currentSession) if (loginRes.error) { NotificationApi.error(loginRes.error.message) } else { toast.success('登录成功') } }) const handleLogin = () => { const newState = crypto.randomUUID().replace(/-/g, '') setLoginState(newState) localStorage.setItem('wechat_login_state', newState) BrowserWindowApi.openUrl(`https://open.weixin.qq.com/connect/qrconnect?appid=wxf91b19da281f23a9&redirect_uri=https%3A%2F%2Fwidgetjs.cn%2Fapi%2Fv1%2Fuser%2Flogin%2Fwechat%2Fcallback&response_type=code&scope=snsapi_login&state=${newState}#wechat_redirect`, { width: 800, height: 600, frame: true, transparent: false, titleBarStyle: 'default', }) } if (!user && !userLoading) { return (
需要登录 请先登录账号以继续使用
) } return <>{children} } ================================================ FILE: src/components/manager/deployed-widget-card.tsx ================================================ import type { DeployedWidget, Widget } from '@widget-js/core' import { DeployedWidgetApi, WidgetApi } from '@widget-js/core' import { Code, RefreshCw, Settings, X } from 'lucide-react' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' import { Card, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip' import { useDebugConfig } from '@/hooks/use-debug-config' interface DeployedWidgetCardProps { deployedWidget: DeployedWidget onRemove: (widget: DeployedWidget) => void } export function DeployedWidgetCard({ deployedWidget, onRemove }: DeployedWidgetCardProps) { const { t, i18n } = useTranslation() const [widget, setWidget] = useState() const [ignoreMouseEvents, setIgnoreMouseEvents] = useState(deployedWidget.isIgnoreMouseEvents ?? false) const [isDebugMode] = useDebugConfig() useEffect(() => { WidgetApi.getWidget(deployedWidget.name).then(setWidget) }, [deployedWidget.name]) const getLocalizedText = (text: any) => { if (typeof text === 'string') { return text } if (!text) { return '' } return text[i18n.language] || text['zh-CN'] || Object.values(text)[0] || '' } const openSettings = () => { if (widget?.configPagePath) { DeployedWidgetApi.openConfigPage(deployedWidget.id) } } const openDevTools = () => { DeployedWidgetApi.openDevTools(deployedWidget.id) } const refresh = () => { WidgetApi.reload(deployedWidget.id) } const onIgnoreMouseEventChange = (checked: boolean) => { setIgnoreMouseEvents(checked) WidgetApi.setIgnoreMouseEvents(deployedWidget.id, checked) } return (
{widget && ( {getLocalizedText(widget.title)} )} {deployedWidget.name}
{isDebugMode && (

DevTools

)}

{t('tray.restartWidgets')}

{widget?.configPagePath && (

{t('settings.title')}

)}

{t('manager.remove')}

{t('manager.confirmRemove')} {t('manager.removeDesc', { name: widget ? getLocalizedText(widget.title) : deployedWidget.name })} {t('settings.widgetPackage.cancel')} onRemove(deployedWidget)}> {t('settings.widgetPackage.confirm')}
) } ================================================ FILE: src/components/manager/deployed-widget-list.tsx ================================================ import type { DeployedWidget } from '@widget-js/core' import { BrowserWindowApi, DeployedWidgetApi } from '@widget-js/core' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { DeployedWidgetCard } from './deployed-widget-card' export default function DeployedWidgetList() { const [widgets, setWidgets] = useState([]) const { t } = useTranslation() const refreshWidgets = () => { DeployedWidgetApi.getDeployedWidgets().then(setWidgets) } useEffect(() => { refreshWidgets() BrowserWindowApi.setAlwaysOnTop(true) // Listen for window focus to refresh list window.addEventListener('focus', refreshWidgets) return () => { window.removeEventListener('focus', refreshWidgets) } }, []) const removeWidget = async (widget: DeployedWidget) => { await DeployedWidgetApi.removeDeployedWidget(widget.id) setWidgets(prev => prev.filter(w => w.id !== widget.id)) } return (
{widgets.map(widget => ( removeWidget(widget)} /> ))} {widgets.length === 0 && (
{t('tray.runningWidgets')} {' '} (0)
)}
) } ================================================ FILE: src/components/nav-main.tsx ================================================ import type { LucideIcon } from 'lucide-react' import { Link } from 'react-router-dom' import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from '@/components/ui/sidebar' export function NavMain({ label, items, }: { label: string items: { title: string url: string icon: LucideIcon isActive?: boolean }[] }) { return ( {label} {items.map(item => ( {item.icon && } {item.title} ))} ) } ================================================ FILE: src/components/nav-user.tsx ================================================ import type { LucideIcon } from 'lucide-react' import { BrowserWindowApi, NotificationApi } from '@widget-js/core' import consola from 'consola' import { ChevronsUpDown, } from 'lucide-react' import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { supabase } from '@/api/supabase' import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from '@/components/ui/sidebar' import UserAvatar from '@/components/user-avatar' import { useSupabaseChannel } from '@/hooks/use-supabase-channel' export function NavUser({ user, }: { user: { name: string email: string avatar?: string icon?: LucideIcon } }) { const navigate = useNavigate() const [loginState, setLoginState] = useState('') useEffect(() => { const storedState = localStorage.getItem('wechat_login_state') if (storedState) { setLoginState(storedState) } }, []) // Handle Supabase channel for login useSupabaseChannel(loginState ? `wechat-login-${loginState}` : '', async (payload: any) => { consola.info(payload) const currentSession = payload.payload.session const loginRes = await supabase.auth.setSession(currentSession) if (loginRes.error) { NotificationApi.error(loginRes.error.message) } else { navigate('/user/profile') } }) const handleLogin = () => { const newState = crypto.randomUUID().replace(/-/g, '') setLoginState(newState) localStorage.setItem('wechat_login_state', newState) BrowserWindowApi.openUrl(`https://open.weixin.qq.com/connect/qrconnect?appid=wxf91b19da281f23a9&redirect_uri=https%3A%2F%2Fwidgetjs.cn%2Fapi%2Fv1%2Fuser%2Flogin%2Fwechat%2Fcallback&response_type=code&scope=snsapi_login&state=${newState}#wechat_redirect`, { width: 800, height: 600, frame: true, transparent: false, titleBarStyle: 'default', }) } const handleClick = () => { if (user.email) { navigate('/user/profile') } else { handleLogin() } } return (
{user.name}
) } ================================================ FILE: src/components/purchase-dialog.tsx ================================================ import type { AlipayOrderResult, PayVirtualProduct } from '@/api/pay' import { SiAlipay } from '@icons-pack/react-simple-icons' import { BrowserWindowApi } from '@widget-js/core' import consola from 'consola' import { useEffect, useState } from 'react' import { toast } from 'sonner' import { PayApi } from '@/api/pay' import { supabase } from '@/api/supabase' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { Spinner } from '@/components/ui/spinner' interface PurchaseDialogProps { open: boolean onOpenChange: (open: boolean) => void productId?: number onSuccess?: () => void } export function PurchaseDialog({ open, onOpenChange, productId = 2, onSuccess }: PurchaseDialogProps) { const [loading, setLoading] = useState(false) const [product, setProduct] = useState(null) const [order, setOrder] = useState(null) const [payUrl, setPayUrl] = useState('') useEffect(() => { if (!order) { return } const channel = supabase .channel('table-db-changes') .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'ai_token_packages', filter: `order_id=eq.${order.orderId}`, }, (payload) => { consola.log('Payment successful:', payload) toast.success('支付成功!') onOpenChange(false) onSuccess?.() }, ) .subscribe() return () => { supabase.removeChannel(channel) } }, [order]) const initPurchase = async () => { try { setLoading(true) setProduct(null) setOrder(null) setPayUrl('') // 1. Get Product Info const products = await PayApi.getProducts('ai') const targetProduct = products.find(p => p.id === productId) if (!targetProduct) { toast.error('商品不存在') onOpenChange(false) return } setProduct(targetProduct) // 2. Create Order const orderRes = await PayApi.createAlipayOrder(targetProduct.id, window.location.href) setOrder(orderRes) const url = await PayApi.getAlipayUrl(orderRes.orderId) setPayUrl(url) } catch (error) { console.error(error) toast.error('获取购买信息失败') onOpenChange(false) } finally { setLoading(false) } } useEffect(() => { if (open) { initPurchase() } else { // Clean up when closed setOrder(null) } }, [open, productId]) return ( 购买套餐
{loading ? (

正在创建订单...

) : product && order ? ( <>

{product.name}

¥ {(product.price / 100).toFixed(2)}

{product.description && (

{product.description}

)}
支付完成后,本窗口会自动刷新
) : (
加载失败,请重试
)}
) } ================================================ FILE: src/components/setting-section.tsx ================================================ import type { ReactNode } from 'react' import { Separator } from '@/components/ui/separator' interface SettingSectionProps { title: string children: ReactNode } export function SettingSection({ title, children }: SettingSectionProps) { return (

{title}

{children}
) } ================================================ FILE: src/components/team-switcher.tsx ================================================ 'use client' import { ChevronsUpDown, Plus } from 'lucide-react' import * as React from 'react' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar, } from '@/components/ui/sidebar' export function TeamSwitcher({ teams, }: { teams: { name: string logo: React.ElementType plan: string }[] }) { const { isMobile } = useSidebar() const [activeTeam, setActiveTeam] = React.useState(teams[0]) if (!activeTeam) { return null } return (
{activeTeam.name} {activeTeam.plan}
Teams {teams.map((team, index) => ( setActiveTeam(team)} className="gap-2 p-2" >
{team.name} ⌘ {index + 1}
))}
Add team
) } ================================================ FILE: src/components/tray/social-links.tsx ================================================ import { AppApi, NotificationApi } from '@widget-js/core' import { useCallback, useRef } from 'react' import { useTranslation } from 'react-i18next' import bilibili from '@/assets/images/bilibili_logo_red.png' import douyin from '@/assets/images/douyin.png' import githubMark from '@/assets/images/github-mark.png' import logo from '@/assets/images/logo.png' import qq from '@/assets/images/qq.png' interface SocialLinksProps { iconSize?: number } function useLongPress(callback: () => void, delay: number = 3000) { const timeoutRef = useRef(null) const start = useCallback(() => { timeoutRef.current = window.setTimeout(() => { callback() }, delay) }, [callback, delay]) const clear = useCallback(() => { if (timeoutRef.current) { clearTimeout(timeoutRef.current) timeoutRef.current = null } }, []) return { onMouseDown: start, onMouseUp: clear, onMouseLeave: clear, onTouchStart: start, onTouchEnd: clear, } } export function SocialLinks({ iconSize = 20 }: SocialLinksProps) { const { t } = useTranslation() const handleEnableDevMode = useCallback(async () => { NotificationApi.info(t('notification.enableDevMode')) await AppApi.setConfig('debug', true) }, [t]) const longPressProps = useLongPress(handleEnableDevMode, 3000) const links = [ { name: 'Widget', url: 'https://widgetjs.cn/', icon: logo, }, { name: 'TikTok', url: 'https://v.douyin.com/YhuNAb8/', icon: douyin, }, { name: 'QQ', url: 'https://jq.qq.com/?_wv=1027&k=TgO2mUQe', icon: qq, }, { name: 'Bilibili', url: 'https://space.bilibili.com/207395767', icon: bilibili, }, { name: 'GitHub', url: 'https://github.com/widget-js/widgets', icon: githubMark, ...longPressProps, // Apply long press to GitHub only }, ] return (
{links.map(link => ( {link.name} ))}
) } ================================================ FILE: src/components/tray/tray-menu-item.tsx ================================================ import type { LucideIcon } from 'lucide-react' import * as React from 'react' import { cn } from '@/lib/utils' interface TrayMenuItemProps extends React.HTMLAttributes { icon: LucideIcon label: string } function TrayMenuItem({ ref, className, icon: Icon, label, ...props }: TrayMenuItemProps & { ref?: React.RefObject }) { return (
{label}
) } TrayMenuItem.displayName = 'TrayMenuItem' export { TrayMenuItem } ================================================ FILE: src/components/ui/alert-dialog.tsx ================================================ import { AlertDialog as AlertDialogPrimitive } from 'radix-ui' import * as React from 'react' import { Button } from '@/components/ui/button' import { cn } from '@/lib/utils' function AlertDialog({ ...props }: React.ComponentProps) { return } function AlertDialogTrigger({ ...props }: React.ComponentProps) { return ( ) } function AlertDialogPortal({ ...props }: React.ComponentProps) { return ( ) } function AlertDialogOverlay({ className, ...props }: React.ComponentProps) { return ( ) } function AlertDialogContent({ className, size = 'default', ...props }: React.ComponentProps & { size?: 'default' | 'sm' }) { return ( ) } function AlertDialogHeader({ className, ...props }: React.ComponentProps<'div'>) { return (
) } function AlertDialogFooter({ className, ...props }: React.ComponentProps<'div'>) { return (
) } function AlertDialogTitle({ className, ...props }: React.ComponentProps) { return ( ) } function AlertDialogDescription({ className, ...props }: React.ComponentProps) { return ( ) } function AlertDialogMedia({ className, ...props }: React.ComponentProps<'div'>) { return (
) } function AlertDialogAction({ className, variant = 'default', size = 'default', ...props }: React.ComponentProps & Pick, 'variant' | 'size'>) { return ( ) } function AlertDialogCancel({ className, variant = 'outline', size = 'default', ...props }: React.ComponentProps & Pick, 'variant' | 'size'>) { return ( ) } export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, } ================================================ FILE: src/components/ui/avatar.tsx ================================================ import { Avatar as AvatarPrimitive } from 'radix-ui' import * as React from 'react' import { cn } from '@/lib/utils' function Avatar({ className, size = 'default', ...props }: React.ComponentProps & { size?: 'default' | 'sm' | 'lg' }) { return ( ) } function AvatarImage({ className, ...props }: React.ComponentProps) { return ( ) } function AvatarFallback({ className, ...props }: React.ComponentProps) { return ( ) } function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) { return ( svg]:hidden', 'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2', 'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2', className, )} {...props} /> ) } function AvatarGroup({ className, ...props }: React.ComponentProps<'div'>) { return (
) } function AvatarGroupCount({ className, ...props }: React.ComponentProps<'div'>) { return (
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3', className, )} {...props} /> ) } export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, } ================================================ FILE: src/components/ui/breadcrumb.tsx ================================================ import { ChevronRight, MoreHorizontal } from 'lucide-react' import { Slot } from 'radix-ui' import * as React from 'react' import { cn } from '@/lib/utils' function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) { return