├── public ├── sites │ ├── any.js │ ├── shopify-cs.js │ ├── supreme.js │ ├── shopify.js │ └── stripe.js ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json ├── index.html └── background.js ├── .env ├── src ├── shared │ ├── actions │ │ ├── settingAction.js │ │ ├── manualAction.js │ │ └── profileAction.js │ ├── reducers │ │ ├── settingReducer.js │ │ ├── index.js │ │ ├── manualReducer.js │ │ └── profileReducer.js │ ├── store │ │ └── index.js │ ├── components │ │ ├── Icon │ │ │ └── index.js │ │ ├── Radio │ │ │ └── index.js │ │ ├── Tabs │ │ │ ├── Tab │ │ │ │ ├── index.js │ │ │ │ └── Styles.js │ │ │ ├── Styles.js │ │ │ └── index.js │ │ ├── Label │ │ │ └── index.js │ │ ├── Input │ │ │ └── index.js │ │ ├── Button │ │ │ └── index.js │ │ └── Select │ │ │ └── index.js │ ├── constants │ │ ├── types.js │ │ └── any.js │ └── utils │ │ └── storage.js ├── App │ ├── Settings │ │ ├── Styles.js │ │ ├── Shopify │ │ │ ├── Styles.js │ │ │ └── index.js │ │ ├── Stripe │ │ │ ├── Styles.js │ │ │ └── index.js │ │ ├── Supreme │ │ │ ├── Styles.js │ │ │ └── index.js │ │ └── index.js │ ├── Styles.js │ ├── Manual │ │ ├── index.js │ │ ├── SelectorForm │ │ │ └── index.js │ │ ├── Styles.js │ │ └── SiteForm │ │ │ └── index.js │ ├── Profile │ │ ├── index.js │ │ ├── Styles.js │ │ ├── ProfileSelector │ │ │ └── index.js │ │ └── ProfileForm │ │ │ └── index.js │ ├── BaseStyles.js │ ├── index.js │ └── NormalizeStyles.js ├── index.js └── serviceWorker.js ├── .gitignore ├── README.md ├── package.json └── LICENSE /public/sites/any.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | INLINE_RUNTIME_CHUNK=false -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericz99/autofill-extension/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericz99/autofill-extension/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericz99/autofill-extension/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/shared/actions/settingAction.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_CONFIG } from "../constants/types"; 2 | 3 | export const setConfig = (options) => { 4 | return { 5 | type: UPDATE_CONFIG, 6 | payload: options, 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /src/shared/reducers/settingReducer.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_CONFIG } from "../constants/types"; 2 | 3 | const initialState = {}; 4 | 5 | export default function (state = initialState, action) { 6 | switch (action.type) { 7 | case UPDATE_CONFIG: 8 | return action.payload; 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/shared/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from "redux"; 2 | import profileReducer from "./profileReducer"; 3 | import settingReducer from "./settingReducer"; 4 | import manualReducer from "./manualReducer"; 5 | 6 | export default combineReducers({ 7 | profile: profileReducer, 8 | setting: settingReducer, 9 | manual: manualReducer, 10 | }); 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/shared/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from "redux"; 2 | import { composeWithDevTools } from "redux-devtools-extension"; 3 | import thunk from "redux-thunk"; 4 | import rootReducer from "../reducers"; 5 | 6 | const initialState = {}; 7 | const middleware = [thunk]; 8 | 9 | export default createStore( 10 | rootReducer, 11 | initialState, 12 | composeWithDevTools(applyMiddleware(...middleware)) 13 | ); 14 | -------------------------------------------------------------------------------- /src/App/Settings/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | position: relative; 7 | `; 8 | 9 | export const Header = styled.h5` 10 | font-weight: 500; 11 | margin-bottom: 10px; 12 | `; 13 | 14 | export const ActiveProfileSelector = styled.div` 15 | display: block; 16 | position: relative; 17 | margin-bottom: 15px; 18 | `; 19 | -------------------------------------------------------------------------------- /src/App/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Wrapper = styled.div` 4 | position: relative; 5 | display: block; 6 | padding: 25px; 7 | width: 350px; 8 | min-height: 600px; 9 | max-height: 600px; 10 | height: 600px; 11 | background-image: linear-gradient(#222231 750px, #191824 100%); 12 | color: #ffffff; 13 | font-family: "Montserrat", sans-serif; 14 | `; 15 | 16 | export const Tab = styled.div``; 17 | -------------------------------------------------------------------------------- /src/App/Manual/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useSelector } from "react-redux"; 3 | 4 | import SelectorForm from "./SelectorForm"; 5 | import SiteForm from "./SiteForm"; 6 | 7 | import { Wrapper } from "./Styles"; 8 | 9 | export default function Manual() { 10 | const { sites, selectedSite } = useSelector((state) => state.manual); 11 | 12 | return ( 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/App/Profile/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useSelector } from "react-redux"; 3 | 4 | import ProfileForm from "./ProfileForm"; 5 | import ProfileSelector from "./ProfileSelector"; 6 | 7 | import { Wrapper } from "./Styles"; 8 | 9 | export default function Profile() { 10 | const { selectedProfile } = useSelector((state) => state.profile); 11 | 12 | return ( 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/shared/components/Icon/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 3 | import styled from "styled-components"; 4 | 5 | export const IconStyle = styled.i` 6 | @media (max-width: 1100px) { 7 | transition: all ease-in-out 0.3s; 8 | &:hover { 9 | border-radius: 10px; 10 | transition: all ease-in-out 0.3s; 11 | } 12 | } 13 | `; 14 | 15 | export default function Icon({ icon }) { 16 | return ( 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/shared/components/Radio/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import Checkbox from "rc-checkbox"; 4 | 5 | export const Label = styled.label` 6 | margin-left: 15px; 7 | `; 8 | 9 | export default function Radio({ 10 | defaultCheck, 11 | type, 12 | onChange, 13 | name, 14 | ...props 15 | }) { 16 | return ( 17 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/shared/components/Tabs/Tab/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { TabStyled, TabBody, TabHead } from "./Styles"; 4 | 5 | export default function Tab({ activeTab, label, onClick, ...props }) { 6 | const handleActiveTab = () => { 7 | // # set back activetab 8 | onClick(label); 9 | }; 10 | 11 | return ( 12 | 17 | 18 | {label} 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/shared/actions/manualAction.js: -------------------------------------------------------------------------------- 1 | import { 2 | CREATED_NEW_SITE, 3 | UPDATED_NEW_SITE, 4 | SELECTED_SITE, 5 | } from "../constants/types"; 6 | 7 | export const addNewSite = (site) => (dispatch) => { 8 | dispatch({ 9 | type: CREATED_NEW_SITE, 10 | payload: site, 11 | }); 12 | }; 13 | 14 | export const updateSite = (sites) => (dispatch) => { 15 | dispatch({ 16 | type: UPDATED_NEW_SITE, 17 | payload: sites, 18 | }); 19 | }; 20 | 21 | export const selectSite = (site) => (dispatch) => { 22 | dispatch({ 23 | type: SELECTED_SITE, 24 | payload: site, 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /src/shared/components/Label/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | 4 | import { IconStyle } from "../Icon"; 5 | 6 | export const LabelStyled = styled.span` 7 | display: flex; 8 | align-items: center; 9 | font-size: 14px; 10 | margin-bottom: 10px; 11 | color: ${(props) => props.color}; 12 | font-weight: 500; 13 | ${IconStyle} { 14 | padding: 8px; 15 | font-weight: 200; 16 | color: rgba(65, 76, 86, 0.6); 17 | } 18 | `; 19 | 20 | export default function Label({ children, color }) { 21 | return {children}; 22 | } 23 | -------------------------------------------------------------------------------- /src/shared/constants/types.js: -------------------------------------------------------------------------------- 1 | export const CREATED_PROFILE = "CREATED_PROFILE"; 2 | export const DELETED_PROFILE = "DELETED_PROFILE"; 3 | export const UPDATED_PROFILE = "UPDATED_PROFILE"; 4 | export const LOAD_CONFIG = "LOAD_CONFIG"; 5 | export const UPDATE_CONFIG = "UPDATE_CONFIG"; 6 | export const SET_LOADING = "SET_LOADING"; 7 | export const GET_ERROR = "GET_ERROR"; 8 | export const SELECTED_PROFILE = "SELECTED_PROFILE"; 9 | export const SET_ACTIVE_PROFILE = "SET_ACTIVE_PROFILE"; 10 | export const CREATED_NEW_SITE = "CREATED_NEW_SITE"; 11 | export const UPDATED_NEW_SITE = "UPDATED_NEW_SITE"; 12 | export const SELECTED_SITE = "SELECTED_SITE"; 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Provider } from "react-redux"; 4 | import "rc-checkbox/assets/index.css"; 5 | 6 | import App from "./App"; 7 | import * as serviceWorker from "./serviceWorker"; 8 | 9 | import store from "./shared/store"; 10 | 11 | ReactDOM.render( 12 | 13 | 14 | 15 | 16 | , 17 | document.getElementById("root") 18 | ); 19 | 20 | // If you want your app to work offline and load faster, you can change 21 | // unregister() to register() below. Note this comes with some pitfalls. 22 | // Learn more about service workers: https://bit.ly/CRA-PWA 23 | serviceWorker.unregister(); 24 | -------------------------------------------------------------------------------- /src/shared/reducers/manualReducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | CREATED_NEW_SITE, 3 | UPDATED_NEW_SITE, 4 | SELECTED_SITE, 5 | } from "../constants/types"; 6 | 7 | const initialState = { 8 | sites: [], 9 | selectedSite: {}, 10 | }; 11 | 12 | export default function (state = initialState, action) { 13 | switch (action.type) { 14 | case CREATED_NEW_SITE: 15 | return { 16 | ...state, 17 | sites: [...state.sites, action.payload], 18 | }; 19 | case UPDATED_NEW_SITE: 20 | return { 21 | ...state, 22 | sites: action.payload, 23 | }; 24 | case SELECTED_SITE: 25 | return { 26 | ...state, 27 | selectedSite: action.payload, 28 | }; 29 | default: 30 | return state; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/shared/components/Tabs/Tab/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const TabBody = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | width: 100%; 7 | `; 8 | 9 | export const TabHead = styled.h3` 10 | flex: 1; 11 | color: rgba(149, 165, 166, 1); 12 | font-size: 14px; 13 | font-weight: 100; 14 | background: none; 15 | `; 16 | 17 | export const TabDetail = styled.p` 18 | flex: 1; 19 | font-size: 14px; 20 | margin-top: 10px; 21 | color: rgba(171, 183, 183, 1); 22 | `; 23 | 24 | export const TabStyled = styled.li` 25 | display: inline-block; 26 | position: relative; 27 | border-bottom: 2px solid #e8e8e8; 28 | cursor: pointer; 29 | margin: 0 15px 0 0; 30 | height: 25px; 31 | 32 | &.active { 33 | border-bottom: 2px solid #2574a9; 34 | ${TabHead} { 35 | color: #2574a9; 36 | } 37 | } 38 | `; 39 | -------------------------------------------------------------------------------- /src/shared/constants/any.js: -------------------------------------------------------------------------------- 1 | // # DEFAULT PROFILE 2 | export const testProfile = { 3 | profileName: "Test Profile", 4 | firstName: "Test", 5 | lastName: "Profile", 6 | email: "TestProfile@gmail.com", 7 | phone: "1234567890", 8 | address: "123 Main Street", 9 | address2: "Apartment 1", 10 | city: "New York", 11 | state: "NY", 12 | zipCode: "10001", 13 | cardName: "Test Profile", 14 | cardNumber: "1234567891234567", 15 | expMonth: "01", 16 | expYear: "2020", 17 | cvv: "123", 18 | country: "United States", 19 | }; 20 | 21 | // # DEFAULT CONFIG 22 | export const defaultConfig = { 23 | shopify: { 24 | navigateSteps: true, 25 | processPayment: false, 26 | skipToCheckout: false, 27 | }, 28 | supreme: { 29 | checkTerms: false, 30 | processPayment: false, 31 | }, 32 | stripe: { 33 | autofill: false, 34 | processPayment: false, 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /src/shared/components/Tabs/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const TabStyled = styled.div` 4 | display: flex; 5 | position: relative; 6 | height: 100%; 7 | width: 100%; 8 | flex-direction: column; 9 | `; 10 | 11 | export const TabList = styled.ul` 12 | list-style: none; 13 | display: flex; 14 | justify-content: flex-start; 15 | flex: 1; 16 | padding: 0; 17 | margin: 0; 18 | `; 19 | 20 | export const Tab = styled.li` 21 | display: flex; 22 | `; 23 | 24 | export const TabBody = styled.div` 25 | display: flex; 26 | `; 27 | 28 | export const TabHead = styled.h3` 29 | flex: 1; 30 | `; 31 | 32 | export const TabDetail = styled.p` 33 | flex: 1; 34 | `; 35 | 36 | export const TabContent = styled.div` 37 | flex: 10; 38 | font-size: 14px; 39 | display: block; 40 | overflow-x: hidden; 41 | overflow-y: auto; 42 | -webkit-overflow-scrolling: touch; 43 | `; 44 | -------------------------------------------------------------------------------- /src/App/Settings/Shopify/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const SiteWrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | flex-wrap: wrap; 7 | margin-bottom: 25px; 8 | `; 9 | 10 | export const SiteHeader = styled.div` 11 | display: flex; 12 | position: relative; 13 | align-items: center; 14 | padding: 0 65px; 15 | 16 | &:before { 17 | content: ""; 18 | display: inline-block; 19 | position: absolute; 20 | left: 0; 21 | height: 2px; 22 | width: 15%; 23 | background: #ffffff; 24 | } 25 | 26 | &:after { 27 | content: ""; 28 | display: inline-block; 29 | position: absolute; 30 | right: 0; 31 | height: 2px; 32 | width: 55%; 33 | background: #ffffff; 34 | } 35 | `; 36 | 37 | export const SiteRadio = styled.div` 38 | flex: 1; 39 | display: flex; 40 | align-items: center; 41 | margin-top: 15px; 42 | font-size: 13px; 43 | `; 44 | -------------------------------------------------------------------------------- /src/App/Settings/Stripe/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const SiteWrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | flex-wrap: wrap; 7 | margin-bottom: 25px; 8 | `; 9 | 10 | export const SiteHeader = styled.div` 11 | display: flex; 12 | position: relative; 13 | align-items: center; 14 | padding: 0 65px; 15 | 16 | &:before { 17 | content: ""; 18 | display: inline-block; 19 | position: absolute; 20 | left: 0; 21 | height: 2px; 22 | width: 15%; 23 | background: #ffffff; 24 | } 25 | 26 | &:after { 27 | content: ""; 28 | display: inline-block; 29 | position: absolute; 30 | right: 0; 31 | height: 2px; 32 | width: 58%; 33 | background: #ffffff; 34 | } 35 | `; 36 | 37 | export const SiteRadio = styled.div` 38 | flex: 1; 39 | display: flex; 40 | align-items: center; 41 | margin-top: 15px; 42 | font-size: 13px; 43 | `; 44 | -------------------------------------------------------------------------------- /src/App/Settings/Supreme/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const SiteWrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | flex-wrap: wrap; 7 | margin-bottom: 25px; 8 | `; 9 | 10 | export const SiteHeader = styled.div` 11 | display: flex; 12 | position: relative; 13 | align-items: center; 14 | padding: 0 65px; 15 | 16 | &:before { 17 | content: ""; 18 | display: inline-block; 19 | position: absolute; 20 | left: 0; 21 | height: 2px; 22 | width: 15%; 23 | background: #ffffff; 24 | } 25 | 26 | &:after { 27 | content: ""; 28 | display: inline-block; 29 | position: absolute; 30 | right: 0; 31 | height: 2px; 32 | width: 50%; 33 | background: #ffffff; 34 | } 35 | `; 36 | 37 | export const SiteRadio = styled.div` 38 | flex: 1; 39 | display: flex; 40 | align-items: center; 41 | margin-top: 15px; 42 | font-size: 13px; 43 | `; 44 | -------------------------------------------------------------------------------- /src/shared/actions/profileAction.js: -------------------------------------------------------------------------------- 1 | import { 2 | CREATED_PROFILE, 3 | DELETED_PROFILE, 4 | UPDATED_PROFILE, 5 | SELECTED_PROFILE, 6 | SET_ACTIVE_PROFILE, 7 | } from "../constants/types"; 8 | 9 | export const addProfile = (profileData) => (dispatch) => { 10 | dispatch({ 11 | type: CREATED_PROFILE, 12 | payload: profileData, 13 | }); 14 | }; 15 | 16 | export const deleteProfile = (idx) => (dispatch) => { 17 | dispatch({ 18 | type: DELETED_PROFILE, 19 | payload: idx, 20 | }); 21 | }; 22 | 23 | export const updateProfile = (profiles) => (dispatch) => { 24 | dispatch({ 25 | type: UPDATED_PROFILE, 26 | payload: profiles, 27 | }); 28 | }; 29 | 30 | export const selectProfile = (profile) => (dispatch) => { 31 | dispatch({ 32 | type: SELECTED_PROFILE, 33 | payload: profile, 34 | }); 35 | }; 36 | 37 | export const setActiveProfile = (profile) => (dispatch) => { 38 | dispatch({ 39 | type: SET_ACTIVE_PROFILE, 40 | payload: profile, 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "AIO Extension", 4 | "author": "Eric Zhang", 5 | "version": "1.0.0", 6 | "browser_action": { 7 | "default_popup": "index.html", 8 | "default_title": "AIO Extension" 9 | }, 10 | "permissions": ["storage", "tabs", "cookies", "https://*/*", "http://*/*"], 11 | "background": { 12 | "scripts": ["background.js"] 13 | }, 14 | "content_scripts" : [ 15 | { 16 | "matches": ["https://*/*/checkouts/*"], 17 | "js": ["sites/shopify.js"] 18 | }, 19 | { 20 | "matches": ["https://*.shopifycs.com/*"], 21 | "js": ["sites/shopify-cs.js"], 22 | "all_frames": true 23 | }, 24 | { 25 | "run_at": "document_end", 26 | "matches": ["https://checkout.stripe.com/*", "https://*.stripe.com/*"], 27 | "js": ["sites/stripe.js"], 28 | "all_frames": true 29 | }, 30 | { 31 | "matches": ["https://www.supremenewyork.com/checkout"], 32 | "js": ["sites/supreme.js"], 33 | "all_frames": true 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /src/shared/components/Tabs/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | 3 | import Tab from "./Tab"; 4 | 5 | import { TabStyled, TabList, TabContent } from "./Styles"; 6 | 7 | export default function Tabs({ children }) { 8 | const [activeTab, setActiveTab] = useState(children[0].props.label); 9 | 10 | const handleSetActiveTab = (tab) => { 11 | setActiveTab(tab); 12 | }; 13 | 14 | return ( 15 | 16 | 17 | {children.map((child) => { 18 | const { label } = child.props; 19 | 20 | return ( 21 | 27 | ); 28 | })} 29 | 30 | 31 | 32 | {children.map((child) => { 33 | if (child.props.label !== activeTab) return undefined; 34 | return child.props.children; 35 | })} 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AIO Extension 2 | 3 | Easy to use chrome extension, follow the installation below to get started! 4 | 5 | ## Installation 6 | 7 | 1. In your preferred directiory, run `git clone https://github.com/ericz99/aio-extension`. 8 | 2. Go to chrome://extensions/. 9 | 3. Enable Developer mode. 10 | 4. Run `cd aio-extension && yarn run build`. 11 | 5. Unpack the `build` folder. 12 | 13 | ## Features 14 | 15 | - Autofill, preset site, eg: shopify, supreme, stripe. 16 | - Shopify request based checkout. 17 | - DIY autofill. 18 | - many more... 19 | 20 | ## Todo 21 | 22 | - [ ] Manual DIY Autofill (CURRENTLY NOT WORKING) 23 | 24 | ## Pictures 25 | 26 | ![picture1](https://i.imgur.com/BQsUu24.png) 27 | 28 | ![picture2](https://i.gyazo.com/b7ab36e04e6015624c513b2474ed3ffc.png) 29 | 30 | ![picture3](https://i.gyazo.com/95235c0d5259706eec4ee1b651bf9dbd.png) 31 | 32 | ## App Info 33 | 34 | ### Author 35 | 36 | Eric Zhang 37 | 38 | ### Version 39 | 40 | 1.0.0 41 | 42 | ### License 43 | 44 | This project is licensed under the GPL-3.0 LICENSE - see the [LICENSE](LICENSE) file for details -------------------------------------------------------------------------------- /src/App/Manual/SelectorForm/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDispatch } from "react-redux"; 3 | 4 | import { selectSite } from "../../../shared/actions/manualAction"; 5 | import Select from "../../../shared/components/Select"; 6 | 7 | import { Row, FormControl } from "../Styles"; 8 | 9 | export default function SelectorForm({ sites }) { 10 | const dispatch = useDispatch(); 11 | 12 | const handleOnChange = (e) => { 13 | const { value } = e.target; 14 | 15 | sites.forEach((item) => { 16 | if (item.siteName.trim().toLowerCase() === value.trim().toLowerCase()) { 17 | // # dispatch to redux state 18 | dispatch(selectSite(item)); 19 | } 20 | }); 21 | }; 22 | 23 | return ( 24 | 25 | 26 | 37 | 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/App/Manual/Styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | position: relative; 7 | `; 8 | 9 | export const SmallHelpText = styled.small` 10 | display: block; 11 | font-size: 11px; 12 | color: rgba(65, 76, 86, 1); 13 | line-height: 18px; 14 | margin-top: 5px; 15 | `; 16 | 17 | export const Form = styled.form` 18 | display: flex; 19 | flex-direction: column; 20 | position: relative; 21 | width: 100%; 22 | `; 23 | 24 | export const FormControl = styled.div` 25 | display: block; 26 | margin: 0 0 10px 0; 27 | width: 100%; 28 | flex: 1; 29 | `; 30 | 31 | export const SplitControl = styled.div` 32 | display: block; 33 | width: 100%; 34 | flex: 1; 35 | margin-bottom: 10px; 36 | 37 | &:nth-child(1) { 38 | margin-right: 5px; 39 | } 40 | 41 | &:nth-child(3) { 42 | margin-left: 5px; 43 | } 44 | `; 45 | 46 | export const Row = styled.div` 47 | display: flex; 48 | `; 49 | 50 | export const Header = styled.div` 51 | font-size: 14px; 52 | font-weight: 100; 53 | display: block; 54 | text-align: center; 55 | margin-bottom: 15px; 56 | `; 57 | 58 | export const ButtonGroup = styled.div` 59 | display: flex; 60 | flex-direction: row; 61 | width: 100%; 62 | margin-bottom: 10px; 63 | `; 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aio-extension", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@fortawesome/fontawesome-svg-core": "^1.2.29", 7 | "@fortawesome/free-solid-svg-icons": "^5.13.1", 8 | "@fortawesome/react-fontawesome": "^0.1.11", 9 | "@testing-library/jest-dom": "^4.2.4", 10 | "@testing-library/react": "^9.3.2", 11 | "@testing-library/user-event": "^7.1.2", 12 | "rc-checkbox": "^2.2.0", 13 | "react": "^16.13.1", 14 | "react-dom": "^16.13.1", 15 | "react-hook-form": "^5.7.2", 16 | "react-redux": "^7.2.0", 17 | "react-router-dom": "^5.2.0", 18 | "react-scripts": "3.4.1", 19 | "redux": "^4.0.5", 20 | "redux-devtools-extension": "^2.13.8", 21 | "redux-thunk": "^2.3.0", 22 | "styled-components": "^5.1.1" 23 | }, 24 | "scripts": { 25 | "start": "react-scripts start", 26 | "build": "react-scripts build", 27 | "test": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": "react-app" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/shared/utils/storage.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | // # gets all profile stored in local storage 3 | export const getProfiles = () => { 4 | return JSON.parse(localStorage.getItem("profiles")); 5 | }; 6 | 7 | // # save profiles to local storage 8 | export const saveProfiles = (profiles) => { 9 | localStorage.setItem("profiles", JSON.stringify(profiles)); 10 | }; 11 | 12 | // # get settings 13 | export const getSettings = () => { 14 | return JSON.parse(localStorage.getItem("settings")); 15 | }; 16 | 17 | // # save settings 18 | export const saveSettings = (settings) => { 19 | localStorage.setItem("settings", JSON.stringify(settings)); 20 | chrome.storage.local.set({ settings: settings }); 21 | }; 22 | 23 | // # set current profile 24 | export const setCurrentProfile = (profile) => { 25 | localStorage.setItem("activeProfile", JSON.stringify(profile)); 26 | chrome.storage.local.set({ activeProfile: profile }); 27 | }; 28 | 29 | // # get current profile 30 | export const getCurrentProfile = () => { 31 | return JSON.parse(localStorage.getItem("activeProfile")); 32 | }; 33 | 34 | // # set manaual site 35 | export const setManualSite = (sites) => { 36 | localStorage.setItem("manualSites", JSON.stringify(sites)); 37 | chrome.storage.local.set({ manualSites: sites }); 38 | }; 39 | 40 | // # get current profile 41 | export const getManualSite = () => { 42 | return JSON.parse(localStorage.getItem("manualSites")); 43 | }; 44 | -------------------------------------------------------------------------------- /src/App/Settings/Shopify/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Radio from "../../../shared/components/Radio"; 4 | 5 | import { SiteHeader, SiteWrapper, SiteRadio } from "./Styles"; 6 | 7 | export default function Shopify({ handleChange, settings }) { 8 | const handleOptionUpdate = (name) => { 9 | handleChange(name); 10 | }; 11 | 12 | return ( 13 | <> 14 | 15 | Shopify 16 | 17 | Navigate Steps 18 | handleOptionUpdate("navigateSteps")} 20 | name="navigateSteps" 21 | defaultCheck={settings["shopify"]["navigateSteps"]} 22 | type="checkbox" 23 | /> 24 | 25 | 26 | Process Payment 27 | handleOptionUpdate("processPayment")} 29 | name="processPayment" 30 | defaultCheck={settings["shopify"]["processPayment"]} 31 | type="checkbox" 32 | /> 33 | 34 | 35 | Skip To Checkout 36 | handleOptionUpdate("skipToCheckout")} 38 | name="skipToCheckout" 39 | defaultCheck={settings["shopify"]["skipToCheckout"]} 40 | type="checkbox" 41 | /> 42 | 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /public/sites/shopify-cs.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | let activeProfile; 3 | let currentConfig; 4 | 5 | // # FETCH ACTIVE PROFILE 6 | chrome.storage.local.get(["activeProfile"], (result) => { 7 | activeProfile = result.activeProfile; 8 | }); 9 | 10 | // # FETCH USER SETTINGS FOR SHOPIFY ONLY 11 | chrome.storage.local.get(["settings"], (result) => { 12 | currentConfig = result.settings; 13 | _init(); 14 | }); 15 | 16 | // chrome.extension.onMessage.addListener((request, sender, sendResponse) => { 17 | // console.log(request); 18 | 19 | // switch (request.cmd) { 20 | // case "retryCheckout": 21 | // return processCheckout(); 22 | // default: 23 | // break; 24 | // } 25 | // }); 26 | 27 | // # process the checkout 28 | const processCheckout = () => { 29 | chrome.runtime.sendMessage({ cmd: "processCheckout" }); 30 | }; 31 | 32 | const _init = () => { 33 | // # fill in profile 34 | fillDataInfo(activeProfile); 35 | }; 36 | 37 | // # FILLS SHIPPING INFO 38 | const fillDataInfo = (profile) => { 39 | // # fill in card data 40 | fillInfo("number", profile.cardNumber); 41 | fillInfo("name", `${profile.cardName}`); 42 | fillInfo("expiry", `${profile.expMonth}/${profile.expYear.slice(2)}`); 43 | fillInfo("verification_value", profile.cvv); 44 | 45 | // # initalize checkout 46 | processCheckout(); 47 | }; 48 | 49 | // # fill in information for specific fields 50 | function fillInfo(id, value, byName = false) { 51 | let element = document[byName ? "getElementsByName" : "getElementById"](id); 52 | if (byName) element = element[0]; 53 | 54 | if (element) { 55 | const event = new Event("change", { bubbles: true }); 56 | element.focus(); 57 | element.value = value; 58 | element.dispatchEvent(event); 59 | element.blur(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 23 | AIO Extension 24 | 25 | 26 | 27 |
28 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/App/Settings/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDispatch, useSelector } from "react-redux"; 3 | 4 | import { setActiveProfile } from "../../shared/actions/profileAction"; 5 | import { setConfig } from "../../shared/actions/settingAction"; 6 | import { saveSettings, setCurrentProfile } from "../../shared/utils/storage"; 7 | import Select from "../../shared/components/Select"; 8 | 9 | import Shopify from "./Shopify"; 10 | import Supreme from "./Supreme"; 11 | import Stripe from "./Stripe"; 12 | 13 | import { Wrapper, ActiveProfileSelector, Header } from "./Styles"; 14 | 15 | export default function Settings() { 16 | const { profiles, activeProfile } = useSelector((state) => state.profile); 17 | const settings = useSelector((state) => state.setting); 18 | const dispatch = useDispatch(); 19 | 20 | const updateSettings = (site, name) => { 21 | let newConfig = settings; 22 | // # UPDATE CONFIG 23 | newConfig[site][name] = !newConfig[site][name]; 24 | // # UPDATE REDUX STATE 25 | dispatch(setConfig(newConfig)); 26 | // # UPDATE CONFIG IN LOCALSTORAGE 27 | saveSettings(newConfig); 28 | }; 29 | 30 | const handleActiveProfile = (e) => { 31 | const { value } = e.target; 32 | 33 | // # FETCH THE PROFILE 34 | profiles.forEach((profile) => { 35 | if (profile.profileName.trim() === value.trim()) { 36 | // # SELECT AS PROFILE 37 | dispatch(setActiveProfile(profile)); 38 | // # STORE TO LOCALSTORAGE 39 | setCurrentProfile(profile); 40 | } 41 | }); 42 | }; 43 | 44 | return ( 45 | 46 | 47 |
Active Profile
48 |