A framework for synchronizing files to and from anything.
I'm building and maintaining this package for my open source notetaking app, Saber.
There is a bit of setup required for this package due to its abstract nature.
You can do all of the following in a single file (e.g. my_syncer.dart
)
or organize it however you like.
You can view a simple example of this in the
example file,
or see a real-world example in
Saber's saber_syncer.dart
,
which has added functionality for encryption and caching.
-
Decide on your local and remote file classes. E.g. Saber uses
File
for local files andWebDavFile
for remote files. I will refer to these asMyLocalFile
andMyRemoteFile
respectively, but they can be anything you want. -
Extend the
AbstractSyncFile
class to use the correct generic types.The
AbstractSyncFile
class is intended to help you store more information other than just the local and remote files, such as their path on the remote server, so add any additional fields you need.class MySyncFile extends AbstractSyncFile<MyLocalFile, MyRemoteFile> { MySyncFile({ required super.remoteFile, required super.localFile, }); // Use your IDE to help you implement the necessary methods }
-
Extend the
AbstractSyncInterface
with the correct generic types.The
AbstractSyncInterface
class is how this package can interact with your local and remote files.Your class has to have a
const
constructor which means you can't use variables that aren't final. However, you can usestatic
variables if you need to save state.class MySyncInterface extends AbstractSyncInterface<MySyncFile, MyLocalFile, MyRemoteFile> { const MySyncInterface(); // Use your IDE to help you implement the necessary methods }
-
Finally, we can create a
Syncer
object.The
Syncer
object is what you will interact with outside of this file.final syncer = Syncer<MySyncInterface, MySyncFile, MyLocalFile, MyRemoteFile>( const MySyncInterface(), );
syncer.uploader.enqueue(
// Provide any of syncFile, localFile, or remoteFile
localFile: MyLocalFile(...),
);
syncer.downloader.enqueue(
// Provide any of syncFile, localFile, or remoteFile
remoteFile: MyRemoteFile(...),
);
(The uploader and downloader have an identical interface.)
await syncer.downloader.refresh();
if (syncer.downloader.isRefreshing) {
print('Still checking the server for changes');
}
final subscription = syncer.uploader.transferStream.listen((syncFile) {
print('Uploaded file: $syncFile');
});