diff --git a/src/electron/App/CommunicationMessages.ts b/src/electron/App/CommunicationMessages.ts
index c57e884..e16aa0a 100644
--- a/src/electron/App/CommunicationMessages.ts
+++ b/src/electron/App/CommunicationMessages.ts
@@ -1,39 +1,39 @@
export type IMessages = {
- downloadLinkWritten: {
- ok: string
- },
- accountAndDataDeleted: {
- ok: string
- fail: string
- },
- dataDeleted: {
- ok: string
- fail: string
- },
- generic: {
- ok: string,
- fail: string
- }
+ downloadLinkWritten: {
+ ok: string
+ }
+ accountAndDataDeleted: {
+ ok: string
+ fail: string
+ }
+ dataDeleted: {
+ ok: string
+ fail: string
+ }
+ generic: {
+ ok: string
+ fail: string
+ }
}
const en: IMessages = {
- downloadLinkWritten: {
- ok: `The link was written to the clipboard.\nPaste it in a browser and the database will download.\nRemember to keep it a secret!`
- },
- accountAndDataDeleted: {
- ok: "Account and your data were successfully deleted",
- fail: "Failed to delete your account and/or data"
- },
- dataDeleted: {
- ok: "Failed to delete your data",
- fail: "Data successfully deleted"
- },
- generic: {
- ok: "Operation successfully completed",
- fail: "Operation failed"
- }
+ downloadLinkWritten: {
+ ok: `The link was written to the clipboard.\nPaste it in a browser and the database will download.\nRemember to keep it a secret!`
+ },
+ accountAndDataDeleted: {
+ ok: 'Account and your data were successfully deleted',
+ fail: 'Failed to delete your account and/or data'
+ },
+ dataDeleted: {
+ ok: 'Failed to delete your data',
+ fail: 'Data successfully deleted'
+ },
+ generic: {
+ ok: 'Operation successfully completed',
+ fail: 'Operation failed'
+ }
}
-export const messages = (lang: "en" | "tbd" = "en"): IMessages => {
- return en
-}
\ No newline at end of file
+export const messages = (lang: 'en' | 'tbd' = 'en'): IMessages => {
+ return en
+}
diff --git a/src/electron/App/EventHandler.ts b/src/electron/App/EventHandler.ts
index 92d853e..8d3082c 100644
--- a/src/electron/App/EventHandler.ts
+++ b/src/electron/App/EventHandler.ts
@@ -327,7 +327,7 @@ async function registerUser(rawUser: { name: string; password: string }) {
}
/**
- * Events send by the front-end, not Iohook specific
+ * from frontend, not Iohook specific
*/
const channelsFromRender: IReceiveChannel[] = [
{
@@ -484,6 +484,33 @@ const channelsFromRender: IReceiveChannel[] = [
handler: async (event: any) => {
actionsExported.askPassword()
}
+ },
+ {
+ name: 'to.backend.openImage',
+ handler: async (event: any, hash: string, width: number, height: number) => {
+ const item = await ItemRepo.get(hash)
+ if (!item || item.contentType !== 3) {
+ actionsExported.alertFrontend('cannot open a non image')
+ }
+ const win = new BrowserWindow({
+ height,
+ width,
+ show: false,
+ autoHideMenuBar: true
+ })
+
+ const content = `data:text/html;charset=utf-8,
image taken on ${item?.modified.toLocaleString()}
`
+ win.loadURL(content)
+ win.setAlwaysOnTop(true, 'floating')
+ win.setVisibleOnAllWorkspaces(true)
+ win.once('ready-to-show', () => {
+ win.show()
+ })
+ win.focus()
+ win
+ }
}
]
diff --git a/src/electron/Data/ItemRepository.ts b/src/electron/Data/ItemRepository.ts
index ec6ad62..22e3a96 100644
--- a/src/electron/Data/ItemRepository.ts
+++ b/src/electron/Data/ItemRepository.ts
@@ -38,7 +38,6 @@ const update = (item: IClipboardItem): boolean => {
return false
}
-
const remove = async (hash: string) => {
items.delete(hash)
await RequestService.clips.delete(hash)
@@ -96,7 +95,7 @@ async function loadItemsBeforeDate(date: DateTime, limit: number, masterKey: str
}
let needsLoading = false
if (!state.user) {
- throw new Error("user not found")
+ throw new Error('user not found')
}
// console.log("received items: " + res.data.clips.length)
for (const clip of res.data.clips) {
@@ -136,18 +135,18 @@ export const ItemRepo = {
loadItemsBeforeHash: async (hash: string, password: string, limit = 50) => {
const item = items.get(hash)
if (!item) {
- throw new Error("tried to read before unexisting hash!")
+ throw new Error('tried to read before unexisting hash!')
}
return loadItemsBeforeDate(DateTime.fromJSDate(item.modified), limit, password)
},
cleanUp: async (maxAgeInSeconds: number, maxNumberTotal: number): Promise => {
let changed = false
- changed = changed || await removeOldUnfavored(maxAgeInSeconds)
- changed = changed || await limitMapSize(maxNumberTotal)
+ changed = changed || (await removeOldUnfavored(maxAgeInSeconds))
+ changed = changed || (await limitMapSize(maxNumberTotal))
return changed
},
syncWithRemote: async (password: string) => {
- console.log("syncing")
+ console.log('syncing')
const res = await RequestService.clips.getSince(oldestPull)
if (!res.ok || !res.data) {
actionsExported.logFrontend(messages().generic.fail + `.\nFetch of items since ${oldestPull.toISO()}.`)
@@ -156,9 +155,9 @@ export const ItemRepo = {
oldestPull = DateTime.now()
let needsLoading = false
if (!state.user) {
- throw new Error("user not found")
+ throw new Error('user not found')
}
- console.log("received items after sync: " + res.data.clips.length)
+ console.log('received items after sync: ' + res.data.clips.length)
for (const clip of res.data.clips) {
needsLoading = true
try {
@@ -185,8 +184,7 @@ export const ItemRepo = {
item[1].remoteStatus = RemoteItemStatus.pushedToRemote
} else if (res.status == 409) {
item[1].remoteStatus = RemoteItemStatus.needsUpdateOnRemote
- }
- else {
+ } else {
console.log(await res.text())
}
needsLoading = true
@@ -204,7 +202,7 @@ export const ItemRepo = {
}
console.log('done syncing')
if (needsLoading) {
- console.log("needs loading after remote sync")
+ console.log('needs loading after remote sync')
actionsExported.sendCurrentItems()
}
}
diff --git a/src/electron/Data/RequestUtils.ts b/src/electron/Data/RequestUtils.ts
index e4fde43..e3e70eb 100644
--- a/src/electron/Data/RequestUtils.ts
+++ b/src/electron/Data/RequestUtils.ts
@@ -5,16 +5,13 @@ export const ClipsEndpoints = {
CreateUpdate: `${userPreferences.storeUrl.value}/v1/clips`,
Delete: (hash: string) => `${userPreferences.storeUrl.value}/v1/clips/${hash}`,
GetOne: (hash: string) => `${userPreferences.storeUrl.value}/v1/clips/${hash}`,
- GetAllSince: (time: DateTime) =>
- `${userPreferences.storeUrl.value}/v1/clips/since/${time.toUTC().toISO()}`,
+ GetAllSince: (time: DateTime) => `${userPreferences.storeUrl.value}/v1/clips/since/${time.toUTC().toISO()}`,
GetNBefore: (time: DateTime, limit: number) =>
`${userPreferences.storeUrl.value}/v1/clips/before/${time.toUTC().toISO()}/limit/${limit}`,
GetInBetween: (start: DateTime, end: DateTime) =>
`${userPreferences.storeUrl.value}/v1/clips/between/${start.toUTC().toISO()}/${end.toUTC().toISO()}`,
- DeletAllData: () =>
- `${userPreferences.storeUrl.value}/v1/deleteMyData`,
- GetDatabaseFile: () =>
- `${userPreferences.storeUrl.value}/v1/database`
+ DeletAllData: () => `${userPreferences.storeUrl.value}/v1/deleteMyData`,
+ GetDatabaseFile: () => `${userPreferences.storeUrl.value}/v1/database`
}
export const UserEndpoints = {
@@ -22,5 +19,5 @@ export const UserEndpoints = {
Login: `${userPreferences.authUrl.value}/v1/login`,
RefreshToken: `${userPreferences.authUrl.value}/v1/refresh`,
DeleteProfile: `${userPreferences.authUrl.value}/v1/deleteAccount`,
- Confirm2FA: `${userPreferences.authUrl.value}/v1/confirm2fa`,
+ Confirm2FA: `${userPreferences.authUrl.value}/v1/confirm2fa`
}
diff --git a/src/electron/Data/Requests.ts b/src/electron/Data/Requests.ts
index 0644482..25e8e67 100644
--- a/src/electron/Data/Requests.ts
+++ b/src/electron/Data/Requests.ts
@@ -1,9 +1,9 @@
-import { DateTime } from "luxon"
+import { DateTime } from 'luxon'
import fetch from 'node-fetch'
-import { actionsExported } from "../App/EventHandler"
-import { IClipboardItemEncrypted } from "../DataModels/DataTypes"
-import { BulkRes, CommonRes, LoginRes, RefreshRes, RegisterRes } from "../DataModels/RequestTypes"
-import { ClipsEndpoints, UserEndpoints } from "./RequestUtils"
+import { actionsExported } from '../App/EventHandler'
+import { IClipboardItemEncrypted } from '../DataModels/DataTypes'
+import { BulkRes, CommonRes, LoginRes, RefreshRes, RegisterRes } from '../DataModels/RequestTypes'
+import { ClipsEndpoints, UserEndpoints } from './RequestUtils'
export const userTokens: Tokens = {
access_expires: DateTime.now()
@@ -15,12 +15,12 @@ type Tokens = {
access_expires: DateTime
}
-function request(url: string, method: string = "GET", body?: object, headers?: Record) {
+function request(url: string, method: string = 'GET', body?: object, headers?: Record) {
if (!headers) {
headers = {}
}
if (body) {
- headers["content-type"] = "application/json"
+ headers['content-type'] = 'application/json'
}
const opts = {
@@ -33,20 +33,25 @@ function request(url: string, method: string = "GET", body?: object, headers?: R
}
type ResWrapped = {
- ok: boolean,
- data?: T,
+ ok: boolean
+ data?: T
err?: string
code: number
}
-async function requestWithResponseBody(url: string, method: string = "GET", body?: object, headers?: Record): Promise> {
+async function requestWithResponseBody(
+ url: string,
+ method: string = 'GET',
+ body?: object,
+ headers?: Record
+): Promise> {
const res = await request(url, method, body, headers)
const result: ResWrapped = {
ok: res.ok,
code: res.status
}
if (res.ok) {
- result.data = await res.json() as T
+ result.data = (await res.json()) as T
} else {
result.err = await res.text()
}
@@ -56,7 +61,7 @@ async function requestWithResponseBody(url: string, method: string = "GET", b
async function getAccessToken(): Promise {
if (DateTime.now().plus({ minute: 1 }) > userTokens.access_expires) {
- console.log("access token needs a refresh!")
+ console.log('access token needs a refresh!')
const refreshRes = await RequestService.account.refresh()
if (refreshRes.ok && refreshRes.data) {
userTokens.access_expires = DateTime.now().plus({ minutes: 55 })
@@ -66,25 +71,30 @@ async function getAccessToken(): Promise {
}
}
if (!userTokens.access) {
- actionsExported.logFrontend("Tried to call using an empty token!")
- throw new Error("token not set")
+ actionsExported.logFrontend('Tried to call using an empty token!')
+ throw new Error('token not set')
}
return userTokens.access
}
-async function requestToken(url: string, method: string = "GET", body?: object) {
- return await request(url, method, body, { 'authorization': `Bearer ${await getAccessToken()}` })
+async function requestToken(url: string, method: string = 'GET', body?: object) {
+ return await request(url, method, body, { authorization: `Bearer ${await getAccessToken()}` })
}
-async function requestTokenBody(url: string, method: string = "GET", body?: object) {
- return requestWithResponseBody(url, method, body, { 'authorization': `Bearer ${await getAccessToken()}` })
+async function requestTokenBody(url: string, method: string = 'GET', body?: object) {
+ return requestWithResponseBody(url, method, body, { authorization: `Bearer ${await getAccessToken()}` })
}
export const RequestService = {
account: {
- register: (username: string, remotePass: string) => requestWithResponseBody(UserEndpoints.Register, "POST", { username, password: remotePass }),
- login: (username: string, remotePass: string, code2fa: string) => requestWithResponseBody(UserEndpoints.Login, "POST", { username, password: remotePass, code: code2fa }),
- refresh: () => requestWithResponseBody(UserEndpoints.RefreshToken, "POST", undefined, { "authorization": `Bearer ${userTokens.refresh}` }),
+ register: (username: string, remotePass: string) =>
+ requestWithResponseBody(UserEndpoints.Register, 'POST', { username, password: remotePass }),
+ login: (username: string, remotePass: string, code2fa: string) =>
+ requestWithResponseBody(UserEndpoints.Login, 'POST', { username, password: remotePass, code: code2fa }),
+ refresh: () =>
+ requestWithResponseBody(UserEndpoints.RefreshToken, 'POST', undefined, {
+ authorization: `Bearer ${userTokens.refresh}`
+ }),
logout() {
userTokens.refresh = undefined
userTokens.access = undefined
@@ -95,18 +105,24 @@ export const RequestService = {
const url = ClipsEndpoints.GetDatabaseFile() + `?token=${await getAccessToken()}`
return url
},
- confirm2fa: (code: string, token: string) => requestWithResponseBody(UserEndpoints.Confirm2FA, "POST", {
- code
- }, { "authorization": `Bearer ${token}` })
+ confirm2fa: (code: string, token: string) =>
+ requestWithResponseBody(
+ UserEndpoints.Confirm2FA,
+ 'POST',
+ {
+ code
+ },
+ { authorization: `Bearer ${token}` }
+ )
},
clips: {
- add: (clip: IClipboardItemEncrypted) => requestToken(ClipsEndpoints.CreateUpdate, "POST", clip),
- upsert: (clip: IClipboardItemEncrypted) => requestToken(ClipsEndpoints.CreateUpdate, "PUT", clip),
- update: (clip: { isFavorite: boolean, hash: string }) => requestToken(ClipsEndpoints.CreateUpdate, "PATCH", clip),
- delete: (hash: string) => requestToken(ClipsEndpoints.Delete(hash), "DELETE"),
- getSince: (time: DateTime) => requestTokenBody(ClipsEndpoints.GetAllSince(time), "GET"),
- getBetween: (start: DateTime, end: DateTime) => requestTokenBody(ClipsEndpoints.GetInBetween(start, end), "GET"),
- getNBefore: (time: DateTime, limit: number) => requestTokenBody(ClipsEndpoints.GetNBefore(time, limit), "GET"),
- deleteAll: () => requestTokenBody(ClipsEndpoints.DeletAllData(), "DELETE"),
+ add: (clip: IClipboardItemEncrypted) => requestToken(ClipsEndpoints.CreateUpdate, 'POST', clip),
+ upsert: (clip: IClipboardItemEncrypted) => requestToken(ClipsEndpoints.CreateUpdate, 'PUT', clip),
+ update: (clip: { isFavorite: boolean; hash: string }) => requestToken(ClipsEndpoints.CreateUpdate, 'PATCH', clip),
+ delete: (hash: string) => requestToken(ClipsEndpoints.Delete(hash), 'DELETE'),
+ getSince: (time: DateTime) => requestTokenBody(ClipsEndpoints.GetAllSince(time), 'GET'),
+ getBetween: (start: DateTime, end: DateTime) => requestTokenBody(ClipsEndpoints.GetInBetween(start, end), 'GET'),
+ getNBefore: (time: DateTime, limit: number) => requestTokenBody(ClipsEndpoints.GetNBefore(time, limit), 'GET'),
+ deleteAll: () => requestTokenBody(ClipsEndpoints.DeletAllData(), 'DELETE')
}
-}
\ No newline at end of file
+}
diff --git a/src/electron/DataModels/DataTypes.ts b/src/electron/DataModels/DataTypes.ts
index 7bdf602..bd8b83c 100644
--- a/src/electron/DataModels/DataTypes.ts
+++ b/src/electron/DataModels/DataTypes.ts
@@ -1,6 +1,5 @@
import stringify from 'json-stable-stringify'
-
// export interface IItemsDb {
// Add(item: IClipboardItemEncrypted): Promise
// GetRange(start: number, end: number): Promise
@@ -68,7 +67,7 @@ export enum RemoteItemStatus {
}
export interface IClipboardItem extends ItemBase {
- content: string;
+ content: string
created: Date
modified: Date
remoteStatus: RemoteItemStatus
diff --git a/src/electron/DataModels/RequestTypes.ts b/src/electron/DataModels/RequestTypes.ts
index c90aee1..4838609 100644
--- a/src/electron/DataModels/RequestTypes.ts
+++ b/src/electron/DataModels/RequestTypes.ts
@@ -1,4 +1,4 @@
-import { IClipboardItemEncrypted } from "./DataTypes";
+import { IClipboardItemEncrypted } from './DataTypes'
export interface CommonRes {
message: string
@@ -13,21 +13,20 @@ export interface LoginResTotp {
}
export interface TotpRes {
- qr : string
- secret : string
- token : string
+ qr: string
+ secret: string
+ token: string
}
export interface RefreshRes {
- access_token: string;
- type: string;
+ access_token: string
+ type: string
}
export interface LoginRes extends RefreshRes {
- refresh_token: string;
+ refresh_token: string
}
-
export interface BulkRes {
clips: IClipboardItemEncrypted[]
-}
\ No newline at end of file
+}
diff --git a/src/electron/index.ts b/src/electron/index.ts
index 7846966..7b942be 100644
--- a/src/electron/index.ts
+++ b/src/electron/index.ts
@@ -6,7 +6,6 @@ import CustomWindow from './App/CustomWindow'
import { channelsToRender, ioHookHandler } from './App/EventHandler'
import { userPreferences } from './App/UserPreferences'
-
let mainWindow: CustomWindow
let appIcon: Tray
@@ -70,9 +69,9 @@ app.on('ready', async () => {
appIcon.setToolTip(AppSettings.name)
if (AppSettings.openDevTools) {
- console.log("open dev tools!")
+ console.log('open dev tools!')
setTimeout(() => {
- mainWindow.window.webContents.openDevTools({ mode: "detach" })
+ mainWindow.window.webContents.openDevTools({ mode: 'detach' })
}, 1000)
}
if (AppSettings.isMac) {
@@ -117,16 +116,15 @@ app.on('window-all-closed', () => {
app.quit()
})
-
if (AppSettings.isLinux) {
- app.commandLine.appendSwitch('disable-gpu-sandbox');
+ app.commandLine.appendSwitch('disable-gpu-sandbox')
}
if (AppSettings.enableDevTools && AppSettings.isLinux) {
const port = '8315'
console.log(`starting debugging on port: ${port}. Open http://localhost:${port}`)
- app.commandLine.appendSwitch('remote-debugging-port', port);
- app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
+ app.commandLine.appendSwitch('remote-debugging-port', port)
+ app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')
}
function stopProcessReuse() {
diff --git a/src/frontend/Components/Button.svelte b/src/frontend/Components/Button.svelte
index 02e9a7a..ff3cf02 100644
--- a/src/frontend/Components/Button.svelte
+++ b/src/frontend/Components/Button.svelte
@@ -15,7 +15,7 @@
{#if visible}