sync method

Future sync({
  1. bool forceDownload = false,
  2. bool forceUpload = false,
  3. bool ignoreError = false,
})
  • Initiate download from remote if getLocalSaveTime < google drive save time

  • Initiate upload to remote if getLocalSaveTime > google drive save time

  • Auto skip or no real action (no throw) if

    • enable is false, except when forceDownload or forceUpload is true
    • error.value is true, except ignoreError set to true
    • forceDownload and remote file does not exist
    • syncing.value is true, syncing is in progress
    • local(from getLocalSaveTime) and remote save time are same
  • syncing.value : will be set to true at beginning and to false when done.

  • error.value : will be set to true on error. Reset(to false) on successful sync.

  • forceDownload : when set to true, will initiate download from remote regardless of save time on both sides

  • forceUpload : when set to true, will initiate upload to remote regardless of save time on both sides

  • Throw if

    • Both forceDownload and forceUpload are true.
    • token is empty.

Implementation

Future sync({
  bool forceDownload = false,
  bool forceUpload = false,
  bool ignoreError = false,
}) async {
  String debugPrefix = '$runtimeType.sync()';

  lazy.log(
      '$debugPrefix:forceDownload=$forceDownload:forceUpload=$forceUpload:ignoreError=$ignoreError');

  if (!enable && !forceDownload && !forceUpload) {
    lazy.log('$debugPrefix:enable=$enable');
    return;
  }
  if (syncing.value) {
    lazy.log('$debugPrefix:syncing already in progress');
    return;
  }
  if (error.value && !ignoreError) {
    lazy.log('$debugPrefix:error=${error.value}');
    return;
  }

  try {
    if (forceDownload == true && forceUpload == true) {
      throw ('[forceDownload] and [forceUpload] cannot be `true` at the same time.');
    }
    if (token.isEmpty) {
      throw ('[token] must be set.');
    }

    _lazyGDrive.token = token;

    syncing.value = true;

    // Remote file meta
    gd.File? gFile = await _lazyGDrive.getLatest(name: filename);
    int lastSaveMillisecondsRemote =
        (gFile?.modifiedTime ?? DateTime(0)).millisecondsSinceEpoch;

    // Local info
    int lastSaveMillisecondsLocal = localSaveTime.millisecondsSinceEpoch;

    // Sync logic
    if (gFile != null &&
        (forceDownload ||
            lastSaveMillisecondsRemote > lastSaveMillisecondsLocal)) {
      // remote file exist and is newer or forced -> download
      String content = await _lazyGDrive.download(gFile);
      if (setLocalContent == null) {
        throw ('setLocalContent callback not provided.');
      }
      setLocalContent!(content, gFile.modifiedTime);
    } else if (forceUpload ||
        lastSaveMillisecondsRemote < lastSaveMillisecondsLocal) {
      // no remote or local is newer or forced -> upload

      // Not using `update` nor `updateContent` as they cannot set modifiedTime
      _lazyGDrive.upload(
        name: filename,
        content: content,
        modifiedTime: localSaveTime,
      );
    } else {
      lazy.log('$debugPrefix:already up to date');
    }
    // clean up
    await _lazyGDrive.delCopies(name: filename);

    error.value = false;
    syncing.value = false;
    _lastSync = DateTime.now();
  } catch (e) {
    error.value = true;
    syncing.value = false;
    lazy.log('$debugPrefix:catch:$e');
  }
}