Fix icons, export working

This commit is contained in:
Corentin 2022-11-15 16:04:28 +09:00
commit 24f918d76a
12 changed files with 59 additions and 15 deletions

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M22.5 38V25.5H10v-3h12.5V10h3v12.5H38v3H25.5V38Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 183 B

Before After
Before After

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="m12.45 37.65-2.1-2.1L21.9 24 10.35 12.45l2.1-2.1L24 21.9l11.55-11.55 2.1 2.1L26.1 24l11.55 11.55-2.1 2.1L24 26.1Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 248 B

Before After
Before After

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M13.05 42q-1.2 0-2.1-.9-.9-.9-.9-2.1V10.5H8v-3h9.4V6h13.2v1.5H40v3h-2.05V39q0 1.2-.9 2.1-.9.9-2.1.9Zm21.9-31.5h-21.9V39h21.9Zm-16.6 24.2h3V14.75h-3Zm8.3 0h3V14.75h-3Zm-13.6-24.2V39Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 316 B

Before After
Before After

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M18.9 35.7 7.7 24.5l2.15-2.15 9.05 9.05 19.2-19.2 2.15 2.15Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 195 B

Before After
Before After

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M9 39h2.2l22.15-22.15-2.2-2.2L9 36.8Zm30.7-24.3-6.4-6.4 2.1-2.1q.85-.85 2.1-.85t2.1.85l2.2 2.2q.85.85.85 2.1t-.85 2.1Zm-2.1 2.1L12.4 42H6v-6.4l25.2-25.2Zm-5.35-1.05-1.1-1.1 2.2 2.2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 316 B

Before After
Before After

3
icons/export.svg Normal file
View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M11 40q-1.2 0-2.1-.9Q8 38.2 8 37v-7.15h3V37h26v-7.15h3V37q0 1.2-.9 2.1-.9.9-2.1.9Zm13-7.65-9.65-9.65 2.15-2.15 6 6V8h3v18.55l6-6 2.15 2.15Z"/>
</svg>

After

Width:  |  Height:  |  Size: 274 B

3
icons/import.svg Normal file
View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M11 40q-1.2 0-2.1-.9Q8 38.2 8 37v-7.15h3V37h26v-7.15h3V37q0 1.2-.9 2.1-.9.9-2.1.9Zm11.5-7.65V13.8l-6 6-2.15-2.15L24 8l9.65 9.65-2.15 2.15-6-6v18.55Z"/>
</svg>

After

Width:  |  Height:  |  Size: 283 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M9 42q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h14.55v3H9v30h14.55v3Zm24.3-9.25-2.15-2.15 5.1-5.1h-17.5v-3h17.4l-5.1-5.1 2.15-2.15 8.8 8.8Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

Before After
Before After

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:none;">
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" viewBox="0 0 48 48" style="stroke:#ccc;fill:#ccc;">
<path d="M24 31.5q3.55 0 6.025-2.475Q32.5 26.55 32.5 23q0-3.55-2.475-6.025Q27.55 14.5 24 14.5q-3.55 0-6.025 2.475Q15.5 19.45 15.5 23q0 3.55 2.475 6.025Q20.45 31.5 24 31.5Zm0-2.9q-2.35 0-3.975-1.625T18.4 23q0-2.35 1.625-3.975T24 17.4q2.35 0 3.975 1.625T29.6 23q0 2.35-1.625 3.975T24 28.6Zm0 9.4q-7.3 0-13.2-4.15Q4.9 29.7 2 23q2.9-6.7 8.8-10.85Q16.7 8 24 8q7.3 0 13.2 4.15Q43.1 16.3 46 23q-2.9 6.7-8.8 10.85Q31.3 38 24 38Zm0-15Zm0 12q6.05 0 11.125-3.275T42.85 23q-2.65-5.45-7.725-8.725Q30.05 11 24 11t-11.125 3.275Q7.8 17.55 5.1 23q2.7 5.45 7.775 8.725Q17.95 35 24 35Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 692 B

Before After
Before After

View file

@ -60,7 +60,8 @@ h2 {
display: flex;
}
.entry .header h2, .entry .header input {
.entry .header h2,
.entry .header input {
flex-grow: 1;
}
@ -89,8 +90,13 @@ h2 {
border-top: 1px solid var(--border-color);
}
#entry-list .entry input {
font-size: 1.2em;
width: 200px;
}
.hidden {
display: none;
display: none !important;
}
.icon {
@ -115,6 +121,7 @@ h2 {
#entry-add-container {
position: relative;
padding-bottom: 4px;
}
#entry-form {
@ -150,4 +157,14 @@ h2 {
#password-form label {
margin-right: 8px;
}
#store-action {
display: flex;
justify-content: center;
}
#store-action img {
height: 2em;
cursor: pointer;
}

View file

@ -10,14 +10,14 @@
<form id="password-form">
<label for="master-password">Password</label>
<div class="password-container">
<input type="password" id="master-password" />
<input type="password" id="master-password" autofocus />
<img id="master-visibility" class="icon visibility" src="/icons/visibility.svg" />
</div>
<button>Open</button>
</form>
</div>
<div class="entry add hidden" id="entry-add-container">
<img id="logout" class="icon" src="/icons/logout.svg">
<img id="logout" class="icon" src="/icons/logout.svg" title="Logout">
<form id="entry-form">
<div>
<label for="entry-name">Name</label>
@ -33,7 +33,11 @@
</div>
</form>
</div>
<div id="entry-list"></div>
<div id="entry-list">
<div id="store-action" class="hidden">
<img id="export" src="/icons/export.svg" title="Export" />
</div>
</div>
<script src="/popup.js"></script>
</body>
</html>

View file

@ -1,10 +1,11 @@
const body_elt = document.getElementsByTagName('body')[0]
const password_container_elt = document.querySelector('#password-container')
const password_form_elt = document.querySelector('#password-form')
const master_password_elt = document.querySelector('#master-password')
const master_visibility_elt = document.querySelector('#master-visibility')
const entry_add_container_elt = document.querySelector('#entry-add-container')
const logout_elt = document.querySelector('#logout')
const store_action_elt = document.querySelector('#store-action')
const export_elt = document.querySelector('#export')
const entry_form_elt = document.querySelector('#entry-form')
const entry_name_elt = document.querySelector('#entry-name')
const entry_secret_elt = document.querySelector('#entry-secret')
@ -135,11 +136,11 @@ class Store
if(this.key === null)
throw `Cannot save store without key`
let encoder = new TextEncoder();
const entries = this.entries.map(entry => {return {name: entry.name, secret: entry.secret}})
const encrypted = await window.crypto.subtle.encrypt(
{name: 'AES-GCM', iv: this.iv},
this.key,
encoder.encode(JSON.stringify(entries)))
encoder.encode(JSON.stringify(
this.entries.map(entry => {return {name: entry.name, secret: entry.secret}}))))
await browser.storage.local.set({
iv: b32encode(this.iv),
salt: b32encode(this.salt),
@ -169,6 +170,18 @@ class Store
this.entries = []
this.key = null
}
export()
{
let export_elt = document.createElement('a')
export_elt.setAttribute('href', 'data:application/json,' + JSON.stringify(
this.entries.map(entry => {return {name: entry.name, secret: entry.secret}})))
export_elt.setAttribute('download', 'uotp_export.json')
export_elt.style.display = 'none'
document.body.appendChild(export_elt)
export_elt.click()
document.body.removeChild(export_elt)
}
}
let store = new Store()
@ -304,6 +317,7 @@ class Entry
done_elt.addEventListener('click', () => {
this.name = name_input_elt.value
this.elements.title.textContent = this.name
this.secret = secret_input_elt.value
this.regenerateKey().then(() => { this.refresh(Math.floor(Date.now() / 30000)) })
store.save()
@ -340,6 +354,7 @@ async function addEntry(event)
function start()
{
password_container_elt.classList.add('hidden')
store_action_elt.classList.remove('hidden')
entry_add_container_elt.classList.remove('hidden')
const now = Date.now()
if(refresh_timeout !== null)
@ -353,6 +368,7 @@ function start()
function stop()
{
store_action_elt.classList.add('hidden')
entry_add_container_elt.classList.add('hidden')
password_container_elt.classList.remove('hidden')
if(refresh_timeout !== null)
@ -376,6 +392,7 @@ async function init()
background_port.postMessage({command: 'logout', password: master_password_elt.value})
stop()
})
export_elt.addEventListener('click', () => { store.export() })
background_port.postMessage({command: 'init'})
background_port.onMessage.addListener((state) => {