Skip to content

Commit

Permalink
Add multi-selection actions to settings page
Browse files Browse the repository at this point in the history
Fixes #182 and fixes #206
  • Loading branch information
nt1m committed Mar 20, 2020
1 parent 5d6f5ce commit 8896eea
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 10 deletions.
42 changes: 36 additions & 6 deletions css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ label {
float: right;
}

.flex {
.flex:not([hidden]) {
display: flex;
}

Expand Down Expand Up @@ -295,7 +295,7 @@ input.short {
max-width: 7ch;
}

input:not([type="submit"]):not([type="button"]):not([type="hidden"]) {
input:not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]) {
background-color: var(--textbox-background);
color: inherit;
border: 1px solid var(--grey-90-a30);
Expand All @@ -305,21 +305,51 @@ input:not([type="submit"]):not([type="button"]):not([type="hidden"]) {
transition: box-shadow 0.15s cubic-bezier(.07,.95,0,1);
}

input:not([type="submit"]):not([type="button"]):not([type="hidden"]):hover {
input:not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]):hover {
border-color: var(--grey-90-a50);
}

input:not([type="submit"]):not([type="button"]):not([type="hidden"]):focus {
input:not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]):focus {
border-color: var(--blue-50);
box-shadow: 0 0 0 1px var(--blue-50), 0 0 0 4px var(--blue-50-a30);
}

input:not([type="submit"]):not([type="button"]):not([type="hidden"]).error,
input:not([type="submit"]):not([type="button"]):not([type="hidden"]):invalid {
input:not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]).error,
input:not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]):invalid {
border-color: var(--red-50);
box-shadow: 0 0 0 1px var(--red-50), 0 0 0 4px var(--red-50-a30);
}

input[type="checkbox"] {
-moz-appearance: none;
border: 2px solid var(--grey-10-a10);
border-radius: 2px;
width: 16px;
height: 16px;
display: inline-block;
}

input[type="checkbox"]::before {
display: inline-block;
width: 16px;
height: 16px;
margin: -2px;
}

input[type="checkbox"]:checked::before {
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6.52,12.5a1,1,0,0,1-.705-.291l-3.52-3.5a1,1,0,1,1,1.41-1.418l2.812,2.8,5.774-5.793a1,1,0,0,1,1.416,1.412l-6.479,6.5A1,1,0,0,1,6.52,12.5Z" fill="white"/></svg>')
}

input[type="checkbox"]:indeterminate::before {
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><rect x="3" y="7" width="10" height="2" rx="1" fill="white"/></svg>');
}

input[type="checkbox"]:indeterminate,
input[type="checkbox"]:checked {
border-color: transparent;
background-color: var(--blue-60);
}

.card {
box-shadow: 0 2px 8px var(--grey-90-a10);
background: var(--card-background);
Expand Down
16 changes: 13 additions & 3 deletions pages/settings/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ main > * {
.feed {
display: grid;
padding: 10px;
grid-template-columns: 1fr min-content;
grid-template-areas: "title edit"
"siteUrl edit";
grid-template-columns: min-content 1fr min-content;
grid-template-areas: "checkbox title edit"
"checkbox siteUrl edit";
column-gap: 10px;
}

.feed:first-child {
margin-top: 0;
}

.broken {
Expand All @@ -47,6 +52,11 @@ main > * {
font-weight: bold;
}

.feed-checkbox {
grid-area: checkbox;
align-self: center;
}

.feed-title {
grid-area: title;
}
Expand Down
9 changes: 8 additions & 1 deletion pages/settings/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
</head>
<body>
<main>
<div class="toolbar flex">
<header class="toolbar flex">
<h1 class="grow" data-i18n-text="yourLivemarks"></h1>
<button data-i18n-text="moreOptions" class="icon settings float-right" id="settings-toggle"></button>
<button data-i18n-text="newLivemark" class="icon new icon-white primary float-right" id="add"></button>
</header>
<div class="toolbar flex" id="selection-toolbar" hidden>
<input type="checkbox" id="select-all-checkbox">
<span id="select-status"></span>
<div class="grow"></div>
<button class="">Move to folder</button>
<button class="icon delete" id="delete-feed-selection">Delete</button>
</div>
<div class="empty-notice grow" id="feeds"></div>
</main>
Expand Down
73 changes: 73 additions & 0 deletions pages/settings/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ window.onload = async () => {
reader.readAsText(file);
});

document.querySelector("#delete-feed-selection").addEventListener("click", () => {
FeedMultiSelection.removeSelectedFeeds();
});

loadFeeds();
LivemarkStore.addChangeListener(loadFeeds);
browser.bookmarks.onChanged.addListener(async (id) => {
Expand Down Expand Up @@ -159,15 +163,84 @@ async function loadFeeds() {
feed.title = I18N.getMessage("settings_brokenLivemark");
addFeedToList(feed, true);
});

FeedMultiSelection.reset();
}

const FeedMultiSelection = {
selection: new Set(),
selectAllCheckbox: document.getElementById("select-all-checkbox"),
async _updateSelectAllCheckboxState() {
const size = await LivemarkStore.getSize();
const isEmptySelection = this.selection.size == 0;
this.selectAllCheckbox.indeterminate = !isEmptySelection && this.selection.size < size;
this.selectAllCheckbox.checked = !isEmptySelection && this.selection.size == size;
this.selectAllCheckbox.disabled = size == 0;
document.getElementById("selection-toolbar").hidden = size == 0;
},
addToSelection(feed) {
this.selection.add(feed);
this._updateSelectAllCheckboxState();
},
addAllToSelection() {
for (const element of document.querySelectorAll("#feeds > .feed")) {
this.selection.add(element.feedData);
element.querySelector(".feed-checkbox").checked = true;
}
this._updateSelectAllCheckboxState();
},
removeFromSelection(feed) {
this.selection.delete(feed);
this._updateSelectAllCheckboxState();
},
reset() {
this.selection.clear();
for (const element of document.querySelectorAll("#feeds > .feed")) {
element.querySelector(".feed-checkbox").checked = false;
}
this._updateSelectAllCheckboxState();

// XXX: probably doesn't belong here...
this.selectAllCheckbox.onchange = () => {
if (this.selectAllCheckbox.checked) {
this.addAllToSelection();
} else {
this.reset();
}
};
},

moveSelectedFeeds(folder) {
// XXX: todo
},
async removeSelectedFeeds() {
for (const feed of this.selection) {
await LivemarkStore.remove(feed.id);
}
this.selection.clear();
}
};

function addFeedToList(feed, broken = false) {
const item = document.createElement("div");
item.className = "feed card";
item.feedData = feed;
if (broken) {
item.classList.add("broken");
}

const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.className = "feed-checkbox";
checkbox.onchange = () => {
if (checkbox.checked) {
FeedMultiSelection.addToSelection(feed);
} else {
FeedMultiSelection.removeFromSelection(feed);
}
};
item.appendChild(checkbox);

const feedTitle = document.createElement("span");
feedTitle.textContent = feed.title;
feedTitle.className = "feed-title";
Expand Down
11 changes: 11 additions & 0 deletions shared/livemark-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ const LivemarkStore = {
return all;
},

async getSize() {
const livemarks = await browser.storage.sync.get();
let size = 0;
for (const key in livemarks) {
if (key.startsWith(PREFIX)) {
size++;
}
}
return size;
},

async add(feed) {
const { title, parentId } = feed;
const bookmark = await browser.bookmarks.create({
Expand Down

0 comments on commit 8896eea

Please sign in to comment.