├── .commitlintrc.js ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ └── webpilot-vue3.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierrc.js ├── .stylelintrc.js ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── assets ├── icon.png ├── icon │ ├── close.svg │ └── sendActive.svg ├── locales │ ├── en │ │ └── messages.json │ └── zh_CN │ │ └── messages.json └── styles │ ├── csui-reset.scss │ ├── csui-theme.scss │ ├── reset.scss │ ├── solarized_dark.scss │ └── solarized_light.scss ├── doc └── WebPilot Chrome Extension Privacy Policy.md ├── gettext.config.js ├── package.json ├── pnpm-lock.yaml ├── scripts └── i18n │ ├── gettextOutput │ ├── messages.pot │ └── translations.json │ └── postGettext.js ├── src ├── apiConfig.ts ├── apiService.ts ├── background │ ├── index.js │ └── messages │ │ ├── openSetting.ts │ │ ├── popupCheck.ts │ │ └── signInSuccess.ts ├── components │ ├── DisplayMode.vue │ ├── FloatControlButtons.vue │ ├── HeaderPanel.vue │ ├── HeaderSwitch.vue │ ├── HelpTips.vue │ ├── InteractiveIcon │ │ ├── InteractiveIcon.vue │ │ └── image │ │ │ ├── CloseDarkClick.svg │ │ │ ├── CloseDarkDefault.svg │ │ │ ├── CloseDarkDisable.svg │ │ │ ├── CloseDarkHover.svg │ │ │ ├── CloseLightClick.svg │ │ │ ├── CloseLightDefault.svg │ │ │ ├── CloseLightDisable.svg │ │ │ ├── CloseLightHover.svg │ │ │ ├── CollectDarkClick.svg │ │ │ ├── CollectDarkDefault.svg │ │ │ ├── CollectDarkDisable.svg │ │ │ ├── CollectDarkHover.svg │ │ │ ├── CollectLightClick.svg │ │ │ ├── CollectLightDefault.svg │ │ │ ├── CollectLightDisable.svg │ │ │ ├── CollectLightHover.svg │ │ │ ├── CopyDarkClick.svg │ │ │ ├── CopyDarkDefault.svg │ │ │ ├── CopyDarkDisable.svg │ │ │ ├── CopyDarkHover.svg │ │ │ ├── CopyLightClick.svg │ │ │ ├── CopyLightDefault.svg │ │ │ ├── CopyLightDisable.svg │ │ │ ├── CopyLightHover.svg │ │ │ ├── DeleteDarkClick.svg │ │ │ ├── DeleteDarkDefault.svg │ │ │ ├── DeleteDarkHover.svg │ │ │ ├── DeleteLightClick.svg │ │ │ ├── DeleteLightDefault.svg │ │ │ ├── DeleteLightHover.svg │ │ │ ├── PencilDarkClick.svg │ │ │ ├── PencilDarkDefault.svg │ │ │ ├── PencilDarkHover.svg │ │ │ ├── PencilLightClick.svg │ │ │ ├── PencilLightDefault.svg │ │ │ ├── PencilLightHover.svg │ │ │ ├── PreviousDarkClick.svg │ │ │ ├── PreviousDarkDefault.svg │ │ │ ├── PreviousDarkDisable.svg │ │ │ ├── PreviousDarkHover.svg │ │ │ ├── PreviousLightClick.svg │ │ │ ├── PreviousLightDefault.svg │ │ │ ├── PreviousLightDisable.svg │ │ │ ├── PreviousLightHover.svg │ │ │ ├── SaveDarkClick.svg │ │ │ ├── SaveDarkDefault.svg │ │ │ ├── SaveDarkDisable.svg │ │ │ ├── SaveDarkHover.svg │ │ │ ├── SaveLightClick.svg │ │ │ ├── SaveLightDefault.svg │ │ │ ├── SaveLightDisable.svg │ │ │ ├── SaveLightHover.svg │ │ │ ├── SendDarkClick.svg │ │ │ ├── SendDarkDefault.svg │ │ │ ├── SendDarkHover.svg │ │ │ ├── SendLightClick.svg │ │ │ ├── SendLightDefault.svg │ │ │ ├── SendLightHover.svg │ │ │ ├── SettingDarkClick.svg │ │ │ ├── SettingDarkDefault.svg │ │ │ ├── SettingDarkDisable.svg │ │ │ ├── SettingDarkHover.svg │ │ │ ├── SettingLightClick.svg │ │ │ ├── SettingLightDefault.svg │ │ │ ├── SettingLightDisable.svg │ │ │ └── SettingLightHover.svg │ ├── PromptAreaSelector.vue │ ├── PromptEditor.vue │ ├── PromptInput.vue │ ├── PromptList.vue │ ├── PromptListItem.vue │ ├── PromptMenu.vue │ ├── PromptResult.vue │ ├── SendButton │ │ └── Index.vue │ ├── ShortcutInput.vue │ ├── ShortcutTips.vue │ ├── SuperButton │ │ ├── SuperButton.vue │ │ ├── SuperButtonPromptEditor.vue │ │ ├── SuperButtonTooltip.vue │ │ └── icon │ │ │ ├── edit.svg │ │ │ ├── editActive.svg │ │ │ ├── editHover.svg │ │ │ ├── generating.svg │ │ │ ├── generatingActive.svg │ │ │ ├── generatingHover.svg │ │ │ ├── triangle.png │ │ │ ├── undo.svg │ │ │ ├── undoActive.svg │ │ │ ├── undoHover.svg │ │ │ ├── webpilot.svg │ │ │ ├── webpilotActive.svg │ │ │ └── webpilotHover.svg │ ├── TipsShortcut.vue │ ├── WebpilotAlert.vue │ ├── WebpilotAttribution.vue │ ├── WebpilotButton.vue │ ├── WebpilotCheckbox.vue │ ├── icon │ │ ├── IconAlertError.vue │ │ ├── IconAlertInfo.vue │ │ ├── IconAlertSuccess.vue │ │ ├── IconBackArrow.vue │ │ ├── IconCheckmark.vue │ │ ├── IconEnter.vue │ │ ├── IconHelp.vue │ │ ├── IconJigsaw.vue │ │ ├── IconLoading.vue │ │ ├── IconLogoAndText.vue │ │ ├── IllustrationPopup.vue │ │ └── IllustrationSidebar.vue │ └── image │ │ ├── IconDraggingDark.svg │ │ ├── IconDraggingLight.svg │ │ ├── ImageFreePlan.vue │ │ ├── ImagePinGuide.vue │ │ ├── ImageSelectTextWithIcon.vue │ │ └── ImageSelectTextWithoutIcon.vue ├── config.ts ├── contents │ ├── DiscordMessages.vue │ ├── GithubIssues.vue │ ├── GithubIssues.vue.bak │ ├── Index.vue │ ├── SlackMessages.vue │ ├── SlackMessages.vue.bak │ ├── TwitterInput.vue │ ├── TwitterMessages.vue │ └── signInListener.ts ├── csui │ ├── DiscordMessages │ │ ├── TheEntry.bak.vue │ │ └── TheEntry.vue │ ├── GithubIssues │ │ └── TheEntry.vue │ ├── Index │ │ ├── TheEntry.vue │ │ ├── ThePopupBox │ │ │ └── ThePopupBox.vue │ │ └── TheSidebar │ │ │ └── TheSidebar.vue │ ├── SlackMessages │ │ ├── TheEntry.bak.vue │ │ └── TheEntry.vue │ ├── TwitterInput │ │ └── TheEntry.vue │ └── TwitterMessages │ │ └── TheEntry.vue ├── featureFlagsConfig.ts ├── hooks │ ├── useAskAi.ts │ ├── useClickoutside.ts │ ├── useDraggable.ts │ ├── useMessage.ts │ ├── useScroll.ts │ ├── useSelectedText.ts │ ├── useStopKeyboardEvent.ts │ └── useSuperButtonPrompt.ts ├── io.ts ├── options │ ├── AboutView.vue │ ├── AccountView.vue │ ├── AdvancedView.vue │ ├── TheEntry.vue │ ├── components │ │ ├── ContributorView.vue │ │ ├── CreditOpenAI.vue │ │ ├── CreditRadioGroup.vue │ │ ├── CreditWebpilotStatus.vue │ │ ├── LinkedAccount.vue │ │ ├── NavItem.vue │ │ ├── ServerTypeSelector.vue │ │ ├── SettingAlert.vue │ │ ├── SwitchButton.vue │ │ └── WebpilotInput.vue │ ├── images │ │ ├── Pop_up.svg │ │ ├── Side_bar.svg │ │ ├── Text+Logo.svg │ │ ├── bg-signin.png │ │ ├── default.png │ │ ├── dropdown.png │ │ ├── edit.png │ │ ├── edit.svg │ │ ├── g-logo.png │ │ ├── help.png │ │ ├── icon-about-filled.vue │ │ ├── icon-about-outline.vue │ │ ├── icon-addon-filled.vue │ │ ├── icon-addon-outline.vue │ │ ├── icon-caret.vue │ │ ├── icon-confirmation.vue │ │ ├── icon-infor-filled.vue │ │ ├── icon-logo-email.vue │ │ ├── icon-logo-github.vue │ │ ├── icon-logo-google.vue │ │ ├── icon-logo-microsoft.vue │ │ ├── icon-logo-openai-proxy.vue │ │ ├── icon-logo-openai.vue │ │ ├── icon-logo-twitter.vue │ │ ├── icon-logo-with-text-dark.vue │ │ ├── icon-logo-with-text.vue │ │ ├── icon-logo.vue │ │ ├── icon-nav-about-filled.vue │ │ ├── icon-nav-about-outline.vue │ │ ├── icon-nav-extension-filled.vue │ │ ├── icon-nav-extension-outline.vue │ │ ├── icon-person-filled.vue │ │ ├── icon-person-outline.vue │ │ ├── icon-question-outline.vue │ │ ├── question_mark.svg │ │ └── sign-in-with-google.png │ ├── index.css │ ├── index.html │ ├── index.vue │ └── views │ │ ├── AboutView.vue │ │ ├── AccountView.vue │ │ └── ExtensionView.vue ├── popup │ ├── componetns │ │ └── WebpilotPopup.vue │ ├── index.html │ └── index.vue ├── stores │ ├── api.ts │ ├── store.ts │ └── user.ts ├── tabs │ ├── components │ │ ├── StepFour.vue │ │ ├── StepOne.vue │ │ ├── StepThree.vue │ │ ├── StepTwo.vue │ │ ├── WelcomePage.vue │ │ └── WelcomeTitle.vue │ ├── images │ │ ├── icon-gift.png │ │ ├── key-cap-big.png │ │ ├── key-cap-small.png │ │ ├── logo.png │ │ └── signin-google.png │ ├── index.html │ └── index.vue └── utils │ ├── i18n.js │ └── index.ts └── tsconfig.json /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | } 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .plasmo/ 2 | build/ 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: {webextensions: true}, 4 | extends: ['standard-one/vue', 'standard-one'], 5 | parserOptions: { 6 | tsconfigRootDir: __dirname, 7 | project: ['./tsconfig.json'], 8 | }, 9 | rules: { 10 | 'import/no-unresolved': [2, {ignore: ['data-url:', 'data-base64:']}], 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/webpilot-vue3.yml: -------------------------------------------------------------------------------- 1 | # 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 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs 3 | 4 | name: Vue3 Webpilot 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'main' 10 | - 'vue3' 11 | - 'dev' 12 | pull_request: 13 | branches: 14 | - 'main' 15 | - 'vue3' 16 | - 'dev' 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | node-version: [18.x] 25 | 26 | steps: 27 | - uses: actions/checkout@v3 28 | 29 | - name: Use Node.js ${{ matrix.node-version }} 30 | uses: actions/setup-node@v3 31 | with: 32 | node-version: ${{ matrix.node-version }} 33 | 34 | - uses: pnpm/action-setup@v2 35 | name: Install pnpm 36 | id: pnpm-install 37 | with: 38 | version: 8 39 | run_install: false 40 | 41 | - name: Get pnpm store directory 42 | id: pnpm-cache 43 | shell: bash 44 | run: | 45 | echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT 46 | 47 | - uses: actions/cache@v3 48 | name: Setup pnpm cache 49 | with: 50 | path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} 51 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 52 | restore-keys: | 53 | ${{ runner.os }}-pnpm-store- 54 | 55 | - name: Install dependencies 56 | run: pnpm install 57 | 58 | - name: Building extension 59 | run: pnpm run build 60 | 61 | - name: Pack Extension 62 | uses: actions/upload-artifact@v3 63 | with: 64 | name: webpilot 65 | path: build 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules/ 6 | .pnp 7 | .pnp.js 8 | package-lock.json 9 | yarn.lock 10 | 11 | # testing 12 | /coverage 13 | 14 | #cache 15 | .turbo 16 | .*cache 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | *.po 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files 30 | .env* 31 | 32 | out/ 33 | build/ 34 | dist/ 35 | 36 | # plasmo - https://www.plasmo.com 37 | .plasmo 38 | 39 | # bpp - http://bpp.browser.market/ 40 | keys.json 41 | 42 | # typescript 43 | .tsbuildinfo 44 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged 5 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('prettier-config-standard-one') 2 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'stylelint-config-standard-one', 4 | 'stylelint-config-standard-one/scss', 5 | 'stylelint-config-standard-one/vue', 6 | ], 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.endOfLine": "cr", 3 | "files.eol": "\n", 4 | "cSpell.words": ["csui", "gettext", "openai", "Webpilot"] 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Webpilot 2 | 3 |  4 | 5 |  6 | 7 |  8 | 9 |  10 | 11 | Webpilot is a free, open-source "Copilot for web" that allows you to have free-form conversations with web pages or engage in automatic arguments with other users. Unlike ChatGPT, there is no need to chat or switch web pages, and no need to constantly copy and paste back and forth. 12 | 13 | Chrome Extension: [Add to Chrome](https://chrome.google.com/webstore/detail/Webpilot/biaggnjibplcfekllonekbonhfgchopo?utm_source=link&utm_medium=git&) 14 | 15 | Official Website: [HomePage](https://www.Webpilot.ai/) 16 | 17 | Dev Team: dev@webpilot.ai 18 | 19 | 20 | ## Getting Started 21 | 22 | First, run the development server: 23 | 24 | ```bash 25 | pnpm dev 26 | # or 27 | npm run dev 28 | # or 29 | yarn dev 30 | ``` 31 | 32 | Open your Chrome browser and load the appropriate development build: 33 | 34 | 1. Go to [chrome://extensions](chrome://extensions). 35 | 2. At the top right, turn on Developer mode. 36 | 3. Click Load unpacked. 37 | 4. Find and select the `build/chrome-mv3-dev` folder. 38 | 5. Pin this extension to your Chrome toolbar. 39 | 6. After installation, please refresh the page where you want to select text before using this extension. 40 | 41 | 42 | ## Star History 43 | 44 | [](https://star-history.com/#webpilot-ai/Webpilot&Date) 45 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/assets/icon.png -------------------------------------------------------------------------------- /assets/icon/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/icon/sendActive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /assets/styles/csui-reset.scss: -------------------------------------------------------------------------------- 1 | /* stylelint-disable */ 2 | #webpilot-template { 3 | @import './reset.scss'; 4 | @import './solarized_light.scss'; 5 | } 6 | #webpilot-content { 7 | p { 8 | margin: 0; 9 | line-height: 1.6; 10 | } 11 | pre { 12 | padding: 0; 13 | } 14 | code { 15 | font-size: 14px; 16 | padding: 1 5px; 17 | background: #fdf6e3; 18 | color: #657b83; 19 | border-radius: 6px; 20 | box-shadow: none; 21 | } 22 | } 23 | 24 | @media (prefers-color-scheme: dark) { 25 | #webpilot-template { 26 | @import './solarized_dark.scss'; 27 | } 28 | #webpilot-content { 29 | p { 30 | color: #dcdcdc; 31 | } 32 | li { 33 | color: #dcdcdc; 34 | } 35 | code { 36 | background: #002b36; 37 | color: #839496; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /assets/styles/csui-theme.scss: -------------------------------------------------------------------------------- 1 | /* Theme Color */ 2 | 3 | :root { 4 | --webpilot-theme-main-text-color: #929497; 5 | --webpilot-theme-icon-default-and-secondary-text: #585b58; 6 | --webpilot-theme-main-background-color: #fff; 7 | --webpilot-theme-content-background-color: #fff; 8 | --webpilot-theme-baseline-text: #292929; 9 | --webpilot-theme-main-background-shadow: rgb(149 157 165 / 20%); 10 | 11 | /* only text link or title need to change */ 12 | --webpilot-theme-brand-primary: #4f5aff; 13 | --webpilot-theme-stoke-and-hover-status: #dbdeff; 14 | --webpilot-theme-brightness-number: 1; 15 | --webpilot-theme-invert-number: 0; 16 | } 17 | 18 | @media (prefers-color-scheme: dark) { 19 | :root { 20 | --webpilot-theme-main-text-color: #fff; 21 | --webpilot-theme-icon-default-and-secondary-text: #4f5aff33; 22 | --webpilot-theme-main-background-color: #292d3f; 23 | --webpilot-theme-content-background-color: #323558; 24 | --webpilot-theme-baseline-text: #fff; 25 | --webpilot-theme-main-background-shadow: rgb(84 132 181 / 20%); 26 | 27 | // --webpilot-theme-brand-primary: #5e80ff; 28 | --webpilot-theme-brand-primary: #fff; 29 | --webpilot-theme-stoke-and-hover-status: #585c8a; 30 | --webpilot-theme-brightness-number: 3; 31 | --webpilot-theme-invert-number: 1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /assets/styles/reset.scss: -------------------------------------------------------------------------------- 1 | /* Box sizing rules */ 2 | *, 3 | *::before, 4 | *::after { 5 | box-sizing: border-box; 6 | font-family: 'PingFang SC', system, -apple-system, BlinkMacSystemFont, 'Helvetica Neue', STHeiti, 7 | 'Microsoft Yahei', Tahoma, Simsun, sans-serif; 8 | } 9 | 10 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ 11 | ul[role='list'], 12 | ol[role='list'] { 13 | list-style: none; 14 | } 15 | 16 | /* Set core root defaults */ 17 | html:focus-within { 18 | scroll-behavior: smooth; 19 | } 20 | 21 | /* Set core body defaults */ 22 | body { 23 | margin: 0; 24 | text-rendering: optimizespeed; 25 | line-height: 1.5; 26 | } 27 | 28 | /* A elements that don"t have a class get default styles */ 29 | a:not([class]) { 30 | text-decoration-skip-ink: auto; 31 | } 32 | 33 | /* Make images easier to work with */ 34 | img, 35 | picture { 36 | display: block; 37 | max-width: 100%; 38 | } 39 | 40 | /* Inherit fonts for inputs and buttons */ 41 | input, 42 | button, 43 | textarea, 44 | select { 45 | font: inherit; 46 | } 47 | 48 | /* Textarea default style */ 49 | textarea { 50 | // background-color: #fff; 51 | cursor: text; 52 | } 53 | -------------------------------------------------------------------------------- /assets/styles/solarized_dark.scss: -------------------------------------------------------------------------------- 1 | /* stylelint-disable */ 2 | // https://unpkg.com/highlightjs@9.16.2/styles/solarized_dark.css 3 | .hljs { 4 | display: block; 5 | overflow-x: auto; 6 | padding: 0.5em; 7 | background: #002b36; 8 | color: #839496 !important; 9 | -webkit-text-size-adjust: none; 10 | } 11 | 12 | .hljs-comment, 13 | .diff .hljs-header, 14 | .hljs-doctype, 15 | .hljs-pi, 16 | .lisp .hljs-string { 17 | color: #586e75 !important; 18 | } 19 | 20 | /* Solarized Green */ 21 | .hljs-keyword, 22 | .hljs-winutils, 23 | .method, 24 | .hljs-addition, 25 | .css .hljs-tag, 26 | .hljs-request, 27 | .hljs-status, 28 | .nginx .hljs-title { 29 | color: #859900 !important; 30 | } 31 | 32 | /* Solarized Cyan */ 33 | .hljs-number, 34 | .hljs-command, 35 | .hljs-string, 36 | .hljs-tag .hljs-value, 37 | .hljs-rule .hljs-value, 38 | .hljs-doctag, 39 | .tex .hljs-formula, 40 | .hljs-regexp, 41 | .hljs-hexcolor, 42 | .hljs-link_url { 43 | color: #2aa198 !important; 44 | } 45 | 46 | /* Solarized Blue */ 47 | .hljs-title, 48 | .hljs-localvars, 49 | .hljs-chunk, 50 | .hljs-decorator, 51 | .hljs-built_in, 52 | .hljs-identifier, 53 | .vhdl .hljs-literal, 54 | .hljs-id, 55 | .css .hljs-function, 56 | .hljs-name { 57 | color: #268bd2 !important; 58 | } 59 | 60 | /* Solarized Yellow */ 61 | .hljs-attribute, 62 | .hljs-variable, 63 | .lisp .hljs-body, 64 | .smalltalk .hljs-number, 65 | .hljs-constant, 66 | .hljs-class .hljs-title, 67 | .hljs-parent, 68 | .hljs-type, 69 | .hljs-link_reference { 70 | color: #b58900 !important; 71 | } 72 | 73 | /* Solarized Orange */ 74 | .hljs-preprocessor, 75 | .hljs-preprocessor .hljs-keyword, 76 | .hljs-pragma, 77 | .hljs-shebang, 78 | .hljs-symbol, 79 | .hljs-symbol .hljs-string, 80 | .diff .hljs-change, 81 | .hljs-special, 82 | .hljs-attr_selector, 83 | .hljs-subst, 84 | .hljs-cdata, 85 | .css .hljs-pseudo, 86 | .hljs-header { 87 | color: #cb4b16 !important; 88 | } 89 | 90 | /* Solarized Red */ 91 | .hljs-deletion, 92 | .hljs-important { 93 | color: #dc322f !important; 94 | } 95 | 96 | /* Solarized Violet */ 97 | .hljs-link_label { 98 | color: #6c71c4 !important; 99 | } 100 | 101 | .tex .hljs-formula { 102 | background: #073642; 103 | } -------------------------------------------------------------------------------- /assets/styles/solarized_light.scss: -------------------------------------------------------------------------------- 1 | /* stylelint-disable */ 2 | // https://unpkg.com/highlightjs@9.16.2/styles/solarized_light.css 3 | .hljs { 4 | display: block; 5 | overflow-x: auto; 6 | padding: 0.5em; 7 | background: #fdf6e3; 8 | color: #657b83 !important; 9 | -webkit-text-size-adjust: none; 10 | } 11 | 12 | .hljs-comment, 13 | .diff .hljs-header, 14 | .hljs-doctype, 15 | .hljs-pi, 16 | .lisp .hljs-string { 17 | color: #93a1a1 !important; 18 | } 19 | 20 | /* Solarized Green */ 21 | .hljs-keyword, 22 | .hljs-winutils, 23 | .method, 24 | .hljs-addition, 25 | .css .hljs-tag, 26 | .hljs-request, 27 | .hljs-status, 28 | .nginx .hljs-title { 29 | color: #859900 !important; 30 | } 31 | 32 | /* Solarized Cyan */ 33 | .hljs-number, 34 | .hljs-command, 35 | .hljs-string, 36 | .hljs-tag .hljs-value, 37 | .hljs-rule .hljs-value, 38 | .hljs-doctag, 39 | .tex .hljs-formula, 40 | .hljs-regexp, 41 | .hljs-hexcolor, 42 | .hljs-link_url { 43 | color: #2aa198 !important; 44 | } 45 | 46 | /* Solarized Blue */ 47 | .hljs-title, 48 | .hljs-localvars, 49 | .hljs-chunk, 50 | .hljs-decorator, 51 | .hljs-built_in, 52 | .hljs-identifier, 53 | .vhdl .hljs-literal, 54 | .hljs-id, 55 | .css .hljs-function, 56 | .hljs-name { 57 | color: #268bd2 !important; 58 | } 59 | 60 | /* Solarized Yellow */ 61 | .hljs-attribute, 62 | .hljs-variable, 63 | .lisp .hljs-body, 64 | .smalltalk .hljs-number, 65 | .hljs-constant, 66 | .hljs-class .hljs-title, 67 | .hljs-parent, 68 | .hljs-type, 69 | .hljs-link_reference { 70 | color: #b58900 !important; 71 | } 72 | 73 | /* Solarized Orange */ 74 | .hljs-preprocessor, 75 | .hljs-preprocessor .hljs-keyword, 76 | .hljs-pragma, 77 | .hljs-shebang, 78 | .hljs-symbol, 79 | .hljs-symbol .hljs-string, 80 | .diff .hljs-change, 81 | .hljs-special, 82 | .hljs-attr_selector, 83 | .hljs-subst, 84 | .hljs-cdata, 85 | .css .hljs-pseudo, 86 | .hljs-header { 87 | color: #cb4b16 !important; 88 | } 89 | 90 | /* Solarized Red */ 91 | .hljs-deletion, 92 | .hljs-important { 93 | color: #dc322f !important; 94 | } 95 | 96 | /* Solarized Violet */ 97 | .hljs-link_label { 98 | color: #6c71c4 !important; 99 | } 100 | 101 | .tex .hljs-formula { 102 | background: #eee8d5; 103 | } -------------------------------------------------------------------------------- /doc/WebPilot Chrome Extension Privacy Policy.md: -------------------------------------------------------------------------------- 1 | # WebPilot Chrome Extension Privacy Policy 2 | Last Updated: October 26, 2023 3 | 4 | ## 1. Introduction 5 | Welcome to WebPilot! This privacy policy is designed to help you understand how we, WebPilot Inc. located at 2435 N CENTRAL EXPY STE 1200, RICHARDSON, TX 75080, collect, use, and share your data when you use our WebPilot Chrome Extension. 6 | 7 | ## 2. Data Collection, Use, and Storage 8 | Login Information: Before users can fully utilize the WebPilot Chrome Extension, they are required to log in using their Google account. We use this information only for authentication purposes and do not store any personal data related to your Google account. 9 | 10 | User Interactions: We do not actively collect personal information from users. However, if users engage in a Q&A session with selected content or an entire page, we collect the chosen text and the user's questions. This information is used solely to respond to user requests, as this is an AI application, and to optimize our product. 11 | 12 | Data Storage: All collected data is stored in the United States. We prioritize the safety and security of your data. 13 | 14 | API Requests: Users have the option to make requests to WebPilot servers using their WebPilot account quota or invoke their own OpenAI API Key to communicate with OpenAI, Microsoft, or other custom proxies. 15 | 16 | ## 3. Data Sharing 17 | When users make requests to WebPilot servers, we may relay these requests to OpenAI, Microsoft, or future AI service providers. This is a standard request mechanism, and the data shared is limited to the user-selected content and the accompanying questions. 18 | 19 | ## 4. Open Source and Licensing 20 | WebPilot Chrome Extension is an open-source application and can be found at https://github.com/webpilot-ai/Webpilot. It adheres to the GPL-3.0 license. 21 | 22 | ## 5. Updates to This Privacy Policy 23 | We may update our privacy policy in the future to reflect changes in our practices or for other operational, legal, or regulatory reasons. Such updates may be made without additional notice. 24 | 25 | ## 6. Contact Us 26 | For more information about our privacy practices, if you have questions, or if you would like to make a complaint, please contact us at: 27 | 28 | WebPilot Inc. 29 | 2435 N CENTRAL EXPY STE 1200 30 | RICHARDSON, TX 75080 31 | -------------------------------------------------------------------------------- /gettext.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | input: { 3 | path: './src', // only files in this directory are considered for extraction 4 | include: ['**/*.vue', '**/*.ts', '**/*.js'], 5 | exclude: [], 6 | compileTemplate: true, // do not compile tag when its lang is not html 7 | }, 8 | output: { 9 | path: './scripts/i18n/gettextOutput/', // output path of all created files 10 | locales: ['en'], 11 | flat: true, // don't create subdirectories for locales 12 | linguas: false, // create a LINGUAS file 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /src/apiConfig.ts: -------------------------------------------------------------------------------- 1 | export const BASE_URL = 'https://api.webpilotai.com/hyrule/v1' 2 | 3 | export const GOOGLE_CREDENTIAL = 'GOOGLE_CREDENTIAL' 4 | 5 | export const ENDPOINT = { 6 | GET_USER: '/user', 7 | GET_API_USAGE: '/user/apikey/usage', 8 | } 9 | -------------------------------------------------------------------------------- /src/background/messages/openSetting.ts: -------------------------------------------------------------------------------- 1 | const handler = async () => { 2 | chrome.runtime.openOptionsPage() 3 | } 4 | 5 | export default handler 6 | -------------------------------------------------------------------------------- /src/background/messages/popupCheck.ts: -------------------------------------------------------------------------------- 1 | import {sendToContentScript} from '@plasmohq/messaging' 2 | 3 | import {MESSAGING_EVENT} from '@/config' 4 | 5 | const handler = async (req, res) => { 6 | const queryOptions = {active: true, currentWindow: true} 7 | const [tab] = await chrome.tabs.query(queryOptions) 8 | const url = tab?.url 9 | 10 | let keepPopupOpen = true 11 | 12 | if (url) { 13 | keepPopupOpen = url.startsWith('chrome:') || url.startsWith('chrome-extension:') 14 | } 15 | 16 | res.send(keepPopupOpen) 17 | 18 | if (!keepPopupOpen) { 19 | sendToContentScript({ 20 | name: MESSAGING_EVENT.SHOW_POPUP, 21 | }) 22 | } 23 | } 24 | 25 | export default handler 26 | -------------------------------------------------------------------------------- /src/background/messages/signInSuccess.ts: -------------------------------------------------------------------------------- 1 | import {Storage} from '@plasmohq/storage' 2 | 3 | import {GOOGLE_CREDENTIAL} from '@/apiConfig' 4 | 5 | const extensionURL = chrome.runtime.getURL('./tabs/index.html') 6 | 7 | const getCurrentTabId = async () => { 8 | const queryOptions = { 9 | active: true, 10 | lastFocusedWindow: true, 11 | url: ['https://account.webpilot.ai/*', 'http://localhost/*'], 12 | } 13 | // `tab` will either be a `tabs.Tab` instance or `undefined`. 14 | const [tab] = await chrome.tabs.query(queryOptions) 15 | return tab?.id 16 | } 17 | 18 | const handler = async req => { 19 | const storage = new Storage() 20 | const tabId = await getCurrentTabId() 21 | 22 | if (tabId) { 23 | chrome.tabs.update({url: extensionURL}) 24 | } 25 | 26 | const {credential} = req.body 27 | storage.set(GOOGLE_CREDENTIAL, credential) 28 | } 29 | 30 | export default handler 31 | -------------------------------------------------------------------------------- /src/components/DisplayMode.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Pop up 31 | 32 | 33 | 34 | 35 | 36 | 37 | Side Bar 38 | 39 | 40 | 41 | 42 | 43 | 44 | 82 | -------------------------------------------------------------------------------- /src/components/HelpTips.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | {{ value }} 20 | {{ value }} 21 | 22 | 23 | 24 | 46 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseDarkDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CloseLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectDarkDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CollectLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyDarkDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/CopyLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/DeleteLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PencilLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousDarkDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/PreviousLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveDarkDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveDarkDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SaveLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SendDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SendDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SendLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SendLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SendLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingDarkClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingDarkHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingLightClick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingLightDefault.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingLightDisable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/InteractiveIcon/image/SettingLightHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/PromptAreaSelector.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | To get started, please enter API Key from OpenAI Website 5 | 6 | https://platform.openai.com/account/api-keys 9 | 10 | 11 | 12 | 13 | With the selected content “{{ selectedText }}” 15 | 16 | 17 | 18 | 19 | 20 | Answer based on this page “{{ selectedText }}” 22 | 23 | 24 | 25 | 26 | 37 | 38 | 87 | -------------------------------------------------------------------------------- /src/components/PromptList.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | handleSelectPrompt(index)" 10 | @on-edit="() => handleEditPrompt(index)" 11 | /> 12 | 13 | 14 | 15 | 16 | 17 | 54 | 55 | 71 | -------------------------------------------------------------------------------- /src/components/PromptListItem.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ title }} 4 | 5 | 6 | 7 | 8 | 23 | 24 | 49 | -------------------------------------------------------------------------------- /src/components/SendButton/Index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 31 | 32 | 75 | -------------------------------------------------------------------------------- /src/components/ShortcutTips.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 25 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/editActive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/editHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/components/SuperButton/icon/triangle.png -------------------------------------------------------------------------------- /src/components/SuperButton/icon/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/undoActive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/undoHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/webpilot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/webpilotActive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/SuperButton/icon/webpilotHover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/TipsShortcut.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | Shortcut: 4 | 5 | {{ shortcut }} 6 | 7 | 8 | 9 | 10 | 22 | 23 | 53 | -------------------------------------------------------------------------------- /src/components/WebpilotAlert.vue: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{ tips }} 18 | 19 | 20 | 21 | 63 | 64 | 92 | -------------------------------------------------------------------------------- /src/components/WebpilotAttribution.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Powered by Webpilot 5 | 6 | 7 | 8 | 11 | 12 | 31 | -------------------------------------------------------------------------------- /src/components/WebpilotButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | {{ value }} 14 | 15 | 16 | 17 | 51 | 52 | 113 | -------------------------------------------------------------------------------- /src/components/WebpilotCheckbox.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | {{ label }} 11 | 12 | 13 | 14 | 46 | 47 | 90 | -------------------------------------------------------------------------------- /src/components/icon/IconAlertError.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/components/icon/IconAlertInfo.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/icon/IconAlertSuccess.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/icon/IconBackArrow.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/components/icon/IconCheckmark.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/components/icon/IconEnter.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/components/icon/IconJigsaw.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/icon/IllustrationSidebar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/components/image/IconDraggingDark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/image/IconDraggingLight.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/components/image/ImageSelectTextWithoutIcon.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/contents/DiscordMessages.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 57 | 58 | 66 | -------------------------------------------------------------------------------- /src/contents/GithubIssues.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 89 | 90 | 98 | -------------------------------------------------------------------------------- /src/contents/Index.vue: -------------------------------------------------------------------------------- 1 | 73 | -------------------------------------------------------------------------------- /src/contents/SlackMessages.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 48 | 49 | 57 | -------------------------------------------------------------------------------- /src/contents/SlackMessages.vue.bak: -------------------------------------------------------------------------------- 1 | 43 | -------------------------------------------------------------------------------- /src/contents/TwitterMessages.vue: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /src/contents/signInListener.ts: -------------------------------------------------------------------------------- 1 | import {sendToBackground} from '@plasmohq/messaging' 2 | 3 | export const config = { 4 | matches: ['https://account.webpilot.ai/*', 'http://localhost/*', 'https://openai.com/*'], 5 | } 6 | 7 | const handleMessage = event => { 8 | if (event.source === window && event.data && event.data.credential) { 9 | // Send the message to the background script 10 | sendToBackground({ 11 | name: 'signInSuccess', 12 | body: { 13 | credential: event.data.credential, 14 | }, 15 | }) 16 | // chrome.runtime.sendMessage({credential: event.data.credential}) 17 | } 18 | } 19 | 20 | window.addEventListener('message', handleMessage) 21 | -------------------------------------------------------------------------------- /src/csui/GithubIssues/TheEntry.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 65 | -------------------------------------------------------------------------------- /src/csui/Index/TheSidebar/TheSidebar.vue: -------------------------------------------------------------------------------- 1 | 2 | {{ name }} hi? 3 | 4 | 5 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/csui/SlackMessages/TheEntry.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 64 | -------------------------------------------------------------------------------- /src/csui/TwitterInput/TheEntry.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 60 | -------------------------------------------------------------------------------- /src/featureFlagsConfig.ts: -------------------------------------------------------------------------------- 1 | // Hardcode to disable the extisions warning 2 | 3 | globalThis.__VUE_OPTIONS_API__ = false 4 | globalThis.__VUE_PROD_DEVTOOLS__ = false 5 | -------------------------------------------------------------------------------- /src/hooks/useClickoutside.ts: -------------------------------------------------------------------------------- 1 | import {watch} from 'vue' 2 | 3 | export default function useClickOutside(element, onClickOutside) { 4 | const handleMouseClick = e => { 5 | const {target} = e 6 | 7 | if (!target.closest(`#${element.value.$el.id}`)) { 8 | onClickOutside() 9 | } 10 | } 11 | 12 | watch(element, newValue => { 13 | if (newValue?.$el) { 14 | document.addEventListener('mouseup', handleMouseClick) 15 | } else { 16 | document.removeEventListener('mouseup', handleMouseClick) 17 | } 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/hooks/useDraggable.ts: -------------------------------------------------------------------------------- 1 | import {ref, watch, onUnmounted} from 'vue' 2 | 3 | export default function useDraggable(element) { 4 | const originPosition = {x: 0, y: 0} 5 | const lastOffset = {x: 0, y: 0} 6 | const offsetX = ref(0) 7 | const offsetY = ref(0) 8 | const isDragging = ref(false) 9 | 10 | const handleMousemove = e => { 11 | const {clientX: x, clientY: y} = e 12 | const currentOffsetX = x - originPosition.x 13 | const currentOffsetY = y - originPosition.y 14 | 15 | offsetX.value = currentOffsetX + lastOffset.x 16 | offsetY.value = currentOffsetY + lastOffset.y 17 | } 18 | 19 | const startListenMove = e => { 20 | originPosition.x = e.clientX 21 | originPosition.y = e.clientY 22 | 23 | document.addEventListener('mousemove', handleMousemove) 24 | isDragging.value = true 25 | document.addEventListener('mouseup', () => { 26 | lastOffset.x = offsetX.value 27 | lastOffset.y = offsetY.value 28 | document.removeEventListener('mousemove', handleMousemove) 29 | isDragging.value = false 30 | }) 31 | } 32 | 33 | watch(element, v => { 34 | if (v) { 35 | element.value.addEventListener('mousedown', startListenMove) 36 | } else { 37 | element.value?.removeEventListener('mousedown', startListenMove) 38 | } 39 | }) 40 | 41 | onUnmounted(() => { 42 | element.value.removeEventListener('mousedown', startListenMove) 43 | isDragging.value = false 44 | }) 45 | 46 | const resetDrag = () => { 47 | originPosition.x = 0 48 | originPosition.y = 0 49 | lastOffset.x = 0 50 | lastOffset.y = 0 51 | offsetX.value = 0 52 | offsetY.value = 0 53 | } 54 | 55 | return {offsetX, offsetY, resetDrag, isDragging} 56 | } 57 | -------------------------------------------------------------------------------- /src/hooks/useMessage.ts: -------------------------------------------------------------------------------- 1 | import {onMounted, onUnmounted} from 'vue' 2 | 3 | export default function useMessage(handler) { 4 | const metaListener = async (req, sender, sendResponse) => { 5 | await handler?.( 6 | { 7 | ...req, 8 | sender, 9 | }, 10 | { 11 | send: p => sendResponse(p), 12 | } 13 | ) 14 | } 15 | 16 | onMounted(() => { 17 | chrome.runtime.onMessage.addListener(metaListener) 18 | }) 19 | 20 | onUnmounted(() => { 21 | chrome.runtime.onMessage.removeListener(metaListener) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /src/hooks/useScroll.ts: -------------------------------------------------------------------------------- 1 | import {onUnmounted, ref, watch} from 'vue' 2 | 3 | import {getAllScrollableParents} from '@/utils' 4 | 5 | export default function useScroll(element, target) { 6 | const offsetY = ref(0) 7 | 8 | let originY = 0 9 | let scrollableElements = [] 10 | 11 | const getScrollYOffset = () => { 12 | const targetElement = target.value 13 | const {y} = targetElement.getBoundingClientRect() 14 | offsetY.value = y - originY 15 | } 16 | 17 | const addListeners = () => { 18 | scrollableElements.forEach(item => { 19 | item.addEventListener('scroll', getScrollYOffset) 20 | }) 21 | } 22 | 23 | const removeListeners = () => { 24 | scrollableElements.forEach(item => { 25 | item.removeEventListener('scroll', getScrollYOffset) 26 | }) 27 | scrollableElements = [] 28 | } 29 | 30 | watch(element, newValue => { 31 | if (newValue) { 32 | const targetElement = target.value 33 | 34 | if (!targetElement?.getBoundingClientRect) return 35 | 36 | resetScroll() 37 | // get all scrollable parents 38 | scrollableElements = getAllScrollableParents(targetElement) 39 | 40 | const {y} = targetElement.getBoundingClientRect() 41 | 42 | originY = y || 0 43 | 44 | addListeners() 45 | } else { 46 | removeListeners() 47 | } 48 | }) 49 | 50 | onUnmounted(() => { 51 | removeListeners() 52 | }) 53 | 54 | const resetScroll = () => { 55 | const {y} = target.value.getBoundingClientRect() 56 | originY = y 57 | offsetY.value = 0 58 | } 59 | 60 | return {offsetY, resetScroll} 61 | } 62 | -------------------------------------------------------------------------------- /src/hooks/useStopKeyboardEvent.ts: -------------------------------------------------------------------------------- 1 | import {watch} from 'vue' 2 | 3 | export default function useStopKeyboardEvent(target) { 4 | function stopKeyboardEvent(keydownEvent) { 5 | keydownEvent.stopPropagation() 6 | } 7 | 8 | watch(target, (newTarget, oldTarget) => { 9 | if (newTarget) { 10 | newTarget.addEventListener('keydown', stopKeyboardEvent) 11 | } else { 12 | oldTarget.removeEventListener('keydown', stopKeyboardEvent) 13 | } 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /src/hooks/useSuperButtonPrompt.ts: -------------------------------------------------------------------------------- 1 | import {onBeforeMount, ref} from 'vue' 2 | import {Storage} from '@plasmohq/storage' 3 | 4 | const storage = new Storage() 5 | 6 | export default function useSuperButtonPrompt(storageKey, defaultPrompt) { 7 | const prompt = ref(defaultPrompt) 8 | 9 | onBeforeMount(() => { 10 | ;(async function () { 11 | const superButtonPrompt = await getPrompt() 12 | 13 | prompt.value = superButtonPrompt 14 | })() 15 | }) 16 | 17 | async function getPrompt() { 18 | const {superButtonPrompt} = (await storage.get(storageKey)) || { 19 | superButtonPrompt: defaultPrompt, 20 | } 21 | 22 | prompt.value = superButtonPrompt 23 | 24 | return superButtonPrompt 25 | } 26 | 27 | async function setPrompt(superButtonPrompt) { 28 | prompt.value = superButtonPrompt 29 | 30 | await storage.set(storageKey, {superButtonPrompt}) 31 | 32 | return superButtonPrompt 33 | } 34 | 35 | return { 36 | superButtonPrompt: prompt, 37 | getSuperButtonPrompt: getPrompt, 38 | setSuperButtonPrompt: setPrompt, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/options/AboutView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ key }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{ donate?.text }} 15 | 16 | 17 | 18 | 19 | 20 | 40 | 41 | 74 | -------------------------------------------------------------------------------- /src/options/components/ContributorView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ info.name }} 12 | {{ info.name }} 13 | {{ info.bio }} 14 | 15 | 16 | 17 | 25 | 26 | 60 | -------------------------------------------------------------------------------- /src/options/components/CreditRadioGroup.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 16 | Webpilot Credit 17 | 18 | 19 | 20 | 28 | 29 | Open AI Credits 30 | 31 | 32 | 33 | 34 | 35 | 66 | 67 | 96 | -------------------------------------------------------------------------------- /src/options/components/LinkedAccount.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ user }} 5 | UNLINK 6 | 7 | 8 | 9 | 28 | 29 | 57 | -------------------------------------------------------------------------------- /src/options/components/SwitchButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ switchOn ? onText : offText }} 6 | 7 | 8 | 9 | 10 | 31 | 32 | 81 | -------------------------------------------------------------------------------- /src/options/components/WebpilotInput.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 40 | 41 | 73 | -------------------------------------------------------------------------------- /src/options/images/Side_bar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/options/images/bg-signin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/bg-signin.png -------------------------------------------------------------------------------- /src/options/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/default.png -------------------------------------------------------------------------------- /src/options/images/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/dropdown.png -------------------------------------------------------------------------------- /src/options/images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/edit.png -------------------------------------------------------------------------------- /src/options/images/g-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/g-logo.png -------------------------------------------------------------------------------- /src/options/images/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/help.png -------------------------------------------------------------------------------- /src/options/images/icon-about-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/options/images/icon-about-outline.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 23 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/options/images/icon-addon-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/options/images/icon-addon-outline.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 24 | 38 | 50 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/options/images/icon-caret.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/options/images/icon-confirmation.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/options/images/icon-infor-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/options/images/icon-logo-email.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/options/images/icon-logo-github.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/options/images/icon-logo-google.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/options/images/icon-logo-microsoft.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/options/images/icon-logo-twitter.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/options/images/icon-logo.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 13 | 17 | 18 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/options/images/icon-nav-about-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/options/images/icon-nav-about-outline.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/options/images/icon-nav-extension-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/options/images/icon-person-filled.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/options/images/icon-person-outline.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/options/images/icon-question-outline.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/options/images/sign-in-with-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/options/images/sign-in-with-google.png -------------------------------------------------------------------------------- /src/options/index.css: -------------------------------------------------------------------------------- 1 | /* Theme Color */ 2 | 3 | :root { 4 | --default-font-family: 'PingFang SC', sans-serif; 5 | --color-icon-default-and-secondary-text: #585b58; 6 | --color-light-background: #4f5aff1a; 7 | --color-baseline-text: #292929; 8 | --color-brand-primary: #4f5aff; 9 | --color-label-text: #929497; 10 | --color-nav-background-color: #fff; 11 | --color-main-background-color: #fdfdfd; 12 | 13 | box-sizing: border-box; 14 | font-family: var(--default-font-family); 15 | } 16 | 17 | @media (prefers-color-scheme: dark) { 18 | :root { 19 | --color-label-text: #fff; 20 | --color-baseline-text: #fff; 21 | --color-nav-background-color: #323558; 22 | --color-main-background-color: #292d3f; 23 | --color-icon-default-and-secondary-text: #fff; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/options/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | __plasmo_static_index_title__ 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/options/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 29 | -------------------------------------------------------------------------------- /src/options/views/AccountView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | Credit 4 | 5 | 10 | 11 | 12 | 13 | 14 | Linked Account 15 | 16 | 17 | 18 | 58 | 59 | 80 | -------------------------------------------------------------------------------- /src/popup/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | __plasmo_static_index_title__ 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/popup/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | -------------------------------------------------------------------------------- /src/stores/api.ts: -------------------------------------------------------------------------------- 1 | import {ref} from 'vue' 2 | import {defineStore} from 'pinia' 3 | 4 | export const useAPIStore = defineStore('API', () => { 5 | // 'general' | 'personal' 6 | const APIOrigin = ref('general') 7 | 8 | function getOrigin(value) { 9 | // TODO: get API origin 10 | APIOrigin.value = value 11 | } 12 | 13 | function setOrigin(value) { 14 | // TODO: set API origin 15 | APIOrigin.value = value 16 | } 17 | 18 | return {APIOrigin, getOrigin, setOrigin} 19 | }) 20 | -------------------------------------------------------------------------------- /src/stores/user.ts: -------------------------------------------------------------------------------- 1 | import {ref} from 'vue' 2 | import {defineStore} from 'pinia' 3 | 4 | import {Storage} from '@plasmohq/storage' 5 | 6 | import {getUser as getUserInfo, getAPIUsage} from '@/apiService' 7 | import {defaultConfig} from '@/config' 8 | import {GOOGLE_CREDENTIAL} from '@/apiConfig' 9 | 10 | import useStore from './store' 11 | 12 | const useUserStore = defineStore('user', () => { 13 | const user = ref(null) 14 | const isSignedIn = ref(false) 15 | const usage = ref({current: -1, total: 50, percent: '0'}) 16 | 17 | async function getUser() { 18 | const response = await getUserInfo() 19 | 20 | user.value = response.email 21 | isSignedIn.value = response.isSignedIn 22 | } 23 | 24 | async function getUsage() { 25 | const response = await getAPIUsage() 26 | const {current, total} = response 27 | // const {current, total} = {current: 36, total: 50} 28 | const percent = `${(current / total) * 100}%` 29 | // const percent = '36%' 30 | 31 | usage.value = {current, total, percent} 32 | } 33 | 34 | function unlink() { 35 | const store = useStore() 36 | const storage = new Storage() 37 | 38 | // remove google credential 39 | storage.set(GOOGLE_CREDENTIAL, '') 40 | 41 | // reset config 42 | store.updateConfig(defaultConfig) 43 | 44 | // go init page page 45 | const signURL = 'https://account.webpilot.ai/' 46 | chrome.tabs.create({url: signURL}) 47 | } 48 | 49 | return {user, isSignedIn, getUser, usage, getUsage, unlink} 50 | }) 51 | 52 | export default useUserStore 53 | -------------------------------------------------------------------------------- /src/tabs/components/StepFour.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ $gettext('Pin Webpilot') }} 4 | {{ $gettext('Click') }} {{ 6 | $gettext('and pin Webpilot to your nav bar') 7 | }} 9 | 10 | 13 | 14 | 15 | 16 | 29 | 30 | 58 | -------------------------------------------------------------------------------- /src/tabs/components/WelcomeTitle.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 38 | -------------------------------------------------------------------------------- /src/tabs/images/icon-gift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/tabs/images/icon-gift.png -------------------------------------------------------------------------------- /src/tabs/images/key-cap-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/tabs/images/key-cap-big.png -------------------------------------------------------------------------------- /src/tabs/images/key-cap-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/tabs/images/key-cap-small.png -------------------------------------------------------------------------------- /src/tabs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/tabs/images/logo.png -------------------------------------------------------------------------------- /src/tabs/images/signin-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpilot-ai/Webpilot/3f86cb274884658be48d230ac6b6b02f225e546c/src/tabs/images/signin-google.png -------------------------------------------------------------------------------- /src/tabs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | __plasmo_static_index_title__ 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tabs/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | -------------------------------------------------------------------------------- /src/utils/i18n.js: -------------------------------------------------------------------------------- 1 | export function $gettext(text) { 2 | let res = '' 3 | try { 4 | const key = text.replace(/[^A-Za-z0-9_]/g, '_') 5 | res = chrome.i18n.getMessage(key) || text 6 | } catch (e) { 7 | res = text 8 | } 9 | 10 | return res 11 | } 12 | 13 | export const i18nPlugin = { 14 | install(app) { 15 | /* eslint-disable no-param-reassign */ 16 | app.config.globalProperties.$gettext = $gettext 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "plasmo/templates/tsconfig.base", 3 | "exclude": ["node_modules"], 4 | "include": [".plasmo/index.d.ts", "src", "scripts"], 5 | "compilerOptions": { 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["./src/*"], 9 | "@assets/*": ["./assets/*"] 10 | } 11 | } 12 | } 13 | --------------------------------------------------------------------------------