Skip to content

Commit

Permalink
feat: tray sync indicator, minimize to tray, start minimized, local o…
Browse files Browse the repository at this point in the history
…ptions saving, bump deps, misc
  • Loading branch information
Dwynr committed Nov 26, 2024
1 parent 709f7eb commit a6ddcf6
Show file tree
Hide file tree
Showing 12 changed files with 459 additions and 337 deletions.
Binary file added assets/icons/tray/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tray/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
289 changes: 98 additions & 191 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@filen/desktop",
"version": "3.0.34",
"buildNumber": 334,
"version": "3.0.35",
"buildNumber": 335,
"description": "Filen Desktop Client",
"author": "Filen Cloud Dienste UG (haftungsbeschränkt) <[email protected]>",
"main": "dist/index.js",
Expand Down Expand Up @@ -65,12 +65,12 @@
"yaml": "^2.6.0"
},
"dependencies": {
"@filen/network-drive": "^0.9.35",
"@filen/s3": "^0.2.45",
"@filen/sdk": "^0.1.183",
"@filen/network-drive": "^0.9.36",
"@filen/s3": "^0.2.46",
"@filen/sdk": "^0.1.187",
"@filen/sync": "^0.1.84",
"@filen/web": "^0.1.67",
"@filen/webdav": "^0.2.60",
"@filen/web": "^0.1.71",
"@filen/webdav": "^0.2.61",
"axios": "^0.28.1",
"cors": "^2.8.5",
"electron-updater": "^6.4.0-alpha.1",
Expand Down
106 changes: 59 additions & 47 deletions src/assets/index.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,64 @@
import { nativeImage } from "electron"
import { nativeImage, type NativeImage } from "electron"
import pathModule from "path"
import memoize from "lodash/memoize"

export const getAppIcon = memoize(() => {
return nativeImage.createFromPath(
pathModule.join(
__dirname,
"..",
"..",
"assets",
"icons",
"app",
`${process.platform}.${process.platform === "win32" ? "ico" : process.platform === "darwin" ? "icns" : "png"}`
)
import { type TrayState } from "../types"

export const OVERLAY_ICON = nativeImage.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "app", "overlay", "0.png"))

export const APP_ICON = nativeImage.createFromPath(
pathModule.join(
__dirname,
"..",
"..",
"assets",
"icons",
"app",
`${process.platform}.${process.platform === "win32" ? "ico" : process.platform === "darwin" ? "icns" : "png"}`
)
})

export const getTrayIcon = memoize((notification: boolean) => {
/*return nativeImage.createFromPath(
pathModule.join(
__dirname,
"..",
"..",
"assets",
"icons",
"tray",
nativeTheme.shouldUseDarkColors ? "light" : "dark",
`${process.platform}${notification ? "Notification" : ""}${process.platform === "darwin" ? "Template" : ""}.${
process.platform === "win32" ? "ico" : process.platform === "darwin" ? "png" : "png"
}`
)
)*/

return nativeImage
.createFromPath(
pathModule.join(__dirname, "..", "..", "assets", "icons", "tray", `${notification ? "[email protected]" : "[email protected]"}`)
)
.resize({
width: 16,
height: 16
})
})
)

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const getOverlayIcon = memoize((notificationCount: number) => {
//const count = notificationCount > 9 ? 99 : notificationCount
export const TRAY_ICON_NORMAL = nativeImage
.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "tray", "[email protected]"))
.resize({
width: 16,
height: 16
})

export const TRAY_ICON_SYNC = nativeImage
.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "tray", "[email protected]"))
.resize({
width: 16,
height: 16
})

const count = 0
export const TRAY_ICON_NOTIFICATION = nativeImage
.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "tray", "[email protected]"))
.resize({
width: 16,
height: 16
})

return nativeImage.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "app", "overlay", `${count}.png`))
})
export const TRAY_ICON_WARNING = nativeImage
.createFromPath(pathModule.join(__dirname, "..", "..", "assets", "icons", "tray", "[email protected]"))
.resize({
width: 16,
height: 16
})

export function getAppIcon(): NativeImage {
return APP_ICON
}

export function getTrayIcon({ notificationCount, isSyncing, warningCount, errorCount }: TrayState): NativeImage {
return notificationCount + errorCount > 0
? TRAY_ICON_NOTIFICATION
: warningCount > 0
? TRAY_ICON_WARNING
: isSyncing
? TRAY_ICON_SYNC
: TRAY_ICON_NORMAL
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function getOverlayIcon(notificationCount: number): NativeImage {
return OVERLAY_ICON
}
118 changes: 46 additions & 72 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, BrowserWindow, shell, Tray, nativeTheme, dialog, Menu } from "electron"
import { app, BrowserWindow, shell, dialog } from "electron"
import pathModule from "path"
import IPC from "./ipc"
import FilenSDK from "@filen/sdk"
Expand All @@ -7,12 +7,14 @@ import Cloud from "./lib/cloud"
import FS from "./lib/fs"
import { IS_ELECTRON } from "./constants"
import Worker from "./worker"
import { getAppIcon, getTrayIcon, getOverlayIcon } from "./assets"
import { getAppIcon } from "./assets"
import Updater from "./lib/updater"
import isDev from "./isDev"
import Logger from "./lib/logger"
import serveProd from "./lib/serve"
import WindowState from "./lib/windowState"
import Status from "./lib/status"
import Options from "./lib/options"

if (IS_ELECTRON) {
// Needs to be here, otherwise Chromium's FileSystemAccess API won't work. Waiting for the electron team to fix it.
Expand Down Expand Up @@ -40,13 +42,14 @@ export class FilenDesktop {
cloud: Cloud
fs: FS
}
public notificationCount = 0
public tray: Tray | null = null
public updater: Updater
public logger: Logger
public isUnityRunning: boolean = process.platform === "linux" ? app.isUnityRunning() : false
public serve: (window: BrowserWindow) => Promise<void>
public windowState: WindowState
public minimizeToTray: boolean = false
public status: Status
public options: Options

/**
* Creates an instance of FilenDesktop.
Expand All @@ -67,6 +70,8 @@ export class FilenDesktop {
this.worker = new Worker(this)
this.updater = new Updater(this)
this.logger = new Logger(false, false)
this.status = new Status(this)
this.options = new Options()
}

/**
Expand Down Expand Up @@ -103,7 +108,14 @@ export class FilenDesktop {
return
}

const options = await this.options.get()

await app.whenReady()

if (options.startMinimized && process.platform === "darwin") {
app?.dock?.hide()
}

await this.createLauncherWindow()

this.initializeSDK()
Expand Down Expand Up @@ -202,7 +214,9 @@ export class FilenDesktop {

await this.launcherWindow.loadFile(pathModule.join("..", "public", "launcher.html"))

if (!app.commandLine.hasSwitch("hidden") && !process.argv.includes("--hidden")) {
const startMinimized = (await this.options.get()).startMinimized ?? false

if (!app.commandLine.hasSwitch("hidden") && !process.argv.includes("--hidden") && !startMinimized) {
this.launcherWindow.show()
}
}
Expand All @@ -216,7 +230,7 @@ export class FilenDesktop {
this.launcherWindow = null
}

private showOrOpenDriveWindow(): void {
public showOrOpenDriveWindow(): void {
if (BrowserWindow.getAllWindows().length === 0) {
this.createMainWindow().catch(err => {
this.logger.log("error", err)
Expand All @@ -225,15 +239,19 @@ export class FilenDesktop {
return
}

this.driveWindow?.show()
if (this.driveWindow?.isMinimized()) {
this.driveWindow?.restore()
} else {
this.driveWindow?.show()
}
}

private async createMainWindow(): Promise<void> {
if (this.driveWindow) {
return
}

const state = await this.windowState.get()
const [state, options] = await Promise.all([this.windowState.get(), this.options.get()])

this.driveWindow = new BrowserWindow({
width: state ? state.width : 1280,
Expand Down Expand Up @@ -263,6 +281,8 @@ export class FilenDesktop {
}
})

this.status.initialize()

if (state) {
this.driveWindow.setBounds({
width: state.width,
Expand All @@ -274,82 +294,36 @@ export class FilenDesktop {

this.windowState.manage(this.driveWindow)

if (!this.tray) {
this.tray = new Tray(getTrayIcon(this.notificationCount > 0))

this.tray.setContextMenu(null)
this.tray.setToolTip("Filen")

this.tray.on("click", () => {
if (process.platform !== "win32") {
return
}

this.showOrOpenDriveWindow()
})

this.tray.setContextMenu(
Menu.buildFromTemplate([
{
label: "Filen",
type: "normal",
icon: getTrayIcon(false),
enabled: false
},
{
label: "Open",
type: "normal",
click: () => {
this.showOrOpenDriveWindow()
}
},
{
label: "Separator",
type: "separator"
},
{
label: "Exit",
type: "normal",
click: () => {
app?.quit()
}
}
])
)
}

if (process.platform === "win32") {
this.driveWindow?.setThumbarButtons([])
}

this.driveWindow.on("closed", () => {
this.driveWindow?.on("closed", () => {
this.driveWindow = null
})

// Handle different icons based on the user's theme (dark/light)
nativeTheme.on("updated", () => {
this.driveWindow?.setIcon(getAppIcon())
this.tray?.setImage(getTrayIcon(this.notificationCount > 0))

if (process.platform === "win32") {
if (this.notificationCount > 0) {
this.driveWindow?.setOverlayIcon(getOverlayIcon(this.notificationCount), this.notificationCount.toString())
} else {
this.driveWindow?.setOverlayIcon(null, "")
}
this.driveWindow?.on("minimize", () => {
if (process.platform === "darwin" && this.minimizeToTray) {
app?.dock?.hide()
}
})

if (process.platform === "darwin") {
app?.dock?.setIcon(getAppIcon())
this.driveWindow?.on("show", () => {
if (process.platform === "darwin" && !app?.dock?.isVisible()) {
app?.dock?.show()
}
})

this.driveWindow?.on("close", e => {
if ((process.platform === "darwin" || this.minimizeToTray) && !this.driveWindow?.isMinimized()) {
e.preventDefault()

if (process.platform === "darwin" || (process.platform === "linux" && this.isUnityRunning)) {
app?.setBadgeCount(this.notificationCount)
this.driveWindow?.minimize()
}
})

// Open links in default external browser
this.driveWindow.webContents.setWindowOpenHandler(({ url }) => {
this.driveWindow?.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url)

return {
Expand All @@ -358,13 +332,13 @@ export class FilenDesktop {
})

if (isDev) {
await this.driveWindow.loadURL("http://localhost:5173")
await this.driveWindow?.loadURL("http://localhost:5173")
} else {
await this.serve(this.driveWindow)
}

if (!app.commandLine.hasSwitch("hidden") && !process.argv.includes("--hidden")) {
this.driveWindow.show()
if (!app.commandLine.hasSwitch("hidden") && !process.argv.includes("--hidden") && !options.startMinimized) {
this.driveWindow?.show()
}
}
}
Expand Down
Loading

0 comments on commit a6ddcf6

Please sign in to comment.