diff --git a/bookmarks.html b/bookmarks.html new file mode 100644 index 0000000..42faaba --- /dev/null +++ b/bookmarks.html @@ -0,0 +1,14 @@ + + + + + + + + + Bookmarks + + + + + diff --git a/bookmarks.js b/bookmarks.js new file mode 100644 index 0000000..f857dba --- /dev/null +++ b/bookmarks.js @@ -0,0 +1,80 @@ +import { categorizeByDate } from "./utils/categorize.js"; + +window.addEventListener("DOMContentLoaded", function () { + let bookmarks = document.createElement("div"); + bookmarks.id = "bookmarks"; + + const categoriesList = document.createElement("ul"); + categoriesList.id = "categories-list"; + const searchHistoryArray = JSON.parse( + localStorage.getItem("search-history") || "[]" + ); + const categories = categorizeByDate(searchHistoryArray); + console.log(categories); + + const sortedKeys = Object.keys(categories).sort((a, b) => { + if (a.includes("Today")) return -1; + if (b.includes("Today")) return 1; + if (a.includes("Yesterday")) return -1; + if (b.includes("Yesterday")) return 1; + if (a.includes("Last 7 days")) return -1; + if (b.includes("Last 7 days")) return 1; + if (a.includes("Older")) return -1; + if (b.includes("Older")) return 1; + return 0; + }); + + sortedKeys.forEach((key) => { + const category = document.createElement("li"); + category.className = "category"; + const categoryTitle = document.createElement("h4"); + categoryTitle.innerText = key; + category.appendChild(categoryTitle); + const categoryList = document.createElement("ul"); + categoryList.className = "category-list"; + categories[key].forEach((item) => { + let marks = document.createElement("ul"); + marks.className = "marks"; + const itemLi = document.createElement("li"); + itemLi.className = "item"; + const itemLink = document.createElement("a"); + const time = document.createElement("div"); + time.className = "time"; + time.innerText = new Date(item.time).toLocaleTimeString(); + let button = document.createElement("button"); + button.innerHTML = ""; + button.addEventListener("click", function () { + const sHistory = JSON.parse( + localStorage.getItem("bookmarks") + ).filter((i) => i.id !== item.id); + localStorage.setItem("bookmarks", JSON.stringify(sHistory)); + itemLi.remove(); + if (categoriesList.children.length === 0) { + let li = document.createElement("li"); + li.textContent = "No Bookmarks"; + categoriesList.appendChild(li); + } + }); + itemLink.href = item.url; + itemLink.innerText = item.url.slice( + item.url.indexOf("//") + 2, + item.url.indexOf("/", item.url.indexOf("//") + 2) + ); + itemLink.target = "_blank"; + itemLi.appendChild(itemLink); + itemLi.appendChild(time); + itemLi.appendChild(button); + marks.appendChild(itemLi); + category.appendChild(marks); + categoriesList.appendChild(category); + }); + }); + + if (categoriesList.children.length === 0) { + let li = document.createElement("li"); + li.textContent = "No Bookmarks"; + categoriesList.appendChild(li); + } + bookmarks.appendChild(categoriesList); + document.body.appendChild(bookmarks); +}); diff --git a/components/BookmarkBtn.js b/components/BookmarkBtn.js new file mode 100644 index 0000000..fc33d14 --- /dev/null +++ b/components/BookmarkBtn.js @@ -0,0 +1,24 @@ +const { + addBookmark, + getBookmarks, + removeFromBookmarks, +} = require("../utils/handleLocalStorage"); + +const BookmarkBtn = () => { + const bookmarkBtn = document.createElement("button"); + bookmarkBtn.id = "bookmark-btn"; + bookmarkBtn.innerHTML = ''; + bookmarkBtn.addEventListener("click", function () { + bookmarkBtn.classList.toggle("active"); + const bookmarks = getBookmarks(); + const activeWebview = document.querySelector(".active-webview"); + const url = activeWebview.src; + if (!bookmarks.find((item) => item.url === url)) { + addBookmark(url); + } else { + removeFromBookmarks(url); + } + }); + return bookmarkBtn; +}; +module.exports = BookmarkBtn; diff --git a/components/LocationForm.js b/components/LocationForm.js index 300dae8..7caa40e 100644 --- a/components/LocationForm.js +++ b/components/LocationForm.js @@ -1,14 +1,14 @@ const goToLocation = require("../utils/goToLocation"); const LocationForm = () => { + const container = document.createElement("div"); const locationForm = document.createElement("form"); - + container.classList.add("location-container"); const location = document.createElement("input"); locationForm.id = "location-form"; location.id = "location-input"; location.type = "text"; location.value = "https://www.unelma.xyz/"; - locationForm.appendChild(location); locationForm.addEventListener("submit", (e) => { e.preventDefault(); @@ -16,4 +16,4 @@ const LocationForm = () => { }); return locationForm; }; -module.exports = LocationForm; \ No newline at end of file +module.exports = LocationForm; diff --git a/components/Menu.js b/components/Menu.js new file mode 100644 index 0000000..0fb2d97 --- /dev/null +++ b/components/Menu.js @@ -0,0 +1,48 @@ +const addTab = require("../utils/addTab"); +const { getCurrentTabs } = require("../utils/handleLocalStorage"); + +const menuItems = [ + { + name: "Bookmarks", + url: "bookmarks.html", + icon: "bookmark", + }, + { + name: "History", + url: "history.html", + icon: "history", + }, +]; + +const Menu = () => { + const menu = document.createElement("div"); + menu.id = "menu"; + const menuList = document.createElement("ul"); + menuList.id = "menu-list"; + const bookmarks = document.createElement("li"); + bookmarks.id = "bookmarks"; + menuItems.forEach((item) => { + const menuItem = document.createElement("li"); + menuItem.classList.add("menu-item"); + menuItem.innerHTML = ` ${item.name}`; + menuItem.addEventListener("click", () => { + menu.classList.remove("open"); + const historyTab = getCurrentTabs().find( + (item) => item.url === "history.html" + ); + const bookmarksTab = getCurrentTabs().find( + (item) => item.url === "bookmarks.html" + ); + if (!historyTab && item.url === "history.html") { + addTab("history.html"); + } + if (!bookmarksTab && item.url === "bookmarks.html") { + addTab("bookmarks.html"); + } + }); + menuList.appendChild(menuItem); + }); + menu.appendChild(menuList); + return menu; +}; +module.exports = Menu; diff --git a/components/MenuButton.js b/components/MenuButton.js new file mode 100644 index 0000000..3421a91 --- /dev/null +++ b/components/MenuButton.js @@ -0,0 +1,11 @@ +const MenuButton = () => { + const menuButton = document.createElement("div"); + menuButton.id = "menu-button"; + menuButton.innerHTML = ''; + menuButton.addEventListener("click", () => { + const menu = document.getElementById("menu"); + menu.classList.toggle("open"); + }); + return menuButton; +}; +module.exports = MenuButton; diff --git a/components/NavigationControls.js b/components/NavigationControls.js index 02a5b68..1cdb5f6 100644 --- a/components/NavigationControls.js +++ b/components/NavigationControls.js @@ -9,7 +9,7 @@ const NavigationControls = () => { navigationControlsForward.innerHTML = ''; const navigationControlsReload = document.createElement("button"); navigationControlsReload.id = "navigation-controls-reload"; - navigationControlsReload.innerHTML = ''; + navigationControlsReload.innerHTML = ''; navigationControls.appendChild(navigationControlsBack); navigationControls.appendChild(navigationControlsForward); navigationControls.appendChild(navigationControlsReload); diff --git a/components/Sidebar.js b/components/Sidebar.js index 17c03d6..a7a5ca8 100644 --- a/components/Sidebar.js +++ b/components/Sidebar.js @@ -1,4 +1,7 @@ +const BookmarkBtn = require("./BookmarkBtn"); const LocationForm = require("./LocationForm"); +const Menu = require("./Menu"); +const MenuButton = require("./MenuButton"); const NavigationControls = require("./NavigationControls"); const TabsList = require("./TabsList"); const WindowControllers = require("./WindowControllers"); @@ -8,10 +11,13 @@ const Sidebar = () => { appSidebar.id = "app-sidebar"; const controllers = document.createElement("div"); controllers.id = "controllers"; - controllers.appendChild(WindowControllers()); - controllers.appendChild(NavigationControls()); + controllers.appendChild(MenuButton()); + controllers.appendChild(WindowControllers()); + controllers.appendChild(BookmarkBtn()); + controllers.appendChild(NavigationControls()); appSidebar.appendChild(controllers); appSidebar.appendChild(LocationForm()); + appSidebar.appendChild(Menu()); appSidebar.appendChild(TabsList()); return appSidebar; }; diff --git a/components/Tab.js b/components/Tab.js index 6043777..41c84d0 100644 --- a/components/Tab.js +++ b/components/Tab.js @@ -1,11 +1,15 @@ const { ipcRenderer } = require("electron"); +const { + setCurrentTabs, + getCurrentTabs, + getBookmarks, +} = require("../utils/handleLocalStorage"); const Tab = (input, id) => { const tab = document.createElement("div"); const tabContent = document.createElement("div"); const closeTab = document.createElement("button"); tab.classList.add("tab"); tab.id = `tab-${id}`; - setTimeout(() => (tabContent.textContent = "Unelma Search"), 300); closeTab.innerHTML = "✖"; tabContent.classList.add("content"); closeTab.classList.add("close"); @@ -19,13 +23,22 @@ const Tab = (input, id) => { [...document.querySelectorAll(".active-webview")].forEach((t) => { t.classList.remove("active-webview"); }); - + const currentView = document.getElementById(`webview-${id}`); tab.classList.add("active-tab"); currentView.classList.add("active-webview"); - input.value = currentView.getURL(); + + input.value = currentView.getURL(); + const bookmarks = getBookmarks(); + const bookmarkBtn = document.getElementById("bookmark-btn"); + if (bookmarks.find((item) => item.url === input.value)) + bookmarkBtn.classList.add("active"); + else bookmarkBtn.classList.remove("active"); }); closeTab.addEventListener("click", function () { + const currentTabs = getCurrentTabs(); + const newTabs = currentTabs.filter((tab) => tab.id !== id); + setCurrentTabs(newTabs); const tabs = document.getElementById("actual-tabs").children; if (tabs.length === 1) { ipcRenderer.send("close-window"); @@ -34,7 +47,6 @@ const Tab = (input, id) => { const tabIndex = [...tabs].findIndex((t) => t.id.endsWith(id)); const viewIndex = [...views].findIndex((t) => t.id.endsWith(id)); if (tab.classList.contains("active-tab")) { - tabs[tabIndex].remove(); views[viewIndex].remove(); tabs[tabIndex === 0 ? tabIndex + 1 : tabIndex - 1].classList.add( @@ -48,6 +60,11 @@ const Tab = (input, id) => { views[viewIndex].remove(); } } + const bookmarks = getBookmarks(); + const bookmarkBtn = document.getElementById("bookmark-btn"); + if (bookmarks.find((item) => item.url === input.value)) + bookmarkBtn.classList.add("active"); + else bookmarkBtn.classList.remove("active"); }); return tab; }; diff --git a/components/TopBar.js b/components/TopBar.js new file mode 100644 index 0000000..6231548 --- /dev/null +++ b/components/TopBar.js @@ -0,0 +1,30 @@ +const handleMaximization = require("../utils/handleMaximization"); +const TopBar = () => { + const topBar = document.createElement("div"); + topBar.classList.add("top-bar"); + const windowControlsClose = document.createElement("button"); + windowControlsClose.id = "window-controls-close"; + windowControlsClose.innerHTML = ''; + const windowControlsMinimize = document.createElement("button"); + windowControlsMinimize.id = "window-controls-minimize"; + windowControlsMinimize.innerHTML = ''; + const windowControlsMaximize = document.createElement("button"); + windowControlsMaximize.id = "window-controls-maximize"; + windowControlsMaximize.innerHTML = ''; + + const windowControlsUnmaximize = document.createElement("button"); + windowControlsUnmaximize.id = "window-controls-unmaximize"; + windowControlsUnmaximize.innerHTML = ''; + handleMaximization( + windowControlsUnmaximize, + windowControlsMaximize, + windowControlsClose, + windowControlsMinimize + ); + topBar.appendChild(windowControlsMinimize); + topBar.appendChild(windowControlsMaximize); + topBar.appendChild(windowControlsUnmaximize); + topBar.appendChild(windowControlsClose); + return topBar; +}; +module.exports = TopBar; \ No newline at end of file diff --git a/components/Webview.js b/components/Webview.js index f9e0e37..0aa46f5 100644 --- a/components/Webview.js +++ b/components/Webview.js @@ -17,14 +17,17 @@ const Webview = (id, url) => { const currentTab = document.getElementById(`tab-${id}`); currentTab.children[0].textContent = "Loading..."; }); + webview.addEventListener("did-finish-load", () => { const currentTab = document.getElementById(`tab-${id}`); - currentTab.children[0].textContent = webview.getTitle() + currentTab.children[0].textContent = webview.getTitle(); + }); webview.addEventListener("did-frame-finish-load", () => { const currentTab = document.getElementById(`tab-${id}`); currentTab.children[0].textContent = webview.getTitle(); document.getElementById("location-input").value = webview.getURL(); + }); return webview; }; diff --git a/components/WindowControllers.js b/components/WindowControllers.js index a103486..97388cc 100644 --- a/components/WindowControllers.js +++ b/components/WindowControllers.js @@ -1,36 +1,11 @@ -const handleMaximization = require("../utils/handleMaximization"); - const WindowControllers = () => { const windowControls = document.createElement("div"); - windowControls.id = "window-controllers"; - const windowControlsClose = document.createElement("button"); - windowControlsClose.id = "window-controls-close"; - windowControlsClose.innerHTML = ''; - const windowControlsMinimize = document.createElement("button"); - windowControlsMinimize.id = "window-controls-minimize"; - windowControlsMinimize.innerHTML = ''; - const windowControlsMaximize = document.createElement("button"); - windowControlsMaximize.id = "window-controls-maximize"; - windowControlsMaximize.innerHTML = ''; - - const windowControlsUnmaximize = document.createElement("button"); - windowControlsUnmaximize.id = "window-controls-unmaximize"; - windowControlsUnmaximize.innerHTML = ''; - - windowControls.appendChild(windowControlsClose); - windowControls.appendChild(windowControlsMinimize); - windowControls.appendChild(windowControlsMaximize); - windowControls.appendChild(windowControlsUnmaximize); + windowControls.id = "window-controllers" const toggleBtn = document.createElement("button"); toggleBtn.id = "toggle-btn"; toggleBtn.innerHTML = 'toggle'; windowControls.appendChild(toggleBtn); - handleMaximization( - windowControlsUnmaximize, - windowControlsMaximize, - windowControlsClose, - windowControlsMinimize - ); + toggleBtn.addEventListener("click", () => { const sidebar = document.getElementById("app-sidebar"); if (!sidebar.classList.contains("toggled-sidebar")) { diff --git a/css/bookmarks.css b/css/bookmarks.css new file mode 100644 index 0000000..366a4f8 --- /dev/null +++ b/css/bookmarks.css @@ -0,0 +1,79 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: Lucida Grande, Arial, sans-serif; + background-color: transparent; +} +body::-webkit-scrollbar { + width: 0px; +} +button, +input { + outline: none; + border: 0; + background: none; +} +button { + cursor: pointer; +} +a { + text-decoration: none; + color: rgb(73, 87, 107); + display: block; + width: 200px; +} +ul { + list-style: none; +} +#bookmarks { + border-radius: 7px; + display: flex; + padding: 30px; + width: 100%; +} +#categories-list { + width: 100%; +} +#bookmarks .category { + display: flex; + list-style: none; + flex-direction: column; + width: 100%; + border: 1px solid rgba(216, 220, 226, 0.37); + border-radius: 10px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + padding: 15px; + margin-bottom: 20px; +} +#bookmarks .category-list > li { + display: flex; + list-style: none; + flex-direction: column; + width: 100%; + padding: 15px 10px; + margin-bottom: 10px; +} +.history { + width: 100%; +} +.item { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + +} +h4 { + border-bottom: 1px solid rgba(211, 211, 211, 0.575); + padding: 20px; + margin-bottom: 10px; + text-transform: capitalize; +} +.time { + font-weight: bold; + font-size: 14px; +} \ No newline at end of file diff --git a/css/font-awesome.css b/css/font-awesome.css deleted file mode 100644 index 2995ba0..0000000 --- a/css/font-awesome.css +++ /dev/null @@ -1,2343 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') - format('embedded-opentype'), - url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), - url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), - url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), - url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') - format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: 0.2em 0.25em 0.15em; - border: solid 0.08em #eeeeee; - border-radius: 0.1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: 0.3em; -} -.fa.fa-pull-right { - margin-left: 0.3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: 0.3em; -} -.fa.pull-right { - margin-left: 0.3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2)'; - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)'; - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)'; - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)'; - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: '\f000'; -} -.fa-music:before { - content: '\f001'; -} -.fa-search:before { - content: '\f002'; -} -.fa-envelope-o:before { - content: '\f003'; -} -.fa-heart:before { - content: '\f004'; -} -.fa-star:before { - content: '\f005'; -} -.fa-star-o:before { - content: '\f006'; -} -.fa-user:before { - content: '\f007'; -} -.fa-film:before { - content: '\f008'; -} -.fa-th-large:before { - content: '\f009'; -} -.fa-th:before { - content: '\f00a'; -} -.fa-th-list:before { - content: '\f00b'; -} -.fa-check:before { - content: '\f00c'; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: '\f00d'; -} -.fa-search-plus:before { - content: '\f00e'; -} -.fa-search-minus:before { - content: '\f010'; -} -.fa-power-off:before { - content: '\f011'; -} -.fa-signal:before { - content: '\f012'; -} -.fa-gear:before, -.fa-cog:before { - content: '\f013'; -} -.fa-trash-o:before { - content: '\f014'; -} -.fa-home:before { - content: '\f015'; -} -.fa-file-o:before { - content: '\f016'; -} -.fa-clock-o:before { - content: '\f017'; -} -.fa-road:before { - content: '\f018'; -} -.fa-download:before { - content: '\f019'; -} -.fa-arrow-circle-o-down:before { - content: '\f01a'; -} -.fa-arrow-circle-o-up:before { - content: '\f01b'; -} -.fa-inbox:before { - content: '\f01c'; -} -.fa-play-circle-o:before { - content: '\f01d'; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: '\f01e'; -} -.fa-refresh:before { - content: '\f021'; -} -.fa-list-alt:before { - content: '\f022'; -} -.fa-lock:before { - content: '\f023'; -} -.fa-flag:before { - content: '\f024'; -} -.fa-headphones:before { - content: '\f025'; -} -.fa-volume-off:before { - content: '\f026'; -} -.fa-volume-down:before { - content: '\f027'; -} -.fa-volume-up:before { - content: '\f028'; -} -.fa-qrcode:before { - content: '\f029'; -} -.fa-barcode:before { - content: '\f02a'; -} -.fa-tag:before { - content: '\f02b'; -} -.fa-tags:before { - content: '\f02c'; -} -.fa-book:before { - content: '\f02d'; -} -.fa-bookmark:before { - content: '\f02e'; -} -.fa-print:before { - content: '\f02f'; -} -.fa-camera:before { - content: '\f030'; -} -.fa-font:before { - content: '\f031'; -} -.fa-bold:before { - content: '\f032'; -} -.fa-italic:before { - content: '\f033'; -} -.fa-text-height:before { - content: '\f034'; -} -.fa-text-width:before { - content: '\f035'; -} -.fa-align-left:before { - content: '\f036'; -} -.fa-align-center:before { - content: '\f037'; -} -.fa-align-right:before { - content: '\f038'; -} -.fa-align-justify:before { - content: '\f039'; -} -.fa-list:before { - content: '\f03a'; -} -.fa-dedent:before, -.fa-outdent:before { - content: '\f03b'; -} -.fa-indent:before { - content: '\f03c'; -} -.fa-video-camera:before { - content: '\f03d'; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: '\f03e'; -} -.fa-pencil:before { - content: '\f040'; -} -.fa-map-marker:before { - content: '\f041'; -} -.fa-adjust:before { - content: '\f042'; -} -.fa-tint:before { - content: '\f043'; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: '\f044'; -} -.fa-share-square-o:before { - content: '\f045'; -} -.fa-check-square-o:before { - content: '\f046'; -} -.fa-arrows:before { - content: '\f047'; -} -.fa-step-backward:before { - content: '\f048'; -} -.fa-fast-backward:before { - content: '\f049'; -} -.fa-backward:before { - content: '\f04a'; -} -.fa-play:before { - content: '\f04b'; -} -.fa-pause:before { - content: '\f04c'; -} -.fa-stop:before { - content: '\f04d'; -} -.fa-forward:before { - content: '\f04e'; -} -.fa-fast-forward:before { - content: '\f050'; -} -.fa-step-forward:before { - content: '\f051'; -} -.fa-eject:before { - content: '\f052'; -} -.fa-chevron-left:before { - content: '\f053'; -} -.fa-chevron-right:before { - content: '\f054'; -} -.fa-plus-circle:before { - content: '\f055'; -} -.fa-minus-circle:before { - content: '\f056'; -} -.fa-times-circle:before { - content: '\f057'; -} -.fa-check-circle:before { - content: '\f058'; -} -.fa-question-circle:before { - content: '\f059'; -} -.fa-info-circle:before { - content: '\f05a'; -} -.fa-crosshairs:before { - content: '\f05b'; -} -.fa-times-circle-o:before { - content: '\f05c'; -} -.fa-check-circle-o:before { - content: '\f05d'; -} -.fa-ban:before { - content: '\f05e'; -} -.fa-arrow-left:before { - content: '\f060'; -} -.fa-arrow-right:before { - content: '\f061'; -} -.fa-arrow-up:before { - content: '\f062'; -} -.fa-arrow-down:before { - content: '\f063'; -} -.fa-mail-forward:before, -.fa-share:before { - content: '\f064'; -} -.fa-expand:before { - content: '\f065'; -} -.fa-compress:before { - content: '\f066'; -} -.fa-plus:before { - content: '\f067'; -} -.fa-minus:before { - content: '\f068'; -} -.fa-asterisk:before { - content: '\f069'; -} -.fa-exclamation-circle:before { - content: '\f06a'; -} -.fa-gift:before { - content: '\f06b'; -} -.fa-leaf:before { - content: '\f06c'; -} -.fa-fire:before { - content: '\f06d'; -} -.fa-eye:before { - content: '\f06e'; -} -.fa-eye-slash:before { - content: '\f070'; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: '\f071'; -} -.fa-plane:before { - content: '\f072'; -} -.fa-calendar:before { - content: '\f073'; -} -.fa-random:before { - content: '\f074'; -} -.fa-comment:before { - content: '\f075'; -} -.fa-magnet:before { - content: '\f076'; -} -.fa-chevron-up:before { - content: '\f077'; -} -.fa-chevron-down:before { - content: '\f078'; -} -.fa-retweet:before { - content: '\f079'; -} -.fa-shopping-cart:before { - content: '\f07a'; -} -.fa-folder:before { - content: '\f07b'; -} -.fa-folder-open:before { - content: '\f07c'; -} -.fa-arrows-v:before { - content: '\f07d'; -} -.fa-arrows-h:before { - content: '\f07e'; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: '\f080'; -} -.fa-twitter-square:before { - content: '\f081'; -} -.fa-facebook-square:before { - content: '\f082'; -} -.fa-camera-retro:before { - content: '\f083'; -} -.fa-key:before { - content: '\f084'; -} -.fa-gears:before, -.fa-cogs:before { - content: '\f085'; -} -.fa-comments:before { - content: '\f086'; -} -.fa-thumbs-o-up:before { - content: '\f087'; -} -.fa-thumbs-o-down:before { - content: '\f088'; -} -.fa-star-half:before { - content: '\f089'; -} -.fa-heart-o:before { - content: '\f08a'; -} -.fa-sign-out:before { - content: '\f08b'; -} -.fa-linkedin-square:before { - content: '\f08c'; -} -.fa-thumb-tack:before { - content: '\f08d'; -} -.fa-external-link:before { - content: '\f08e'; -} -.fa-sign-in:before { - content: '\f090'; -} -.fa-trophy:before { - content: '\f091'; -} -.fa-github-square:before { - content: '\f092'; -} -.fa-upload:before { - content: '\f093'; -} -.fa-lemon-o:before { - content: '\f094'; -} -.fa-phone:before { - content: '\f095'; -} -.fa-square-o:before { - content: '\f096'; -} -.fa-bookmark-o:before { - content: '\f097'; -} -.fa-phone-square:before { - content: '\f098'; -} -.fa-twitter:before { - content: '\f099'; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: '\f09a'; -} -.fa-github:before { - content: '\f09b'; -} -.fa-unlock:before { - content: '\f09c'; -} -.fa-credit-card:before { - content: '\f09d'; -} -.fa-feed:before, -.fa-rss:before { - content: '\f09e'; -} -.fa-hdd-o:before { - content: '\f0a0'; -} -.fa-bullhorn:before { - content: '\f0a1'; -} -.fa-bell:before { - content: '\f0f3'; -} -.fa-certificate:before { - content: '\f0a3'; -} -.fa-hand-o-right:before { - content: '\f0a4'; -} -.fa-hand-o-left:before { - content: '\f0a5'; -} -.fa-hand-o-up:before { - content: '\f0a6'; -} -.fa-hand-o-down:before { - content: '\f0a7'; -} -.fa-arrow-circle-left:before { - content: '\f0a8'; -} -.fa-arrow-circle-right:before { - content: '\f0a9'; -} -.fa-arrow-circle-up:before { - content: '\f0aa'; -} -.fa-arrow-circle-down:before { - content: '\f0ab'; -} -.fa-globe:before { - content: '\f0ac'; -} -.fa-wrench:before { - content: '\f0ad'; -} -.fa-tasks:before { - content: '\f0ae'; -} -.fa-filter:before { - content: '\f0b0'; -} -.fa-briefcase:before { - content: '\f0b1'; -} -.fa-arrows-alt:before { - content: '\f0b2'; -} -.fa-group:before, -.fa-users:before { - content: '\f0c0'; -} -.fa-chain:before, -.fa-link:before { - content: '\f0c1'; -} -.fa-cloud:before { - content: '\f0c2'; -} -.fa-flask:before { - content: '\f0c3'; -} -.fa-cut:before, -.fa-scissors:before { - content: '\f0c4'; -} -.fa-copy:before, -.fa-files-o:before { - content: '\f0c5'; -} -.fa-paperclip:before { - content: '\f0c6'; -} -.fa-save:before, -.fa-floppy-o:before { - content: '\f0c7'; -} -.fa-square:before { - content: '\f0c8'; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: '\f0c9'; -} -.fa-list-ul:before { - content: '\f0ca'; -} -.fa-list-ol:before { - content: '\f0cb'; -} -.fa-strikethrough:before { - content: '\f0cc'; -} -.fa-underline:before { - content: '\f0cd'; -} -.fa-table:before { - content: '\f0ce'; -} -.fa-magic:before { - content: '\f0d0'; -} -.fa-truck:before { - content: '\f0d1'; -} -.fa-pinterest:before { - content: '\f0d2'; -} -.fa-pinterest-square:before { - content: '\f0d3'; -} -.fa-google-plus-square:before { - content: '\f0d4'; -} -.fa-google-plus:before { - content: '\f0d5'; -} -.fa-money:before { - content: '\f0d6'; -} -.fa-caret-down:before { - content: '\f0d7'; -} -.fa-caret-up:before { - content: '\f0d8'; -} -.fa-caret-left:before { - content: '\f0d9'; -} -.fa-caret-right:before { - content: '\f0da'; -} -.fa-columns:before { - content: '\f0db'; -} -.fa-unsorted:before, -.fa-sort:before { - content: '\f0dc'; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: '\f0dd'; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: '\f0de'; -} -.fa-envelope:before { - content: '\f0e0'; -} -.fa-linkedin:before { - content: '\f0e1'; -} -.fa-rotate-left:before, -.fa-undo:before { - content: '\f0e2'; -} -.fa-legal:before, -.fa-gavel:before { - content: '\f0e3'; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: '\f0e4'; -} -.fa-comment-o:before { - content: '\f0e5'; -} -.fa-comments-o:before { - content: '\f0e6'; -} -.fa-flash:before, -.fa-bolt:before { - content: '\f0e7'; -} -.fa-sitemap:before { - content: '\f0e8'; -} -.fa-umbrella:before { - content: '\f0e9'; -} -.fa-paste:before, -.fa-clipboard:before { - content: '\f0ea'; -} -.fa-lightbulb-o:before { - content: '\f0eb'; -} -.fa-exchange:before { - content: '\f0ec'; -} -.fa-cloud-download:before { - content: '\f0ed'; -} -.fa-cloud-upload:before { - content: '\f0ee'; -} -.fa-user-md:before { - content: '\f0f0'; -} -.fa-stethoscope:before { - content: '\f0f1'; -} -.fa-suitcase:before { - content: '\f0f2'; -} -.fa-bell-o:before { - content: '\f0a2'; -} -.fa-coffee:before { - content: '\f0f4'; -} -.fa-cutlery:before { - content: '\f0f5'; -} -.fa-file-text-o:before { - content: '\f0f6'; -} -.fa-building-o:before { - content: '\f0f7'; -} -.fa-hospital-o:before { - content: '\f0f8'; -} -.fa-ambulance:before { - content: '\f0f9'; -} -.fa-medkit:before { - content: '\f0fa'; -} -.fa-fighter-jet:before { - content: '\f0fb'; -} -.fa-beer:before { - content: '\f0fc'; -} -.fa-h-square:before { - content: '\f0fd'; -} -.fa-plus-square:before { - content: '\f0fe'; -} -.fa-angle-double-left:before { - content: '\f100'; -} -.fa-angle-double-right:before { - content: '\f101'; -} -.fa-angle-double-up:before { - content: '\f102'; -} -.fa-angle-double-down:before { - content: '\f103'; -} -.fa-angle-left:before { - content: '\f104'; -} -.fa-angle-right:before { - content: '\f105'; -} -.fa-angle-up:before { - content: '\f106'; -} -.fa-angle-down:before { - content: '\f107'; -} -.fa-desktop:before { - content: '\f108'; -} -.fa-laptop:before { - content: '\f109'; -} -.fa-tablet:before { - content: '\f10a'; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: '\f10b'; -} -.fa-circle-o:before { - content: '\f10c'; -} -.fa-quote-left:before { - content: '\f10d'; -} -.fa-quote-right:before { - content: '\f10e'; -} -.fa-spinner:before { - content: '\f110'; -} -.fa-circle:before { - content: '\f111'; -} -.fa-mail-reply:before, -.fa-reply:before { - content: '\f112'; -} -.fa-github-alt:before { - content: '\f113'; -} -.fa-folder-o:before { - content: '\f114'; -} -.fa-folder-open-o:before { - content: '\f115'; -} -.fa-smile-o:before { - content: '\f118'; -} -.fa-frown-o:before { - content: '\f119'; -} -.fa-meh-o:before { - content: '\f11a'; -} -.fa-gamepad:before { - content: '\f11b'; -} -.fa-keyboard-o:before { - content: '\f11c'; -} -.fa-flag-o:before { - content: '\f11d'; -} -.fa-flag-checkered:before { - content: '\f11e'; -} -.fa-terminal:before { - content: '\f120'; -} -.fa-code:before { - content: '\f121'; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: '\f122'; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: '\f123'; -} -.fa-location-arrow:before { - content: '\f124'; -} -.fa-crop:before { - content: '\f125'; -} -.fa-code-fork:before { - content: '\f126'; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: '\f127'; -} -.fa-question:before { - content: '\f128'; -} -.fa-info:before { - content: '\f129'; -} -.fa-exclamation:before { - content: '\f12a'; -} -.fa-superscript:before { - content: '\f12b'; -} -.fa-subscript:before { - content: '\f12c'; -} -.fa-eraser:before { - content: '\f12d'; -} -.fa-puzzle-piece:before { - content: '\f12e'; -} -.fa-microphone:before { - content: '\f130'; -} -.fa-microphone-slash:before { - content: '\f131'; -} -.fa-shield:before { - content: '\f132'; -} -.fa-calendar-o:before { - content: '\f133'; -} -.fa-fire-extinguisher:before { - content: '\f134'; -} -.fa-rocket:before { - content: '\f135'; -} -.fa-maxcdn:before { - content: '\f136'; -} -.fa-chevron-circle-left:before { - content: '\f137'; -} -.fa-chevron-circle-right:before { - content: '\f138'; -} -.fa-chevron-circle-up:before { - content: '\f139'; -} -.fa-chevron-circle-down:before { - content: '\f13a'; -} -.fa-html5:before { - content: '\f13b'; -} -.fa-css3:before { - content: '\f13c'; -} -.fa-anchor:before { - content: '\f13d'; -} -.fa-unlock-alt:before { - content: '\f13e'; -} -.fa-bullseye:before { - content: '\f140'; -} -.fa-ellipsis-h:before { - content: '\f141'; -} -.fa-ellipsis-v:before { - content: '\f142'; -} -.fa-rss-square:before { - content: '\f143'; -} -.fa-play-circle:before { - content: '\f144'; -} -.fa-ticket:before { - content: '\f145'; -} -.fa-minus-square:before { - content: '\f146'; -} -.fa-minus-square-o:before { - content: '\f147'; -} -.fa-level-up:before { - content: '\f148'; -} -.fa-level-down:before { - content: '\f149'; -} -.fa-check-square:before { - content: '\f14a'; -} -.fa-pencil-square:before { - content: '\f14b'; -} -.fa-external-link-square:before { - content: '\f14c'; -} -.fa-share-square:before { - content: '\f14d'; -} -.fa-compass:before { - content: '\f14e'; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: '\f150'; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: '\f151'; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: '\f152'; -} -.fa-euro:before, -.fa-eur:before { - content: '\f153'; -} -.fa-gbp:before { - content: '\f154'; -} -.fa-dollar:before, -.fa-usd:before { - content: '\f155'; -} -.fa-rupee:before, -.fa-inr:before { - content: '\f156'; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: '\f157'; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: '\f158'; -} -.fa-won:before, -.fa-krw:before { - content: '\f159'; -} -.fa-bitcoin:before, -.fa-btc:before { - content: '\f15a'; -} -.fa-file:before { - content: '\f15b'; -} -.fa-file-text:before { - content: '\f15c'; -} -.fa-sort-alpha-asc:before { - content: '\f15d'; -} -.fa-sort-alpha-desc:before { - content: '\f15e'; -} -.fa-sort-amount-asc:before { - content: '\f160'; -} -.fa-sort-amount-desc:before { - content: '\f161'; -} -.fa-sort-numeric-asc:before { - content: '\f162'; -} -.fa-sort-numeric-desc:before { - content: '\f163'; -} -.fa-thumbs-up:before { - content: '\f164'; -} -.fa-thumbs-down:before { - content: '\f165'; -} -.fa-youtube-square:before { - content: '\f166'; -} -.fa-youtube:before { - content: '\f167'; -} -.fa-xing:before { - content: '\f168'; -} -.fa-xing-square:before { - content: '\f169'; -} -.fa-youtube-play:before { - content: '\f16a'; -} -.fa-dropbox:before { - content: '\f16b'; -} -.fa-stack-overflow:before { - content: '\f16c'; -} -.fa-instagram:before { - content: '\f16d'; -} -.fa-flickr:before { - content: '\f16e'; -} -.fa-adn:before { - content: '\f170'; -} -.fa-bitbucket:before { - content: '\f171'; -} -.fa-bitbucket-square:before { - content: '\f172'; -} -.fa-tumblr:before { - content: '\f173'; -} -.fa-tumblr-square:before { - content: '\f174'; -} -.fa-long-arrow-down:before { - content: '\f175'; -} -.fa-long-arrow-up:before { - content: '\f176'; -} -.fa-long-arrow-left:before { - content: '\f177'; -} -.fa-long-arrow-right:before { - content: '\f178'; -} -.fa-apple:before { - content: '\f179'; -} -.fa-windows:before { - content: '\f17a'; -} -.fa-android:before { - content: '\f17b'; -} -.fa-linux:before { - content: '\f17c'; -} -.fa-dribbble:before { - content: '\f17d'; -} -.fa-skype:before { - content: '\f17e'; -} -.fa-foursquare:before { - content: '\f180'; -} -.fa-trello:before { - content: '\f181'; -} -.fa-female:before { - content: '\f182'; -} -.fa-male:before { - content: '\f183'; -} -.fa-gittip:before, -.fa-gratipay:before { - content: '\f184'; -} -.fa-sun-o:before { - content: '\f185'; -} -.fa-moon-o:before { - content: '\f186'; -} -.fa-archive:before { - content: '\f187'; -} -.fa-bug:before { - content: '\f188'; -} -.fa-vk:before { - content: '\f189'; -} -.fa-weibo:before { - content: '\f18a'; -} -.fa-renren:before { - content: '\f18b'; -} -.fa-pagelines:before { - content: '\f18c'; -} -.fa-stack-exchange:before { - content: '\f18d'; -} -.fa-arrow-circle-o-right:before { - content: '\f18e'; -} -.fa-arrow-circle-o-left:before { - content: '\f190'; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: '\f191'; -} -.fa-dot-circle-o:before { - content: '\f192'; -} -.fa-wheelchair:before { - content: '\f193'; -} -.fa-vimeo-square:before { - content: '\f194'; -} -.fa-turkish-lira:before, -.fa-try:before { - content: '\f195'; -} -.fa-plus-square-o:before { - content: '\f196'; -} -.fa-space-shuttle:before { - content: '\f197'; -} -.fa-slack:before { - content: '\f198'; -} -.fa-envelope-square:before { - content: '\f199'; -} -.fa-wordpress:before { - content: '\f19a'; -} -.fa-openid:before { - content: '\f19b'; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: '\f19c'; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: '\f19d'; -} -.fa-yahoo:before { - content: '\f19e'; -} -.fa-google:before { - content: '\f1a0'; -} -.fa-reddit:before { - content: '\f1a1'; -} -.fa-reddit-square:before { - content: '\f1a2'; -} -.fa-stumbleupon-circle:before { - content: '\f1a3'; -} -.fa-stumbleupon:before { - content: '\f1a4'; -} -.fa-delicious:before { - content: '\f1a5'; -} -.fa-digg:before { - content: '\f1a6'; -} -.fa-pied-piper-pp:before { - content: '\f1a7'; -} -.fa-pied-piper-alt:before { - content: '\f1a8'; -} -.fa-drupal:before { - content: '\f1a9'; -} -.fa-joomla:before { - content: '\f1aa'; -} -.fa-language:before { - content: '\f1ab'; -} -.fa-fax:before { - content: '\f1ac'; -} -.fa-building:before { - content: '\f1ad'; -} -.fa-child:before { - content: '\f1ae'; -} -.fa-paw:before { - content: '\f1b0'; -} -.fa-spoon:before { - content: '\f1b1'; -} -.fa-cube:before { - content: '\f1b2'; -} -.fa-cubes:before { - content: '\f1b3'; -} -.fa-behance:before { - content: '\f1b4'; -} -.fa-behance-square:before { - content: '\f1b5'; -} -.fa-steam:before { - content: '\f1b6'; -} -.fa-steam-square:before { - content: '\f1b7'; -} -.fa-recycle:before { - content: '\f1b8'; -} -.fa-automobile:before, -.fa-car:before { - content: '\f1b9'; -} -.fa-cab:before, -.fa-taxi:before { - content: '\f1ba'; -} -.fa-tree:before { - content: '\f1bb'; -} -.fa-spotify:before { - content: '\f1bc'; -} -.fa-deviantart:before { - content: '\f1bd'; -} -.fa-soundcloud:before { - content: '\f1be'; -} -.fa-database:before { - content: '\f1c0'; -} -.fa-file-pdf-o:before { - content: '\f1c1'; -} -.fa-file-word-o:before { - content: '\f1c2'; -} -.fa-file-excel-o:before { - content: '\f1c3'; -} -.fa-file-powerpoint-o:before { - content: '\f1c4'; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: '\f1c5'; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: '\f1c6'; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: '\f1c7'; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: '\f1c8'; -} -.fa-file-code-o:before { - content: '\f1c9'; -} -.fa-vine:before { - content: '\f1ca'; -} -.fa-codepen:before { - content: '\f1cb'; -} -.fa-jsfiddle:before { - content: '\f1cc'; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: '\f1cd'; -} -.fa-circle-o-notch:before { - content: '\f1ce'; -} -.fa-ra:before, -.fa-resistance:before, -.fa-rebel:before { - content: '\f1d0'; -} -.fa-ge:before, -.fa-empire:before { - content: '\f1d1'; -} -.fa-git-square:before { - content: '\f1d2'; -} -.fa-git:before { - content: '\f1d3'; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: '\f1d4'; -} -.fa-tencent-weibo:before { - content: '\f1d5'; -} -.fa-qq:before { - content: '\f1d6'; -} -.fa-wechat:before, -.fa-weixin:before { - content: '\f1d7'; -} -.fa-send:before, -.fa-paper-plane:before { - content: '\f1d8'; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: '\f1d9'; -} -.fa-history:before { - content: '\f1da'; -} -.fa-circle-thin:before { - content: '\f1db'; -} -.fa-header:before { - content: '\f1dc'; -} -.fa-paragraph:before { - content: '\f1dd'; -} -.fa-sliders:before { - content: '\f1de'; -} -.fa-share-alt:before { - content: '\f1e0'; -} -.fa-share-alt-square:before { - content: '\f1e1'; -} -.fa-bomb:before { - content: '\f1e2'; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: '\f1e3'; -} -.fa-tty:before { - content: '\f1e4'; -} -.fa-binoculars:before { - content: '\f1e5'; -} -.fa-plug:before { - content: '\f1e6'; -} -.fa-slideshare:before { - content: '\f1e7'; -} -.fa-twitch:before { - content: '\f1e8'; -} -.fa-yelp:before { - content: '\f1e9'; -} -.fa-newspaper-o:before { - content: '\f1ea'; -} -.fa-wifi:before { - content: '\f1eb'; -} -.fa-calculator:before { - content: '\f1ec'; -} -.fa-paypal:before { - content: '\f1ed'; -} -.fa-google-wallet:before { - content: '\f1ee'; -} -.fa-cc-visa:before { - content: '\f1f0'; -} -.fa-cc-mastercard:before { - content: '\f1f1'; -} -.fa-cc-discover:before { - content: '\f1f2'; -} -.fa-cc-amex:before { - content: '\f1f3'; -} -.fa-cc-paypal:before { - content: '\f1f4'; -} -.fa-cc-stripe:before { - content: '\f1f5'; -} -.fa-bell-slash:before { - content: '\f1f6'; -} -.fa-bell-slash-o:before { - content: '\f1f7'; -} -.fa-trash:before { - content: '\f1f8'; -} -.fa-copyright:before { - content: '\f1f9'; -} -.fa-at:before { - content: '\f1fa'; -} -.fa-eyedropper:before { - content: '\f1fb'; -} -.fa-paint-brush:before { - content: '\f1fc'; -} -.fa-birthday-cake:before { - content: '\f1fd'; -} -.fa-area-chart:before { - content: '\f1fe'; -} -.fa-pie-chart:before { - content: '\f200'; -} -.fa-line-chart:before { - content: '\f201'; -} -.fa-lastfm:before { - content: '\f202'; -} -.fa-lastfm-square:before { - content: '\f203'; -} -.fa-toggle-off:before { - content: '\f204'; -} -.fa-toggle-on:before { - content: '\f205'; -} -.fa-bicycle:before { - content: '\f206'; -} -.fa-bus:before { - content: '\f207'; -} -.fa-ioxhost:before { - content: '\f208'; -} -.fa-angellist:before { - content: '\f209'; -} -.fa-cc:before { - content: '\f20a'; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: '\f20b'; -} -.fa-meanpath:before { - content: '\f20c'; -} -.fa-buysellads:before { - content: '\f20d'; -} -.fa-connectdevelop:before { - content: '\f20e'; -} -.fa-dashcube:before { - content: '\f210'; -} -.fa-forumbee:before { - content: '\f211'; -} -.fa-leanpub:before { - content: '\f212'; -} -.fa-sellsy:before { - content: '\f213'; -} -.fa-shirtsinbulk:before { - content: '\f214'; -} -.fa-simplybuilt:before { - content: '\f215'; -} -.fa-skyatlas:before { - content: '\f216'; -} -.fa-cart-plus:before { - content: '\f217'; -} -.fa-cart-arrow-down:before { - content: '\f218'; -} -.fa-diamond:before { - content: '\f219'; -} -.fa-ship:before { - content: '\f21a'; -} -.fa-user-secret:before { - content: '\f21b'; -} -.fa-motorcycle:before { - content: '\f21c'; -} -.fa-street-view:before { - content: '\f21d'; -} -.fa-heartbeat:before { - content: '\f21e'; -} -.fa-venus:before { - content: '\f221'; -} -.fa-mars:before { - content: '\f222'; -} -.fa-mercury:before { - content: '\f223'; -} -.fa-intersex:before, -.fa-transgender:before { - content: '\f224'; -} -.fa-transgender-alt:before { - content: '\f225'; -} -.fa-venus-double:before { - content: '\f226'; -} -.fa-mars-double:before { - content: '\f227'; -} -.fa-venus-mars:before { - content: '\f228'; -} -.fa-mars-stroke:before { - content: '\f229'; -} -.fa-mars-stroke-v:before { - content: '\f22a'; -} -.fa-mars-stroke-h:before { - content: '\f22b'; -} -.fa-neuter:before { - content: '\f22c'; -} -.fa-genderless:before { - content: '\f22d'; -} -.fa-facebook-official:before { - content: '\f230'; -} -.fa-pinterest-p:before { - content: '\f231'; -} -.fa-whatsapp:before { - content: '\f232'; -} -.fa-server:before { - content: '\f233'; -} -.fa-user-plus:before { - content: '\f234'; -} -.fa-user-times:before { - content: '\f235'; -} -.fa-hotel:before, -.fa-bed:before { - content: '\f236'; -} -.fa-viacoin:before { - content: '\f237'; -} -.fa-train:before { - content: '\f238'; -} -.fa-subway:before { - content: '\f239'; -} -.fa-medium:before { - content: '\f23a'; -} -.fa-yc:before, -.fa-y-combinator:before { - content: '\f23b'; -} -.fa-optin-monster:before { - content: '\f23c'; -} -.fa-opencart:before { - content: '\f23d'; -} -.fa-expeditedssl:before { - content: '\f23e'; -} -.fa-battery-4:before, -.fa-battery:before, -.fa-battery-full:before { - content: '\f240'; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: '\f241'; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: '\f242'; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: '\f243'; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: '\f244'; -} -.fa-mouse-pointer:before { - content: '\f245'; -} -.fa-i-cursor:before { - content: '\f246'; -} -.fa-object-group:before { - content: '\f247'; -} -.fa-object-ungroup:before { - content: '\f248'; -} -.fa-sticky-note:before { - content: '\f249'; -} -.fa-sticky-note-o:before { - content: '\f24a'; -} -.fa-cc-jcb:before { - content: '\f24b'; -} -.fa-cc-diners-club:before { - content: '\f24c'; -} -.fa-clone:before { - content: '\f24d'; -} -.fa-balance-scale:before { - content: '\f24e'; -} -.fa-hourglass-o:before { - content: '\f250'; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: '\f251'; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: '\f252'; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: '\f253'; -} -.fa-hourglass:before { - content: '\f254'; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: '\f255'; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: '\f256'; -} -.fa-hand-scissors-o:before { - content: '\f257'; -} -.fa-hand-lizard-o:before { - content: '\f258'; -} -.fa-hand-spock-o:before { - content: '\f259'; -} -.fa-hand-pointer-o:before { - content: '\f25a'; -} -.fa-hand-peace-o:before { - content: '\f25b'; -} -.fa-trademark:before { - content: '\f25c'; -} -.fa-registered:before { - content: '\f25d'; -} -.fa-creative-commons:before { - content: '\f25e'; -} -.fa-gg:before { - content: '\f260'; -} -.fa-gg-circle:before { - content: '\f261'; -} -.fa-tripadvisor:before { - content: '\f262'; -} -.fa-odnoklassniki:before { - content: '\f263'; -} -.fa-odnoklassniki-square:before { - content: '\f264'; -} -.fa-get-pocket:before { - content: '\f265'; -} -.fa-wikipedia-w:before { - content: '\f266'; -} -.fa-safari:before { - content: '\f267'; -} -.fa-chrome:before { - content: '\f268'; -} -.fa-firefox:before { - content: '\f269'; -} -.fa-opera:before { - content: '\f26a'; -} -.fa-internet-explorer:before { - content: '\f26b'; -} -.fa-tv:before, -.fa-television:before { - content: '\f26c'; -} -.fa-contao:before { - content: '\f26d'; -} -.fa-500px:before { - content: '\f26e'; -} -.fa-amazon:before { - content: '\f270'; -} -.fa-calendar-plus-o:before { - content: '\f271'; -} -.fa-calendar-minus-o:before { - content: '\f272'; -} -.fa-calendar-times-o:before { - content: '\f273'; -} -.fa-calendar-check-o:before { - content: '\f274'; -} -.fa-industry:before { - content: '\f275'; -} -.fa-map-pin:before { - content: '\f276'; -} -.fa-map-signs:before { - content: '\f277'; -} -.fa-map-o:before { - content: '\f278'; -} -.fa-map:before { - content: '\f279'; -} -.fa-commenting:before { - content: '\f27a'; -} -.fa-commenting-o:before { - content: '\f27b'; -} -.fa-houzz:before { - content: '\f27c'; -} -.fa-vimeo:before { - content: '\f27d'; -} -.fa-black-tie:before { - content: '\f27e'; -} -.fa-fonticons:before { - content: '\f280'; -} -.fa-reddit-alien:before { - content: '\f281'; -} -.fa-edge:before { - content: '\f282'; -} -.fa-credit-card-alt:before { - content: '\f283'; -} -.fa-codiepie:before { - content: '\f284'; -} -.fa-modx:before { - content: '\f285'; -} -.fa-fort-awesome:before { - content: '\f286'; -} -.fa-usb:before { - content: '\f287'; -} -.fa-product-hunt:before { - content: '\f288'; -} -.fa-mixcloud:before { - content: '\f289'; -} -.fa-scribd:before { - content: '\f28a'; -} -.fa-pause-circle:before { - content: '\f28b'; -} -.fa-pause-circle-o:before { - content: '\f28c'; -} -.fa-stop-circle:before { - content: '\f28d'; -} -.fa-stop-circle-o:before { - content: '\f28e'; -} -.fa-shopping-bag:before { - content: '\f290'; -} -.fa-shopping-basket:before { - content: '\f291'; -} -.fa-hashtag:before { - content: '\f292'; -} -.fa-bluetooth:before { - content: '\f293'; -} -.fa-bluetooth-b:before { - content: '\f294'; -} -.fa-percent:before { - content: '\f295'; -} -.fa-gitlab:before { - content: '\f296'; -} -.fa-wpbeginner:before { - content: '\f297'; -} -.fa-wpforms:before { - content: '\f298'; -} -.fa-envira:before { - content: '\f299'; -} -.fa-universal-access:before { - content: '\f29a'; -} -.fa-wheelchair-alt:before { - content: '\f29b'; -} -.fa-question-circle-o:before { - content: '\f29c'; -} -.fa-blind:before { - content: '\f29d'; -} -.fa-audio-description:before { - content: '\f29e'; -} -.fa-volume-control-phone:before { - content: '\f2a0'; -} -.fa-braille:before { - content: '\f2a1'; -} -.fa-assistive-listening-systems:before { - content: '\f2a2'; -} -.fa-asl-interpreting:before, -.fa-american-sign-language-interpreting:before { - content: '\f2a3'; -} -.fa-deafness:before, -.fa-hard-of-hearing:before, -.fa-deaf:before { - content: '\f2a4'; -} -.fa-glide:before { - content: '\f2a5'; -} -.fa-glide-g:before { - content: '\f2a6'; -} -.fa-signing:before, -.fa-sign-language:before { - content: '\f2a7'; -} -.fa-low-vision:before { - content: '\f2a8'; -} -.fa-viadeo:before { - content: '\f2a9'; -} -.fa-viadeo-square:before { - content: '\f2aa'; -} -.fa-snapchat:before { - content: '\f2ab'; -} -.fa-snapchat-ghost:before { - content: '\f2ac'; -} -.fa-snapchat-square:before { - content: '\f2ad'; -} -.fa-pied-piper:before { - content: '\f2ae'; -} -.fa-first-order:before { - content: '\f2b0'; -} -.fa-yoast:before { - content: '\f2b1'; -} -.fa-themeisle:before { - content: '\f2b2'; -} -.fa-google-plus-circle:before, -.fa-google-plus-official:before { - content: '\f2b3'; -} -.fa-fa:before, -.fa-font-awesome:before { - content: '\f2b4'; -} -.fa-handshake-o:before { - content: '\f2b5'; -} -.fa-envelope-open:before { - content: '\f2b6'; -} -.fa-envelope-open-o:before { - content: '\f2b7'; -} -.fa-linode:before { - content: '\f2b8'; -} -.fa-address-book:before { - content: '\f2b9'; -} -.fa-address-book-o:before { - content: '\f2ba'; -} -.fa-vcard:before, -.fa-address-card:before { - content: '\f2bb'; -} -.fa-vcard-o:before, -.fa-address-card-o:before { - content: '\f2bc'; -} -.fa-user-circle:before { - content: '\f2bd'; -} -.fa-user-circle-o:before { - content: '\f2be'; -} -.fa-user-o:before { - content: '\f2c0'; -} -.fa-id-badge:before { - content: '\f2c1'; -} -.fa-drivers-license:before, -.fa-id-card:before { - content: '\f2c2'; -} -.fa-drivers-license-o:before, -.fa-id-card-o:before { - content: '\f2c3'; -} -.fa-quora:before { - content: '\f2c4'; -} -.fa-free-code-camp:before { - content: '\f2c5'; -} -.fa-telegram:before { - content: '\f2c6'; -} -.fa-thermometer-4:before, -.fa-thermometer:before, -.fa-thermometer-full:before { - content: '\f2c7'; -} -.fa-thermometer-3:before, -.fa-thermometer-three-quarters:before { - content: '\f2c8'; -} -.fa-thermometer-2:before, -.fa-thermometer-half:before { - content: '\f2c9'; -} -.fa-thermometer-1:before, -.fa-thermometer-quarter:before { - content: '\f2ca'; -} -.fa-thermometer-0:before, -.fa-thermometer-empty:before { - content: '\f2cb'; -} -.fa-shower:before { - content: '\f2cc'; -} -.fa-bathtub:before, -.fa-s15:before, -.fa-bath:before { - content: '\f2cd'; -} -.fa-podcast:before { - content: '\f2ce'; -} -.fa-window-maximize:before { - content: '\f2d0'; -} -.fa-window-minimize:before { - content: '\f2d1'; -} -.fa-window-restore:before { - content: '\f2d2'; -} -.fa-times-rectangle:before, -.fa-window-close:before { - content: '\f2d3'; -} -.fa-times-rectangle-o:before, -.fa-window-close-o:before { - content: '\f2d4'; -} -.fa-bandcamp:before { - content: '\f2d5'; -} -.fa-grav:before { - content: '\f2d6'; -} -.fa-etsy:before { - content: '\f2d7'; -} -.fa-imdb:before { - content: '\f2d8'; -} -.fa-ravelry:before { - content: '\f2d9'; -} -.fa-eercast:before { - content: '\f2da'; -} -.fa-microchip:before { - content: '\f2db'; -} -.fa-snowflake-o:before { - content: '\f2dc'; -} -.fa-superpowers:before { - content: '\f2dd'; -} -.fa-wpexplorer:before { - content: '\f2de'; -} -.fa-meetup:before { - content: '\f2e0'; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} diff --git a/css/history.css b/css/history.css new file mode 100644 index 0000000..2471644 --- /dev/null +++ b/css/history.css @@ -0,0 +1,79 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: Lucida Grande, Arial, sans-serif; + background-color: transparent; +} +body::-webkit-scrollbar { + width: 0px; +} +button, +input { + outline: none; + border: 0; + background: none; +} +button { + cursor: pointer; +} +a { + text-decoration: none; + color: rgb(73, 87, 107); + display: block; + width: 200px; +} +ul { + list-style: none; +} +#search-history { + border-radius: 7px; + display: flex; + padding: 30px; + width: 100%; +} +#categories-list { + width: 100%; +} +#search-history .category { + display: flex; + list-style: none; + flex-direction: column; + width: 100%; + border: 1px solid rgba(216, 220, 226, 0.37); + border-radius: 10px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + padding: 15px; + margin-bottom: 20px; +} +#search-history .category-list > li { + display: flex; + list-style: none; + flex-direction: column; + width: 100%; + padding: 15px 10px; + margin-bottom: 10px; +} +.history { + width: 100%; +} +.item { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + +} +h4 { + border-bottom: 1px solid rgba(211, 211, 211, 0.575); + padding: 20px; + margin-bottom: 10px; + text-transform: capitalize; +} +.time { + font-weight: bold; + font-size: 14px; +} \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index fb4b9c1..c4a9974 100644 --- a/css/styles.css +++ b/css/styles.css @@ -21,6 +21,7 @@ webview { } #root { + position: relative; background: rgb(193, 194, 250); background: linear-gradient( 90deg, @@ -29,7 +30,7 @@ webview { rgba(240, 240, 178, 1) 100% ); border-radius: 7px; - padding: 35px 10px 10px; + padding: 40px 10px 10px; display: flex; justify-content: space-between; align-items: center; @@ -37,10 +38,40 @@ webview { -webkit-user-select: none; user-select: none; } +.top-bar { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 40px; + display: flex; + width: 100%; + justify-content: flex-end; + border-radius: inherit; + align-items: center; + padding: 0 10px; +} + +.top-bar button { + background-color: rgba(0, 0, 0, 0.1); + width: 11px; + height: 11px; + border-radius: 50%; + font-size: 8px; + color: transparent; + margin: 0 4px; + cursor: pointer; + -webkit-app-region: no-drag; +} + +.top-bar button:hover { + color: rgba(255, 255, 255, 0.7); +} #root #app-sidebar { -webkit-app-region: no-drag; + position: relative; border-radius: inherit; - width: 17%; + width: 20%; height: 100%; display: flex; flex-direction: column; @@ -58,6 +89,7 @@ webview { display: flex; width: 100%; justify-content: space-between; + align-items: center; } #root #app-sidebar.toggled-sidebar #controllers { flex-direction: column; @@ -72,28 +104,6 @@ webview { flex-direction: column; } -#root #app-sidebar #controllers #window-controllers button:not(#toggle-btn) { - background-color: rgba(0, 0, 0, 0.1); - width: 11px; - height: 11px; - border-radius: 50%; - font-size: 8px; - color: transparent; - margin: 0 4px; - cursor: pointer; -} -#root #app-sidebar.toggled-sidebar #window-controllers button:not(#toggle-btn) { - margin: 4px 0 !important; -} - -#root - #app-sidebar - #controllers - #window-controllers - button:not(#toggle-btn):hover { - color: rgba(255, 255, 255, 0.7); -} - #root #app-sidebar #controllers #toggle-btn { margin: 0 10px; display: flex; @@ -117,19 +127,57 @@ webview { flex-direction: column; } #root #app-sidebar #navigation-controllers button { - font-size: 12px; - margin: 0 6px; + font-size: 16px; + margin-left: 17px; + margin-right: 2px; color: rgba(51, 51, 51, 0.67); cursor: pointer; } +#menu-button { + margin: 0 5px; + color: rgba(51, 51, 51, 0.67); + cursor: pointer; + font-size: 18px; +} + +#menu { + width: 200px; + border-radius: 7px; + background-color: #fff; + padding: 20px 0; + position: absolute; + top: 30px; + left: 0; + transform: scale(0, 0); + transition: 0.3s; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +} +#menu .menu-item { + display: flex; + align-items: center; + padding: 14px 10px; + color: rgb(72, 82, 97); + cursor: pointer; +} +#menu .menu-item:hover { + background-color: rgba(211, 211, 211, 0.205); +} +#menu .menu-item i { + margin-right: 10px; +} +#menu.open { + transform: scale(1, 1); +} + #root #app-sidebar #location-form { margin: 20px 0; display: flex; align-items: center; width: 100%; + justify-content: space-between; } #root #app-sidebar.toggled-sidebar #navigation-controllers button { - margin: 6px 0; + margin: 10px 0; } #root #app-sidebar.toggled-sidebar #location-form { display: none; @@ -143,6 +191,18 @@ webview { font-size: 13px; color: rgba(51, 51, 51, 0.699); } +#root #app-sidebar .location-container button { + padding: 10px; + border-radius: 8px; + font-size: 13px; + color: rgba(51, 51, 51, 0.699); + cursor: pointer; +} +.location-container { + display: flex; + align-items: center; + justify-content: space-between; +} #root #app-sidebar #location-form input::placeholder { color: rgba(51, 51, 51, 0.699); font-size: 13px; @@ -235,12 +295,28 @@ input { #webviews-container { box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); border-radius: 7px; - width: 82%; + width: 78%; height: 100%; overflow: hidden; -webkit-app-region: no-drag; transition: 0.3s; } #webviews-container.toggled-container { - width: 96%; + width: 95%; +} +#options-bar { + width: 100%; + margin-bottom: 15px; +} + +#bookmark-btn { + margin: 0 5px; + cursor: pointer; + color: rgba(51, 51, 51, 0.637); +} +#bookmark-btn.active { + color: gold !important; } +#root #app-sidebar.toggled-sidebar #bookmark-btn { + margin: 10px 0; +} \ No newline at end of file diff --git a/fonts/fontawesome-webfont.ttf b/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/fonts/fontawesome-webfont.woff b/fonts/fontawesome-webfont.woff deleted file mode 100644 index 400014a..0000000 Binary files a/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/fonts/fontawesome-webfont.woff2 b/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 4d13fc6..0000000 Binary files a/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/history.html b/history.html new file mode 100644 index 0000000..89d8fcb --- /dev/null +++ b/history.html @@ -0,0 +1,14 @@ + + + + + + + + History + + + + + + diff --git a/history.js b/history.js new file mode 100644 index 0000000..de7adac --- /dev/null +++ b/history.js @@ -0,0 +1,80 @@ +import { categorizeByDate } from "./utils/categorize.js"; + +window.addEventListener("DOMContentLoaded", function () { + const searchHistory = document.createElement("div"); + searchHistory.id = "search-history"; + + const categoriesList = document.createElement("ul"); + categoriesList.id = "categories-list"; + history.className = "history"; + const searchHistoryArray = JSON.parse( + localStorage.getItem("search-history") || "[]" + ); + const categories = categorizeByDate(searchHistoryArray); + console.log(categories); + + const sortedKeys = Object.keys(categories).sort((a, b) => { + if (a.includes("Today")) return -1; + if (b.includes("Today")) return 1; + if (a.includes("Yesterday")) return -1; + if (b.includes("Yesterday")) return 1; + if (a.includes("Last 7 days")) return -1; + if (b.includes("Last 7 days")) return 1; + if (a.includes("Older")) return -1; + if (b.includes("Older")) return 1; + return 0; + }); + + sortedKeys.forEach((key) => { + const category = document.createElement("li"); + category.className = "category"; + const categoryTitle = document.createElement("h4"); + categoryTitle.innerText = key; + category.appendChild(categoryTitle); + const categoryList = document.createElement("ul"); + categoryList.className = "category-list"; + categories[key].forEach((item) => { + const history = document.createElement("ul"); + const itemLi = document.createElement("li"); + itemLi.className = "item"; + const itemLink = document.createElement("a"); + const time = document.createElement("div"); + time.className = "time"; + time.innerText = new Date(item.time).toLocaleTimeString(); + let button = document.createElement("button"); + button.innerHTML = ""; + button.addEventListener("click", function () { + const sHistory = JSON.parse( + localStorage.getItem("search-history") + ).filter((i) => i.id !== item.id); + localStorage.setItem("search-history", JSON.stringify(sHistory)); + itemLi.remove(); + if (categoriesList.children.length === 0) { + let li = document.createElement("li"); + li.textContent = "No search history"; + categoriesList.appendChild(li); + } + }); + itemLink.href = item.url; + itemLink.innerText = item.url.slice( + item.url.indexOf("//") + 2, + item.url.indexOf("/", item.url.indexOf("//") + 2) + ); + itemLink.target = "_blank"; + itemLi.appendChild(itemLink); + itemLi.appendChild(time); + itemLi.appendChild(button); + history.appendChild(itemLi); + category.appendChild(history); + categoriesList.appendChild(category); + }); + }); + + if (categoriesList.children.length === 0) { + let li = document.createElement("li"); + li.textContent = "No search history"; + categoriesList.appendChild(li); + } + searchHistory.appendChild(categoriesList); + document.body.appendChild(searchHistory); +}); diff --git a/index.html b/index.html index ef3ab7a..d377c9b 100644 --- a/index.html +++ b/index.html @@ -5,11 +5,13 @@ - Unelma.XYZ - Browser + + -
+
+
diff --git a/main.js b/main.js index 5dbed94..d1f439c 100644 --- a/main.js +++ b/main.js @@ -52,9 +52,9 @@ function createWindow() { // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. -app.on("web-contents-created", function (webContentsCreatedEvent, contents) { +app.on("web-contents-created", function (_, contents) { if (contents.getType() === "webview") { - contents.addListener("new-window", function (newWindowEvent, url) { + contents.addListener("new-window", function (newWindowEvent, _) { newWindowEvent.preventDefault(); }); } diff --git a/script.js b/script.js index 4b83b08..d51a421 100644 --- a/script.js +++ b/script.js @@ -1,5 +1,7 @@ const Sidebar = require("./components/Sidebar"); const addTab = require("./utils/addTab"); +const TopBar = require("./components/TopBar"); +const { getCurrentTabs } = require("./utils/handleLocalStorage"); window.addEventListener("DOMContentLoaded", function () { const root = document.getElementById("root"); @@ -10,6 +12,7 @@ window.addEventListener("DOMContentLoaded", function () { const sidebar = Sidebar(); root.appendChild(sidebar); root.appendChild(content); + root.appendChild(TopBar()); const controllers = document.getElementById("controllers"); const actualTabs = document.getElementById("actual-tabs"); const LocationForm = document.getElementById("location-form"); @@ -28,5 +31,13 @@ window.addEventListener("DOMContentLoaded", function () { 115 }px`; }); - addTab(); + const currentTabs = getCurrentTabs(); + if (currentTabs.length === 0) { + addTab(); + } else { + currentTabs.forEach((tab) => { + addTab(tab.url, true, tab.id); + }); + } + }); diff --git a/styles.css b/styles.css index d84163b..1fd5615 100644 --- a/styles.css +++ b/styles.css @@ -36,7 +36,7 @@ strong, sub, sup, tt, -var, +let, b, u, i, diff --git a/utils/addTab.js b/utils/addTab.js index 86fe2f8..ca2e6c6 100644 --- a/utils/addTab.js +++ b/utils/addTab.js @@ -1,9 +1,15 @@ const Tab = require("../components/Tab"); const Webview = require("../components/Webview"); - -const addTab = (passedURL) => { +const { + getCurrentTabs, + setCurrentTabs, + getBookmarks, + addHistory, +} = require("./handleLocalStorage"); +const newId = () => Math.round(Math.random() * 10000 * Math.random()); +const addTab = (passedURL, isNew, oldId) => { + const id = oldId || newId(); const url = passedURL ? passedURL : "https://www.unelma.xyz/"; - const id = Math.round(Math.random() * 10000 * Math.random()); const tabs = document.getElementById("actual-tabs"); const views = document.getElementById("webviews-container"); const locationInput = document.getElementById("location-input"); @@ -18,12 +24,37 @@ const addTab = (passedURL) => { }); newTab.classList.add("active-tab"); newWebview.classList.add("active-webview"); - newWebview.addEventListener("new-window", (e) => { - addTab(e.url); - }); + + const currentTabs = getCurrentTabs(); + currentTabs.push({ id, url }); + if (!isNew) setCurrentTabs(currentTabs); + newWebview.addEventListener("new-window", (e) => { + addTab(e.url); + }); tabs.appendChild(newTab); views.appendChild(newWebview); + + newWebview.addEventListener("dom-ready", () => { + if ( + url.endsWith("history.html") || + url.endsWith("bookmarks.html") + ) { + newWebview.executeJavaScript( + "window.localStorage.setItem('search-history', JSON.stringify(JSON.parse(localStorage.getItem('search-history')||'[]')));" + ); + newWebview.executeJavaScript( + "window.localStorage.setItem('bookmarks', JSON.stringify(JSON.parse(localStorage.getItem('bookmarks')||'[]')));" + ); + } + }); + const bookmarks = getBookmarks(); + const bookmarkBtn = document.getElementById("bookmark-btn"); + if (bookmarks.find((item) => item.url === url)) + bookmarkBtn.classList.add("active"); + else bookmarkBtn.classList.remove("active"); + locationInput.value = url; } + addHistory(url); }; module.exports = addTab; diff --git a/utils/categorize.js b/utils/categorize.js new file mode 100644 index 0000000..7129466 --- /dev/null +++ b/utils/categorize.js @@ -0,0 +1,32 @@ +export function categorizeByDate(arr) { + const categories = arr.reverse().reduce((acc, item) => { + const date = new Date(item.time); + const today = new Date(); + today.setHours(0, 0, 0, 0); + const yesterday = new Date(today); + yesterday.setDate(today.getDate() - 1); + const older = new Date(today); + older.setDate(today.getDate() - 7); + const category = + date.getTime() > today.getTime() + ? `Today - ${date.toDateString()}` + : date.getTime() > yesterday.getTime() + ? `Yesterday - ${date.toDateString()}` + : date.getTime() > older.getTime() + ? `Last 7 days` + : `Older`; + if (!acc[category]) { + acc[category] = []; + } + acc[category].push(item); + return acc; + }, {}); + + let sortedCategories = {}; + //put key contains today first + //put key contains yesterday second + //put key contains last 7 days third + //put key contains older last + + return categories; +} diff --git a/utils/goToLocation.js b/utils/goToLocation.js index ed58637..ac89d24 100644 --- a/utils/goToLocation.js +++ b/utils/goToLocation.js @@ -1,9 +1,25 @@ +const { + setCurrentTabs, + getBookmarks, + addHistory, +} = require("./handleLocalStorage"); const handleSearch = require("./handleSearch"); const goToLocation = (input) => { const activeWebview = document.querySelector(".active-webview"); + const id = +activeWebview.id.split("-")[1]; activeWebview.src = handleSearch(input.value); input.value = handleSearch(input.value); + const currentTabs = JSON.parse(localStorage.getItem("current-tabs")); + const indexOfCurrentTab = currentTabs.findIndex((tab) => tab.id === id); + currentTabs[indexOfCurrentTab].url = handleSearch(input.value); + setCurrentTabs(currentTabs); + addHistory(handleSearch(input.value)); + const bookmarks = getBookmarks(); + const bookmarkBtn = document.getElementById("bookmark-btn"); + if (bookmarks.find((item) => item.url === handleSearch(input.value))) + bookmarkBtn.classList.add("active"); + else bookmarkBtn.classList.remove("active"); }; module.exports = goToLocation; diff --git a/utils/handleLocalStorage.js b/utils/handleLocalStorage.js new file mode 100644 index 0000000..e2fb1fd --- /dev/null +++ b/utils/handleLocalStorage.js @@ -0,0 +1,58 @@ +const newId = () => Math.round(Math.random() * 10000 * Math.random()); +const dateTime = () => new Date(Date.now()) +module.exports = { + getCurrentTabs: () => { + return JSON.parse(localStorage.getItem("current-tabs") || "[]"); + }, + setCurrentTabs: (tabs) => { + localStorage.setItem("current-tabs", JSON.stringify(tabs)); + }, + getSearchHistory: () => { + return JSON.parse(localStorage.getItem("search-history") || "[]"); + }, + setSearchHistory: (history) => { + localStorage.setItem("search-history", JSON.stringify(history)); + }, + addHistory: (url) => { + let history = JSON.parse(localStorage.getItem("search-history") || "[]"); + if ( + url !== "https://www.unelma.xyz/" && + !url.includes("history.html") && + !url.includes("bookmarks.html") && + !history.find((item) => item.url === url) + ) { + const id = newId(); + history.push({ id, url, time: dateTime() }); + localStorage.setItem("search-history", JSON.stringify(history)); + } + }, + getBookmarks: () => { + return JSON.parse(localStorage.getItem("bookmarks") || "[]"); + }, + setBookmarks: (marks) => { + localStorage.setItem("bookmarks", JSON.stringify(marks)); + }, + addBookmark: (url) => { + let bookmarks = JSON.parse(localStorage.getItem("bookmarks") || "[]"); + if ( + !bookmarks.find((item) => item.url === url) && + !url.endsWith("bookmarks.html") && + !url.endsWith("history.html") + ) { + const id = newId(); + bookmarks.push({ id, url, time: dateTime() }); + localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); + } + }, + removeFromBookmarks: (url) => { + let bookmarks = JSON.parse(localStorage.getItem("bookmarks") || "[]"); + bookmarks = bookmarks.filter((item) => item.url !== url); + localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); + }, + removeFromSearchHistroy: (url) => { + let history = JSON.parse(localStorage.getItem("bookmarks") || "[]"); + + history = history.filter((item) => item.url !== url); + localStorage.setItem("search-history", JSON.stringify(history)); + }, +}; diff --git a/utils/handleSearch.js b/utils/handleSearch.js index f034c13..42a4af7 100644 --- a/utils/handleSearch.js +++ b/utils/handleSearch.js @@ -1,4 +1,3 @@ -// create function to validate url const isURL = (url) => { const urlRegex = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/;