fix(sync): show context-aware permission error for Flatpak/Snap

Add isFlatpak() detection to Electron API and show environment-specific
error messages when file permission errors occur during sync:
- Flatpak users see Flatseal and ~/.var/app/ guidance
- Snap users see 'snap connect' and ~/snap/... guidance
- Other users see generic permission error

Addresses #4078
This commit is contained in:
Johannes Millan 2025-12-22 15:11:50 +01:00
parent ed2dbfbc27
commit 18a0e78f12
5 changed files with 20 additions and 2 deletions

View file

@ -83,6 +83,8 @@ export interface ElectronAPI {
isSnap(): boolean;
isFlatpak(): boolean;
// SEND
// ----
reloadMainWin(): void;

View file

@ -59,6 +59,7 @@ const ea: ElectronAPI = {
isLinux: () => process.platform === 'linux',
isMacOS: () => process.platform === 'darwin',
isSnap: () => process && process.env && !!process.env.SNAP,
isFlatpak: () => process && process.env && !!process.env.FLATPAK_ID,
// SEND
// ----

View file

@ -35,6 +35,7 @@ import { DialogIncoherentTimestampsErrorComponent } from './dialog-incoherent-ti
import { SyncLog } from '../../core/log';
import { promiseTimeout } from '../../util/promise-timeout';
import { devError } from '../../util/dev-error';
import { IS_ELECTRON } from '../../app.constants';
@Injectable({
providedIn: 'root',
@ -244,7 +245,7 @@ export class SyncWrapperService {
return 'HANDLED_ERROR';
} else if (this._isPermissionError(error)) {
this._snackService.open({
msg: T.F.SYNC.S.ERROR_PERMISSION,
msg: this._getPermissionErrorMessage(),
type: 'ERROR',
config: { duration: 12000 },
});
@ -388,6 +389,16 @@ export class SyncWrapperService {
return /EROFS|EACCES|EPERM|read-only file system|permission denied/i.test(errStr);
}
private _getPermissionErrorMessage(): string {
if (IS_ELECTRON && window.ea?.isFlatpak?.()) {
return T.F.SYNC.S.ERROR_PERMISSION_FLATPAK;
}
if (IS_ELECTRON && window.ea?.isSnap?.()) {
return T.F.SYNC.S.ERROR_PERMISSION_SNAP;
}
return T.F.SYNC.S.ERROR_PERMISSION;
}
private lastConflictDialog?: MatDialogRef<any, any>;
private _openConflictDialog$(

View file

@ -1179,6 +1179,8 @@ const T = {
ERROR_DATA_IS_CURRENTLY_WRITTEN: 'F.SYNC.S.ERROR_DATA_IS_CURRENTLY_WRITTEN',
ERROR_FALLBACK_TO_BACKUP: 'F.SYNC.S.ERROR_FALLBACK_TO_BACKUP',
ERROR_PERMISSION: 'F.SYNC.S.ERROR_PERMISSION',
ERROR_PERMISSION_FLATPAK: 'F.SYNC.S.ERROR_PERMISSION_FLATPAK',
ERROR_PERMISSION_SNAP: 'F.SYNC.S.ERROR_PERMISSION_SNAP',
ERROR_INVALID_DATA: 'F.SYNC.S.ERROR_INVALID_DATA',
ERROR_NO_REV: 'F.SYNC.S.ERROR_NO_REV',
ERROR_UNABLE_TO_READ_REMOTE_DATA: 'F.SYNC.S.ERROR_UNABLE_TO_READ_REMOTE_DATA',

View file

@ -1159,7 +1159,9 @@
"BTN_FORCE_OVERWRITE": "Force Overwrite",
"ERROR_CORS": "WebDAV Sync Error: Network request failed.\n\nThis might be a CORS issue. Please ensure:\n• Your WebDAV server allows Cross-Origin requests\n• The server URL is correct and accessible\n• You have a working internet connection",
"ERROR_DATA_IS_CURRENTLY_WRITTEN": "Remote Data is currently being written",
"ERROR_PERMISSION": "File access denied. If using Flatpak/Snap, grant filesystem permission via Flatseal or use a path inside ~/.var/app/",
"ERROR_PERMISSION": "File access denied. Please check your filesystem permissions.",
"ERROR_PERMISSION_FLATPAK": "File access denied. Grant filesystem permission via Flatseal or use a path inside ~/.var/app/",
"ERROR_PERMISSION_SNAP": "File access denied. Run 'snap connect super-productivity:home' or use a path inside ~/snap/super-productivity/common/",
"ERROR_FALLBACK_TO_BACKUP": "Something went wrong while importing the data. Falling back to local backup.",
"ERROR_INVALID_DATA": "Error while syncing. Invalid data",
"ERROR_NO_REV": "No valid rev for remote file",