Skip to content

Commit

Permalink
Improved import from screen capture #208
Browse files Browse the repository at this point in the history
  • Loading branch information
Levminer committed Apr 28, 2022
1 parent 6c5cf81 commit bcddb1c
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 67 deletions.
47 changes: 23 additions & 24 deletions app/import/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" />
<meta charset="UTF-8" />
<!-- js -->
<script defer src="./src/js/index.js"></script>
<script defer src="./index.js"></script>
<!-- css -->
<link rel="stylesheet" href="../.././styles/global.css" />
<link rel="stylesheet" href="../../styles/tailwind.css" />
Expand Down Expand Up @@ -118,50 +118,49 @@ <h5 data-loc class="m-0 pt-4">Enter a TOTP secret key and name manually.</h5>
</div>
</div>

<details class="details mb-5 transform duration-200 ease-in">
<details open class="details mb-5 transform duration-200 ease-in">
<summary data-loc class="summary mx-auto mt-3 mb-10 cursor-pointer font-bold">More options</summary>

<div class="useWebcam m-1">
<button class="buttoni" onclick="useWebcam()">
<div class="screenCapture m-1 mt-5">
<button class="buttoni w-[576px] sm:w-72" onclick="captureFromScreen()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<circle cx="12" cy="10" r="7"></circle>
<circle cx="12" cy="10" r="3"></circle>
<path d="M8 16l-2.091 3.486a1 1 0 0 0 .857 1.514h10.468a1 1 0 0 0 .857 -1.514l-2.091 -3.486"></path>
<rect x="3" y="4" width="18" height="12" rx="1"></rect>
<line x1="7" y1="20" x2="17" y2="20"></line>
<line x1="9" y1="16" x2="9" y2="20"></line>
<line x1="15" y1="16" x2="15" y2="20"></line>
</svg>
<span data-loc>Use webcam</span>
<span data-loc>Capture screen</span>
</button>
<div class="flex flex-row gap-3">
<h5 data-loc class="m-0 pt-4">Use your webcam to scan a 2FA QR code.</h5>
<h5 data-loc class="m-0 pt-4 pb-4">Capture a 2FA QR code from your screen.</h5>
<div class="tooltipContainer">
<span class="tooltip w-max text-base">Make sure no program uses your webcam.</span>
<span class="tooltip -mt-[48px] w-max text-base">
You will have 5 seconds to navigate to the QR code you want to import. <br />
Authme will capture your screen and import the QR code.
</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
</div>
</div>
<div class="screenCapture m-1 mt-5">
<button class="buttoni w-[576px] sm:w-72" onclick="captureFromScreen()">
<div class="useWebcam m-1">
<button class="buttoni" onclick="useWebcam()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="3" y="4" width="18" height="12" rx="1"></rect>
<line x1="7" y1="20" x2="17" y2="20"></line>
<line x1="9" y1="16" x2="9" y2="20"></line>
<line x1="15" y1="16" x2="15" y2="20"></line>
<circle cx="12" cy="10" r="7"></circle>
<circle cx="12" cy="10" r="3"></circle>
<path d="M8 16l-2.091 3.486a1 1 0 0 0 .857 1.514h10.468a1 1 0 0 0 .857 -1.514l-2.091 -3.486"></path>
</svg>
<span data-loc>Capture screen</span>
<span data-loc>Use webcam</span>
</button>
<div class="flex flex-row gap-3">
<h5 data-loc class="m-0 pt-4 pb-6">Capture a 2FA QR code from your screen.</h5>
<h5 data-loc class="m-0 pt-4">Use your webcam to scan a 2FA QR code.</h5>
<div class="tooltipContainer">
<span class="tooltip -mt-[72px] w-max text-base">
This is a preview feature! <br />
Make sure that the picture is visible <br />
under the application window.
</span>
<span class="tooltip w-max text-base">Make sure no program uses your webcam.</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions app/import/src/js/index.js → app/import/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ const QrcodeDecoder = require("qrcode-decoder").default
const { ipcRenderer: ipc } = require("electron")
const path = require("path")
const fs = require("fs")
const { chooseImages } = require(path.join(__dirname, "src", "js", "images.js"))
const { manualEntry } = require(path.join(__dirname, "src", "js", "manual.js"))
const { useWebcam } = require(path.join(__dirname, "src", "js", "webcam.js"))
const { captureFromScreen } = require(path.join(__dirname, "src", "js", "screen.js"))
const { chooseImages } = require("./src/js/images")
const { manualEntry } = require("./src/js/manual")
const { captureFromScreen } = require("./src/js/screen")
const { useWebcam } = require("./src/js/webcam")

/**
* Send error to main process
Expand Down Expand Up @@ -68,7 +68,7 @@ const examplesLink = () => {
* Hide window
*/
const hide = () => {
ipc.send("toggleImport")
ipc.invoke("toggleToolsWindow")
}

/**
Expand Down
94 changes: 58 additions & 36 deletions app/import/src/js/screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,69 @@ module.exports = {
/**
* Read QR code from screen capture
*/
captureFromScreen: () => {
captureFromScreen: async () => {
const window = BrowserWindow.getFocusedWindow()
let string = ""
let counter = 0

await dialog.showMessageBox(window, {
title: "Authme",
buttons: [lang.button.close],
type: "info",
noLink: true,
defaultId: 1,
cancelId: 1,
message: `${lang.import_dialog.before_capture}`,
})

desktopCapturer.getSources({ types: ["screen"], thumbnailSize: { height: 1280, width: 720 } }).then(async (sources) => {
const thumbnail = sources[0].thumbnail.toDataURL()
const interval = setInterval(() => {
counter++

document.querySelector(".thumbnail").src = thumbnail
document.querySelector(".thumbnailContainer").style.display = "block"
if (counter === 10) {
clearInterval(interval)
}
}, 1000)

document.querySelector(".removeThumbnail").addEventListener("click", () => {
document.querySelector(".thumbnailContainer").style.display = "none"
})
setTimeout(() => {
desktopCapturer.getSources({ types: ["screen"], thumbnailSize: { height: 1280, width: 720 } }).then(async (sources) => {
const thumbnail = sources[0].thumbnail.toDataURL()

try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: sources[0].id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720,
},
},
})
document.querySelector(".thumbnail").src = thumbnail
document.querySelector(".thumbnailContainer").style.display = "block"

qrHandleStream(stream)
} catch (error) {
dialog.showMessageBox(BrowserWindow.getFocusedWindow(), {
title: "Authme",
buttons: [lang.button.close],
type: "error",
noLink: true,
message: `${lang.import_dialog.capture_error} \n\n${error}`,
document.querySelector(".removeThumbnail").addEventListener("click", () => {
document.querySelector(".thumbnailContainer").style.display = "none"
})

logger.error("Error starting capture!", error.stack)
}
})
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: sources[0].id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720,
},
},
})

qrHandleStream(stream)
} catch (error) {
dialog.showMessageBox(window, {
title: "Authme",
buttons: [lang.button.close],
type: "error",
noLink: true,
message: `${lang.import_dialog.capture_error} \n\n${error}`,
})

logger.error("Error starting capture!", error.stack)
}
})
}, 5000)

const qrHandleStream = async (stream) => {
const track = stream.getTracks()[0]
Expand All @@ -71,7 +93,7 @@ module.exports = {

const save_exists = fs.existsSync(path.join(folder_path, "codes", "codes.authme"))

const result = await dialog.showMessageBox(BrowserWindow.getFocusedWindow(), {
const result = await dialog.showMessageBox(window, {
title: "Authme",
buttons: [lang.button.yes, lang.button.no],
type: "info",
Expand Down Expand Up @@ -100,7 +122,7 @@ module.exports = {
reader.stop()
track.stop()
} else {
dialog.showMessageBox(BrowserWindow.getFocusedWindow(), {
dialog.showMessageBox(window, {
title: "Authme",
buttons: [lang.button.close],
type: "error",
Expand All @@ -115,7 +137,7 @@ module.exports = {

setTimeout(() => {
if (code_found === false) {
dialog.showMessageBox(BrowserWindow.getFocusedWindow(), {
dialog.showMessageBox(window, {
title: "Authme",
buttons: [lang.button.close],
type: "error",
Expand Down
2 changes: 2 additions & 0 deletions app/settings/src/js/shortcuts.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-nocheck

/**
* Default shortcuts
*/
Expand Down
3 changes: 2 additions & 1 deletion languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,10 @@ module.exports = {
"no_qrcode_found_0": "No QR code found on the picture:",
"no_qrcode_found_1": "\n\nTry to take a better picture and try again!",
"correct_qrcode_found_0": "QR codes imported, go back to the main page to see and save the codes.",
"correct_qrcode_found_1": "\n\nDo you want to save the file for a backup?",
"correct_qrcode_found_1": "\n\nDo you want to save the import file for a backup?",
"wrong_qrcode_found_0": "Wrong QR code found on the picture:",
"wrong_qrcode_found_1": "\n\nMake sure this is a correct QR code and try again!",
"before_capture": "After you close this dialog you will have 10 seconds to navigate to the QR code you want to import. \n\nAuthme will capture your screen and import the QR code.",
"capture_error": "Error starting capture!",
"no_qrcode_captured": "Not found any QR code on your screen! Make sure the QR code is visible or try to screenshot the QR code and import it as an image!",
"issuer_required": "The name field is required. \n\nPlease try again!",
Expand Down
1 change: 1 addition & 0 deletions languages/hu.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ module.exports = {
"correct_qrcode_found_1": "\n\nEl akarod menteni az import fájlt a biztonság kedvéért?",
"wrong_qrcode_found_0": "Nem megfelelő QR-kód van ezeken a képeken:",
"wrong_qrcode_found_1": "\n\nGyőződj meg róla hogy ez egy jó QR-kód!",
"before_capture": "Miután bezárod ezt az üzenetet 10 másodperced lesz eljutni a QR-kódhóz. \n\nAz Authme készít egy képet a képernyődről, majd beimportálja a QR-kódot.",
"capture_error": "Nem sikerült a képernyő rögzítése!",
"no_qrcode_captured": "Nem sikerült QR-kódot találni a képernyődön! Győződj meg róla hogy a QR-kód látható vagy próbálj meg egy képernyőképet készíteni a QR-kódról és importáld be képként!",
"issuer_required": "A név megadása kötelező. \n\nPróbálkozz újra!",
Expand Down
2 changes: 1 addition & 1 deletion styles/tailwind.css

Large diffs are not rendered by default.

0 comments on commit bcddb1c

Please sign in to comment.