Skip to content

Commit 7c12165

Browse files
committed
feat: predefine server + user by last used with suggestedAccounts config
Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
1 parent 25d133c commit 7c12165

File tree

3 files changed

+106
-8
lines changed

3 files changed

+106
-8
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,36 @@ However, using portable `zip` distribution, you can have several Nextcloud Talk
6868
└── ...
6969
```
7070

71+
## ⌨️ CLI usage
72+
73+
### Application flags
74+
75+
Adjust how the application runs when launching.
76+
77+
| Flag | Description |
78+
|----------------|-------------------------------------------------------------------------------|
79+
| `--background` | Start minimized to the system tray without a window (used for run at startup) |
80+
81+
### CLI commands
82+
83+
Run a command in the app and quit without launching entire app.
84+
85+
#### `config`
86+
87+
Set application configuration.
88+
89+
| Option | Description |
90+
|----------------------------|--------------------------------------------|
91+
| `--accounts=[user@]server` | Comma-separated list of prefilled accounts |
92+
93+
Examples:
94+
95+
```sh
96+
./Nextcloud\ Talk config --accounts=cloud.company.tld
97+
./Nextcloud\ Talk config --accounts='Name Surname@cloud.company.tld'
98+
./Nextcloud\ Talk config --accounts=name@email.tld@company.tld/nextcloud
99+
```
100+
71101
## 🛠️ Development Setup
72102

73103
1. Install dependencies

src/app/cli.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*!
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import type { Argv } from 'mri'
7+
8+
import { app } from 'electron'
9+
import { setAppConfig } from './AppConfig.ts'
10+
11+
/**
12+
* Handle CLI usage
13+
*
14+
* @param argv - Parsed by mri CLI arguments
15+
*/
16+
export async function cli(argv: Argv) {
17+
// TODO: Add --help command
18+
19+
if (!argv._.length) {
20+
return
21+
}
22+
23+
if (argv._[0] === 'config' && argv._.length === 1) {
24+
await handleConfigCommand(argv)
25+
} else {
26+
console.log('Unknown command:', argv._.join(' '))
27+
app.exit(1)
28+
}
29+
30+
app.exit(0)
31+
}
32+
33+
/**
34+
* Handle "config" CLI command
35+
*
36+
* @param argv - Parsed by mri CLI arguments
37+
*/
38+
async function handleConfigCommand(argv: Argv) {
39+
if (!argv.accounts) {
40+
console.log('No config to set')
41+
app.exit(1)
42+
}
43+
44+
// --accounts=user@email.tld@server.tld/nextcloud,nextcloud.local
45+
const accounts = argv.accounts.split(',')
46+
47+
// Validate
48+
for (const account of argv.accounts.split(',')) {
49+
const atIndex = account.lastIndexOf('@')
50+
const [server, user] = atIndex === -1
51+
? [account, '']
52+
: [account.slice(atIndex + 1), account.slice(0, atIndex)]
53+
try {
54+
new URL(`https://${server}`)
55+
} catch {
56+
console.error(`Invalid server: ${server}`)
57+
app.exit(1)
58+
}
59+
if (user && (!/^[a-zA-Z0-9 _.@\-']{1,64}$/.test(user) || user !== user.trim())) {
60+
console.error(`Invalid user: ${user}`)
61+
app.exit(1)
62+
}
63+
}
64+
65+
// Set
66+
await setAppConfig('accounts', accounts)
67+
68+
console.log('Accounts configuration updated')
69+
}

src/main.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
const { app, ipcMain, desktopCapturer, systemPreferences, shell, session } = require('electron')
7+
const { default: mri } = require('mri')
78
const { spawn } = require('node:child_process')
89
const fs = require('node:fs')
910
const path = require('node:path')
@@ -12,6 +13,7 @@ const { loadAppConfig, getAppConfig, setAppConfig } = require('./app/AppConfig.t
1213
const { appData } = require('./app/AppData.js')
1314
const { registerAppProtocolHandler } = require('./app/appProtocol.ts')
1415
const { verifyCertificate, promptCertificateTrust } = require('./app/certificate.service.ts')
16+
const { cli } = require('./app/cli.ts')
1517
const { openChromeWebRtcInternals } = require('./app/dev.utils.ts')
1618
const { triggerDownloadUrl } = require('./app/downloads.ts')
1719
const { setupReleaseNotificationScheduler, registerUpdateIpcHandlers } = require('./app/githubReleaseNotification.service.js')
@@ -31,13 +33,7 @@ const { createTalkWindow } = require('./talk/talk.window.js')
3133
const { createUpgradeWindow } = require('./upgrade/upgrade.window.ts')
3234
const { createWelcomeWindow } = require('./welcome/welcome.window.js')
3335

34-
/**
35-
* Parse command line arguments
36-
*/
37-
const ARGUMENTS = {
38-
// Open Talk window in the background, minimized to the system tray
39-
openInBackground: process.argv.includes('--background'),
40-
}
36+
const argv = mri(process.argv.slice(app.isPackaged ? 1 : 2))
4137

4238
// Electron 36 with Chromium 136 is not compatible with GNOME due to GTK3 with GTK4 mixing
4339
// Workaround: force GTK3
@@ -78,6 +74,7 @@ if (require('electron-squirrel-startup')) {
7874
* Only one instance is allowed at the same time
7975
*/
8076
if (!app.requestSingleInstanceLock()) {
77+
console.log('Another instance of the app is already running')
8178
app.quit()
8279
}
8380

@@ -140,6 +137,8 @@ app.whenReady().then(async () => {
140137
await loadAppConfig()
141138
await runMigrations()
142139

140+
await cli(argv)
141+
143142
applyTheme()
144143
initLaunchAtStartupListener()
145144
registerAppProtocolHandler()
@@ -153,7 +152,7 @@ app.whenReady().then(async () => {
153152
}
154153

155154
// Open in the background if it is explicitly set, or the app was open at login on macOS
156-
const openInBackground = ARGUMENTS.openInBackground || app.getLoginItemSettings().wasOpenedAtLogin
155+
const openInBackground = argv.background || app.getLoginItemSettings().wasOpenedAtLogin
157156

158157
try {
159158
await installVueDevtools()

0 commit comments

Comments
 (0)