Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Todas las versiones notables de NextSync se documentan aquí. El formato sigue [Keep a Changelog](https://keepachangelog.com/es/1.1.0/) y el versionado es **+0.0.2 por release, reiniciado en 0.1.4** (decisión del usuario, 22-Ago-2026; sustituye al +0.02 anterior).

## [0.2.26] - 2026-09-17

### Added

- The setup wizard blocks finishing when the selected provider's sync engine is not installed, with an actionable hint naming the package (nextcloud-client / opencloud-desktop). The check re-evaluates for the newly selected provider (#210).
- The Arch package lists both sync engines as optional dependencies and warns on install/upgrade when neither nextcloudcmd nor opencloudcmd is available.

## [0.2.24] - 2026-09-17

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nextsync"
version = "0.2.24"
version = "0.2.26"
edition = "2021"
rust-version = "1.83"
license = "GPL-3.0-or-later"
Expand Down
9 changes: 7 additions & 2 deletions PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# Maintainer: gnacho <https://github.com/gnacho>
pkgname=nextsync
pkgver=0.2.24
pkgver=0.2.26
pkgrel=1
pkgdesc='Nextcloud desktop synchronization client for GNOME (Rust rewrite)'
arch=('x86_64' 'aarch64')
url='https://github.com/gnacho/nextsync'
license=('GPL-3.0-or-later')
depends=('gtk4' 'libadwaita' 'glibc' 'gcc-libs')
makedepends=('cargo')
optdepends=('nextcloud-client: nextcloudcmd sync engine')
# pacman has no "A or B" dependency: the engines are alternative optdepends
# and nextsync.install warns at install/upgrade time when NEITHER is present
# (issue #210).
optdepends=('nextcloud-client: nextcloudcmd sync engine (Nextcloud provider)'
'opencloud-desktop: opencloudcmd sync engine (OpenCloud provider)')
install=nextsync.install
source=("nextsync-$pkgver.tar.gz")
sha256sums=('SKIP')

Expand Down
4 changes: 2 additions & 2 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</p>
<p>
<a href="https://github.com/gnacho/nextsync/actions/workflows/ci.yml"><img src="https://github.com/gnacho/nextsync/actions/workflows/ci.yml/badge.svg" alt="Estado de CI"></a>
<img src="https://img.shields.io/badge/version-0.2.24-blue?style=flat-square" alt="Versión 0.2.24">
<img src="https://img.shields.io/badge/version-0.2.26-blue?style=flat-square" alt="Versión 0.2.26">
<img src="https://img.shields.io/badge/license-GPL--3.0%2B-informational?style=flat-square" alt="GNU GPL v3 o posterior">
</p>
</div>
Expand Down Expand Up @@ -84,7 +84,7 @@ Ambos motores se esconden detrás del mismo trait pequeño, así que un proveedo
Descarga el `.pkg.tar.zst` de la [última release](https://github.com/gnacho/nextsync/releases/latest) e instálalo:

```bash
sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst
sudo pacman -U nextsync-0.2.26-1-x86_64.pkg.tar.zst
```

El paquete depende de `gtk4` y `libadwaita`. Para cuentas Nextcloud instala `nextcloud-client` (aporta `nextcloudcmd`); para cuentas OpenCloud, el `opencloudcmd` oficial.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</p>
<p>
<a href="https://github.com/gnacho/nextsync/actions/workflows/ci.yml"><img src="https://github.com/gnacho/nextsync/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
<img src="https://img.shields.io/badge/version-0.2.24-blue?style=flat-square" alt="Version 0.2.24">
<img src="https://img.shields.io/badge/version-0.2.26-blue?style=flat-square" alt="Version 0.2.26">
<img src="https://img.shields.io/badge/license-GPL--3.0%2B-informational?style=flat-square" alt="GNU GPL v3 or later">
</p>
</div>
Expand Down Expand Up @@ -84,7 +84,7 @@ Both engines sit behind the same small trait, so a new provider is a command bui
Download the `.pkg.tar.zst` from the [latest release](https://github.com/gnacho/nextsync/releases/latest) and install it:

```bash
sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst
sudo pacman -U nextsync-0.2.26-1-x86_64.pkg.tar.zst
```

The package depends on `gtk4` and `libadwaita`. For Nextcloud accounts install `nextcloud-client` (it provides `nextcloudcmd`); for OpenCloud accounts, the official `opencloudcmd`.
Expand Down
1 change: 1 addition & 0 deletions data/io.github.gnacho.nextsync.metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<icon type="stock">io.github.gnacho.nextsync</icon>
<content_rating type="oars-1.1"/>
<releases>
<release version="0.2.26" date="2026-09-17"/>
<release version="0.2.24" date="2026-09-17"/>
<release version="0.2.22" date="2026-09-17"/>
<release version="0.2.20" date="2026-09-08"/>
Expand Down
2 changes: 1 addition & 1 deletion landing/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ <h3 data-i18n="compare.ht">Lo que NextSync no hace (todavía)</h3>
<h2 class="reveal" data-i18n="install.title">Instalación fácil y rápida</h2>
<p class="lead reveal" data-i18n="install.lead">En Arch, CachyOS y derivadas hay paquete listo en cada release.</p>
<div class="card install-card reveal">
<pre class="code-block"><code id="installCmd">sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst</code></pre>
<pre class="code-block"><code id="installCmd">sudo pacman -U nextsync-0.2.26-1-x86_64.pkg.tar.zst</code></pre>
<button class="btn suggested" id="copyBtn" data-i18n="install.copy">Copiar comando</button>
<p class="small-print" data-i18n="install.note">Descarga el paquete <code>.pkg.tar.zst</code> más reciente desde <a href="https://github.com/gnacho/nextsync/releases" target="_blank" rel="noopener">GitHub Releases</a> y ajusta el nombre del fichero.</p>
</div>
Expand Down
17 changes: 17 additions & 0 deletions nextsync.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Issue #210: pacman cannot express "at least one of these two packages", so
# both engines ship as optdepends and this script surfaces a clear warning
# when neither sync engine is available after an install or upgrade.

post_install() {
if ! command -v nextcloudcmd >/dev/null 2>&1 \
&& ! command -v opencloudcmd >/dev/null 2>&1; then
echo "nextsync needs at least one sync engine to synchronize:"
echo " - Nextcloud: install nextcloud-client (provides nextcloudcmd)"
echo " - OpenCloud: install opencloud-desktop (provides opencloudcmd)"
echo "Without one of them every synchronization stays blocked."
fi
}

post_upgrade() {
post_install
}
12 changes: 12 additions & 0 deletions po/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -2578,6 +2578,18 @@ msgstr "Tu árbol de archivos completo se almacenará físicamente en este equip
msgid "opencloudcmd is missing. Install the OpenCloud desktop package before the first synchronization."
msgstr "Falta opencloudcmd. Instala el paquete de escritorio de OpenCloud antes de la primera sincronización."

#: src/ui/setup.rs
msgid "nextcloudcmd is missing. Install the nextcloud-client package (it provides the sync engine) and finish the setup afterwards."
msgstr "Falta nextcloudcmd. Instala el paquete nextcloud-client (incluye el motor de sincronización) y termina la configuración después."

#: src/ui/setup.rs
msgid "opencloudcmd is missing. Install the opencloud-desktop package (it provides the sync engine) and finish the setup afterwards."
msgstr "Falta opencloudcmd. Instala el paquete opencloud-desktop (incluye el motor de sincronización) y termina la configuración después."

#: src/ui/setup.rs
msgid "Sync Engine Not Installed"
msgstr "Motor de sincronización no instalado"


#: src/core/scheduler.rs
msgid "Automatic synchronization is off"
Expand Down
76 changes: 76 additions & 0 deletions src/ui/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,18 @@ fn size_threshold_bytes(store: &ConfigStore) -> Option<u64> {
/// Create the local roots, persist the account and the TLS trust choice, then
/// invoke `on_complete` with the validated account and close the wizard.
fn finish_setup(ctx: &SetupContext) {
// Issue #210: block the finish when the selected provider's sync engine
// is not installed. This is the single choke point every finish path
// (first-sync confirmation, resume, decision) goes through, and the
// provider in the state is the freshly selected one, so switching
// providers re-evaluates the check for the new engine.
let provider = ctx.state.borrow().provider;
if let Some(hint) = engine_install_hint(provider, engine_present_for(provider)) {
let dialog = libadwaita::AlertDialog::new(Some(t("Sync Engine Not Installed")), Some(hint));
dialog.add_response("ok", t("OK"));
dialog.present(Some(&ctx.window));
return;
}
let (provider, server, username, authentication_type, folders, trust_invalid, size_confirmed) = {
let state = ctx.state.borrow();
(
Expand Down Expand Up @@ -1646,6 +1658,34 @@ fn update_provider_warning(banner: &libadwaita::Banner, provider: Provider) {
}
}

/// Whether the selected provider's sync binary is available on `$PATH`
/// (issue #210).
fn engine_present_for(provider: Provider) -> bool {
match provider {
Provider::Nextcloud => find_binary("nextcloudcmd").is_some(),
Provider::OpenCloud => find_binary("opencloudcmd").is_some(),
}
}

/// Issue #210: the setup must not present itself as ready when the selected
/// provider's sync engine is not installed. Returns the actionable install
/// hint to block the finish with, or `None` when the engine is present. Kept
/// pure (binary presence passed in) so the policy is testable without a real
/// `$PATH`.
fn engine_install_hint(provider: Provider, engine_present: bool) -> Option<&'static str> {
if engine_present {
return None;
}
match provider {
Provider::Nextcloud => Some(t(
"nextcloudcmd is missing. Install the nextcloud-client package (it provides the sync engine) and finish the setup afterwards.",
)),
Provider::OpenCloud => Some(t(
"opencloudcmd is missing. Install the opencloud-desktop package (it provides the sync engine) and finish the setup afterwards.",
)),
}
}

// ---------------------------------------------------------------------------
// Widget helpers
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -2451,4 +2491,40 @@ mod tests {
let resolved = wizard_remote_picker_password("https://x.example.net", "").unwrap();
assert!(resolved.is_none());
}

/// Issue #210: finishing the setup with the selected provider's engine
/// missing is blocked with an actionable hint naming the package; with
/// the engine present there is no block at all.
#[test]
fn engine_install_hint_blocks_only_when_the_binary_is_missing() {
use crate::nextcloud::driver::Provider;
assert!(
engine_install_hint(Provider::Nextcloud, true).is_none(),
"an installed engine never blocks the setup"
);
assert!(
engine_install_hint(Provider::OpenCloud, true).is_none(),
"an installed engine never blocks the setup"
);
let nextcloud = engine_install_hint(Provider::Nextcloud, false)
.expect("a missing Nextcloud engine blocks the setup");
assert!(
nextcloud.contains("nextcloudcmd"),
"the hint names the binary: {nextcloud}"
);
assert!(
nextcloud.contains("nextcloud-client"),
"the hint names the Arch package: {nextcloud}"
);
let opencloud = engine_install_hint(Provider::OpenCloud, false)
.expect("a missing OpenCloud engine blocks the setup");
assert!(
opencloud.contains("opencloudcmd"),
"the hint names the binary: {opencloud}"
);
assert!(
opencloud.contains("opencloud-desktop"),
"the hint names the Arch package: {opencloud}"
);
}
}
3 changes: 3 additions & 0 deletions src/util/translations/es.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ pub static CATALOG: &[(&str, &str)] = &[
("Startup", "Inicio"),
("Suspend automatic synchronization inside a daily time window", "Suspende la sincronización automática dentro de una franja horaria diaria"),
("Sync Activity and Conflicts", "Actividad y conflictos de sincronización"),
("Sync Engine Not Installed", "Motor de sincronización no instalado"),
("Sync Now", "Sincronizar ahora"),
("Sync Once", "Sincronizar una vez"),
("Sync provider", "Proveedor de sincronización"),
Expand Down Expand Up @@ -495,8 +496,10 @@ pub static CATALOG: &[(&str, &str)] = &[
("conflict on {file}", "conflicto en {file}"),
("deleting {file}", "eliminando {file}"),
("downloading {file}", "descargando {file}"),
("nextcloudcmd is missing. Install the nextcloud-client package (it provides the sync engine) and finish the setup afterwards.", "Falta nextcloudcmd. Instala el paquete nextcloud-client (incluye el motor de sincronización) y termina la configuración después."),
("nextcloudcmd is missing. Install the nextcloud-desktop-cmd package before the first synchronization.", "Falta nextcloudcmd. Instala el paquete nextcloud-desktop-cmd antes de la primera sincronización."),
("opencloudcmd is missing. Install the OpenCloud desktop package before the first synchronization.", "Falta opencloudcmd. Instala el paquete de escritorio de OpenCloud antes de la primera sincronización."),
("opencloudcmd is missing. Install the opencloud-desktop package (it provides the sync engine) and finish the setup afterwards.", "Falta opencloudcmd. Instala el paquete opencloud-desktop (incluye el motor de sincronización) y termina la configuración después."),
("processing {file}", "procesando {file}"),
("uploading {file}", "subiendo {file}"),
("{account}: open NextSync to check the account credential.", "{account}: abre NextSync para comprobar la credencial de la cuenta."),
Expand Down
8 changes: 4 additions & 4 deletions version.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"schema_version": 1,
"version": "0.2.24",
"version": "0.2.26",
"mandatory": false,
"summary": "Folders recover on their own after connectivity returns, even when the recovery probe fired while the machine was offline.",
"summary": "The setup wizard blocks finishing without the selected provider's sync engine, and the package flags when no engine is installed at all.",
"changelog": [
"After a period without connectivity, folders no longer stay Offline until a manual sync or an app restart: when the network comes back, the server recovery probe is re-armed automatically and synchronization resumes on its own.",
"Fixes the case where the one-shot recovery probe fired while the machine was offline, died silently, and the NetworkRestored trigger stayed parked behind the server-unreachable gate forever."
"The setup wizard now refuses to finish when the selected provider's sync engine is missing, with an actionable hint naming the package to install (nextcloud-client / opencloud-desktop). The welcome banner already warned on provider selection; now the finish is blocked too (issue #210).",
"The Arch package lists both sync engines as optional dependencies and prints a clear warning on install/upgrade when neither nextcloudcmd nor opencloudcmd is available, since pacman cannot express an 'at least one' dependency."
],
"released_at": "2026-09-17T00:00:00Z"
}
Loading