├── link_icon.png ├── style.css ├── manifest.json ├── README.md ├── link_index.html └── app.js /link_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parthpanchal123/Linkaro/HEAD/link_icon.png -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 500px; 3 | height: 500px; 4 | border-top: 1px solid #000; 5 | font-family: "Poppins", sans-serif; 6 | } -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Linkaro", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "browser_action": { 6 | "default_popup": "link_index.html", 7 | "default_icon": "link_icon.png" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Linkaro : A browser extension to store and share your social links easily. 2 | 3 | ## Working 4 | 5 | - Add in your urls and hit the pencil icon . 6 | - The urls will be saved automatically in your browsers local storage 7 | - Now just hit the copy button to copy the link to your clipboard and share the link easily . 8 | 9 | ## Screenshots 10 | 11 | ![](https://i.imgur.com/uDp0KZg.png) 12 | 13 | ## How to use the extension 14 | 15 | - Clone the repository 16 | 17 | `git clone parthpanchal123/Linkaro` 18 | 19 | - Go to extensions in your browser 20 | 21 | ![](https://i.imgur.com/wmnIilX.png) 22 | 23 | - Enable developer options 24 | 25 | ![](https://i.imgur.com/WUvqgVl.png) 26 | 27 | - Click on load unpacked 28 | 29 | ![](https://i.imgur.com/xYkV5W1.png) 30 | 31 | - Simply select the folder where you cloned the Linkaro folder . The extension should be visible in your browser . 32 | 33 | ### Do 🌟 the repo if you liked the extension . 34 | -------------------------------------------------------------------------------- /link_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Linkaro 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 |

Linkaro : Manage your links easily

23 |
24 | 25 | 27 | 28 |
29 | 33 |
34 | 35 |
36 | 37 | Click on the edit button to save after making 38 | required changes
39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // Button Refernce for add new field btn 2 | const addNewBtn = document.getElementById("addNewBtn"); 3 | 4 | // The div that contains all the fields 5 | const linksDiv = document.querySelector(".links-area"); 6 | 7 | /** 8 | * @param {String} key The name of the field 9 | * @param {String} linkData The data of the field 10 | */ 11 | const saveToLocalStorage = (key, linkData) => { 12 | if (!linkData) return; 13 | localStorage.setItem(key, linkData); 14 | }; 15 | 16 | /** 17 | * @param {String} urlData The linkdata of the field 18 | */ 19 | const copyToClipboard = async (urlData) => { 20 | try { 21 | if (!urlData) { 22 | alert("No link to copy ❌ "); 23 | return; 24 | } 25 | await navigator.clipboard.writeText(urlData); 26 | showalert(urlData); 27 | } catch (error) { 28 | alert("Did you give the clipboard permission ?"); 29 | } 30 | }; 31 | 32 | /** 33 | * @param {String} linkData The data of the field 34 | */ 35 | const showalert = (linkData) => { 36 | alert(linkData + " copied to clipboard ✔ "); 37 | }; 38 | 39 | const loadAllFromLocalStorage = () => { 40 | const defaultFields = [ 41 | "Github", 42 | "Linkedin", 43 | "Twitter", 44 | "Portfolio", 45 | "Email", 46 | "Dev", 47 | "Dribbble", 48 | ]; 49 | // An array for custom fields 50 | let customFields = JSON.parse(localStorage.getItem("customFields")) ?? []; 51 | 52 | if (customFields.length != 0) { 53 | customFields.forEach((field) => { 54 | renderFieldsFromLocalStorage({ newFieldName: field, isNewField: false }); 55 | }); 56 | } else { 57 | localStorage.setItem("customFields", JSON.stringify(defaultFields)); 58 | } 59 | }; 60 | /** 61 | * @param {String} newFieldName The name of the field 62 | * @param {Boolean} isNewField A boolean to check if the field is new or not 63 | */ 64 | const renderFieldsFromLocalStorage = ({ newFieldName, isNewField }) => { 65 | const newField = document.createElement("div"); 66 | newField.classList.add( 67 | "flex", 68 | "flex-row", 69 | "justify-center", 70 | "items-center", 71 | "ml-3" 72 | ); 73 | 74 | const iconsHash = { 75 | Github: "fab fa-github", 76 | Linkedin: "fab fa-linkedin", 77 | Twitter: "fab fa-twitter", 78 | Portfolio: "fas fa-globe", 79 | Email: "fas fa-envelope", 80 | Dev: "fab fa-dev", 81 | Dribbble: "fab fa-dribbble", 82 | }; 83 | 84 | const newIcon = document.createElement("i"); 85 | newIcon.style.fontSize = "28px"; 86 | 87 | if (iconsHash[newFieldName]) { 88 | newIcon.classList.add(...iconsHash[newFieldName].split(" ")); 89 | } else { 90 | newIcon.classList.add("fas", "fa-link"); 91 | } 92 | 93 | const newEditIcon = document.createElement("i"); 94 | newEditIcon.classList.add("fas", "fa-edit"); 95 | 96 | const newCopyIcon = document.createElement("i"); 97 | newCopyIcon.classList.add("fas", "fa-copy"); 98 | 99 | const newFieldInput = document.createElement("input"); 100 | newFieldInput.classList.add( 101 | "w-3/5", 102 | "ml-4", 103 | "px-2", 104 | "py-2", 105 | "shadow-md", 106 | "rounded-md", 107 | "text-left" 108 | ); 109 | 110 | newFieldInput.setAttribute("placeholder", newFieldName); 111 | newFieldInput.setAttribute("id", newFieldName); 112 | newFieldInput.value = localStorage.getItem(newFieldName); 113 | newFieldInput.setAttribute("type", "text"); 114 | 115 | const newFieldEditBtn = document.createElement("button"); 116 | newFieldEditBtn.classList.add( 117 | "m-2", 118 | "bg-blue-500", 119 | "hover:bg-blue-700", 120 | "text-white", 121 | "font-bold", 122 | "py-2", 123 | "px-4", 124 | "rounded-md", 125 | "shadow-md" 126 | ); 127 | newFieldEditBtn.setAttribute("id", newFieldName + "EditBtn"); 128 | 129 | newFieldEditBtn.appendChild(newEditIcon); 130 | 131 | newFieldEditBtn.addEventListener("click", () => { 132 | const data = document.getElementById(newFieldName).value; 133 | saveToLocalStorage(newFieldName, data); 134 | }); 135 | 136 | const newFieldCopyBtn = document.createElement("button"); 137 | newFieldCopyBtn.classList.add( 138 | "bg-blue-500", 139 | "hover:bg-blue-700", 140 | "text-white", 141 | "font-bold", 142 | "py-2", 143 | "px-4", 144 | "rounded-md", 145 | "shadow-md" 146 | ); 147 | 148 | newFieldCopyBtn.setAttribute("id", newFieldName + "CopyBtn"); 149 | newFieldCopyBtn.appendChild(newCopyIcon); 150 | 151 | newFieldCopyBtn.addEventListener("click", () => { 152 | const data = document.getElementById(newFieldName).value; 153 | copyToClipboard(data); 154 | }); 155 | 156 | newField.appendChild(newIcon); 157 | newField.appendChild(newFieldInput); 158 | newField.appendChild(newFieldEditBtn); 159 | newField.appendChild(newFieldCopyBtn); 160 | 161 | linksDiv.appendChild(newField); 162 | 163 | if (isNewField) { 164 | let existingFields = JSON.parse(localStorage.getItem("customFields")); 165 | existingFields.push(newFieldName); 166 | localStorage.setItem("customFields", JSON.stringify(existingFields)); 167 | } 168 | }; 169 | 170 | addNewBtn.addEventListener("click", () => { 171 | newFieldName = prompt("Enter a new field name"); 172 | if (!newFieldName) return; 173 | 174 | if (isDuplicateField(newFieldName)) return; 175 | renderFieldsFromLocalStorage({ newFieldName, isNewField: true }); 176 | }); 177 | /** 178 | * @param {String} newLinkName The name of the field 179 | */ 180 | const isDuplicateField = (newLinkName) => { 181 | const links = JSON.parse(localStorage.getItem("customFields")); 182 | 183 | if (!links) return; 184 | 185 | if (links.includes(newLinkName)) { 186 | alert("This field already exists"); 187 | return true; 188 | } 189 | }; 190 | 191 | // Load all the fields from local storage on startup. 192 | document.onload = loadAllFromLocalStorage(); 193 | --------------------------------------------------------------------------------