PicList Advanced Synchronization Features: Multi-Cloud Config and Gallery Sync
PicList provides enterprise-grade synchronization capabilities supporting GitHub, Gitee, Gitea, and WebDAV backends, featuring conflict-aware gallery database merging, proxy support, and incremental configuration uploads through a unified TypeScript API.
The open-source image hosting tool PicList (kuingsmile/piclist) extends beyond simple uploads by offering robust advanced synchronization features that keep your configuration files and gallery databases consistent across multiple machines. Whether you need to sync settings between work and home computers or maintain a centralized gallery database in the cloud, PicList's synchronization subsystem handles complex conflict resolution and network configurations automatically.
Multi-Backend Cloud Synchronization Architecture
PicList's synchronization engine in src/main/utils/syncSettings.ts abstracts multiple storage providers behind a unified interface, allowing seamless switching between Git-based and WebDAV backends without changing the high-level API.
Supported Remote Storage Providers
The system currently supports four primary backend types, selected via the syncConfig.type property:
- GitHub: Uses Octokit with optional
HttpsProxyAgentfor corporate environments - Gitee: Native API integration with Chinese hosting optimization
- Gitea: Self-hosted Git platform support
- WebDAV: Generic WebDAV endpoints with basic and digest authentication
Each backend implements the four core operations defined in syncSettings.ts: uploadLocalToRemote, updateLocalToRemote, downloadRemoteToLocal, and checkCloudFileExist.
Core Synchronization Logic in syncSettings.ts
The file src/main/utils/syncSettings.ts contains the primary orchestration logic. Key functions include:
getSyncConfig(): Retrieves user settings frompicgo.getConfig<ISyncConfig>(configPaths.settings.sync)with sensible defaultsisSyncConfigValidate(): Validates required fields per backend type (e.g.,username,repo,tokenfor GitHub)uploadFile(): Implements incremental logic—first attemptingupdateLocalToRemote, falling back touploadLocalToRemoteon 404 errors
Configuration File Synchronization
PicList treats configuration files (data.json, manage.json, etc.) as first-class synchronization citizens, exposing upload and download operations through RPC handlers in src/main/events/rpc/routes/setting/configure.ts.
Uploading Local Configurations
The RPC action CONFIGURE_UPLOAD_ALL_CONFIG triggers uploadFile() with an array of configuration filenames. This operation:
- Validates the sync configuration via
isSyncConfigValidate() - Iterates through the file list, calling
uploadFuncfor each - Uses the incremental upload strategy (update first, then create)
import { uploadFile } from '~/utils/syncSettings';
const files = ['data.json', 'manage.json'];
const uploaded = await uploadFile(files);
console.log(`Uploaded ${uploaded} configuration files`);
Source: src/main/events/rpc/routes/setting/configure.ts lines 107-112
Downloading Remote Configurations
Conversely, CONFIGURE_DOWNLOAD_ALL_CONFIG invokes downloadFile(), which retrieves remote files via downloadRemoteToLocal() and writes them to the local data directory. This enables rapid restoration of settings on new machines.
import { downloadFile } from '~/utils/syncSettings';
await downloadFile(['data.json', 'manage.json']);
Source: src/main/events/rpc/routes/setting/configure.ts lines 128-133
Gallery Database Synchronization with Conflict Resolution
Beyond static configuration files, PicList synchronizes the dynamic gallery database (gallery.db), implementing sophisticated merge logic to handle conflicts when the same image metadata exists in both local and remote versions.
Temporary Workspace Isolation
All gallery sync operations occur within an isolated temporary directory at $TMPDIR/piclist-sync-tmp. The system creates three distinct paths:
localDBPath: Copy of the current local databaseremoteDBPath: Downloaded remote databasedbMerged: Output path for the merged result
This isolation ensures that failed syncs never corrupt the production database.
Timestamp-Based Merge Strategy
The mergeGalleryDB() function implements conflict resolution by comparing updatedAt timestamps:
- Builds a Map of all gallery items from both local and remote databases
- For items existing in both locations, selects the version with the newer
updatedAt - Respects
settings.lastSyncTimeto ignore stale remote items that haven't changed since the last synchronization - Writes the merged result to
dbMergedand uploads it back to the remote
import { syncGallery } from '~/utils/syncSettings';
const syncedCount = await syncGallery();
console.log(`Synchronized ${syncedCount} gallery databases`);
Source: src/main/utils/syncSettings.ts lines 82-88 and merge logic at lines 38-66
Enterprise Features: Proxy and Authentication
PicList's synchronization subsystem includes enterprise-grade networking features for restricted environments and secure authentication.
Corporate Proxy Support
The system automatically detects and uses proxy settings via HttpsProxyAgent for GitHub operations and Axios configurations for WebDAV. The proxy builder in src/main/utils/syncSettings.ts (lines 89-99) constructs the appropriate agent based on user settings, enabling synchronization behind corporate firewalls.
WebDAV Authentication Methods
For WebDAV backends, PicList supports both basic and digest authentication via the AuthType enum from the webdav package. The configuration interface ISyncConfig allows specifying webdavAuthType to match your server's security requirements.
Programmatic API Usage
While the PicList UI exposes these features through the settings panel, developers can invoke synchronization directly via the internal API.
Complete WebDAV Configuration Example
import { ISyncConfig } from '~/types/sync';
import { configPaths } from '~/utils/configPaths';
const webdavSync: ISyncConfig = {
type: 'webdav',
webdavEndpoint: 'https://webdav.example.com',
webdavUsername: 'myUser',
webdavPassword: 'myPass',
webdavAuthType: 'digest', // or 'basic'
webdavSslEnabled: true,
webdavSavePath: '/piclist-sync',
proxy: '', // optional proxy URL
};
picgo.setConfig({ [configPaths.settings.sync]: webdavSync });
Source: Configuration schema defined in src/renderer/utils/configPaths.ts lines 57-58
Batch Configuration Synchronization
import { uploadFile, downloadFile } from '~/utils/syncSettings';
// Upload multiple config files
const uploadResult = await uploadFile(['data.json', 'manage.json', 'settings.json']);
// Download to restore on new machine
await downloadFile(['data.json', 'manage.json']);
Summary
PicList's advanced synchronization features provide production-ready capabilities for maintaining consistency across multiple environments:
- Multi-backend support for GitHub, Gitee, Gitea, and WebDAV with unified API abstractions in
src/main/utils/syncSettings.ts - Intelligent conflict resolution for gallery databases using timestamp-based merging and
lastSyncTimetracking - Isolated temporary workspaces at
$TMPDIR/piclist-sync-tmpensuring safe database operations - Enterprise networking with
HttpsProxyAgentsupport and both basic/digest WebDAV authentication - Incremental upload strategy that updates existing remote files before falling back to creation
- Programmatic accessibility through RPC routes and direct TypeScript API imports
Frequently Asked Questions
How does PicList handle conflicts when syncing the gallery database across multiple devices?
PicList implements timestamp-based conflict resolution in the mergeGalleryDB() function within src/main/utils/syncSettings.ts. When merging local and remote databases, it builds a Map of all gallery items and compares their updatedAt timestamps, keeping the newer version. It also respects the settings.lastSyncTime property to ignore stale remote items that haven't changed since the last synchronization, ensuring the most recent metadata prevails.
What cloud storage providers does PicList support for configuration synchronization?
According to the source code in src/main/utils/syncSettings.ts, PicList supports four primary backend types: GitHub (via Octokit), Gitee, Gitea (self-hosted), and WebDAV (generic). The system uses a switch statement on syncConfig.type to determine which implementation of uploadLocalToRemote, downloadRemoteToLocal, and other operations to invoke, allowing seamless backend swapping without changing the high-level API.
Can PicList synchronize settings behind a corporate firewall or proxy?
Yes, PicList includes enterprise proxy support for all synchronization operations. The src/main/utils/syncSettings.ts file implements proxy handling using HttpsProxyAgent for GitHub API requests and Axios configurations for WebDAV connections. Users can specify a proxy URL in the sync configuration, enabling synchronization from restricted network environments. Additionally, WebDAV authentication supports both basic and digest methods to comply with various corporate security policies.
Is it possible to trigger PicList synchronization programmatically rather than through the GUI?
Absolutely. While the PicList UI exposes sync controls, developers can invoke synchronization directly through the internal TypeScript API. The src/main/utils/syncSettings.ts module exports functions like syncGallery(), uploadFile(), and downloadFile() that can be imported and called programmatically. Additionally, the RPC routes in src/main/events/rpc/routes/setting/configure.ts expose these capabilities to renderer processes, enabling custom scripts and plugins to trigger configuration uploads, downloads, and gallery merges without user interaction.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →