syncUp method
Uploads preferences embedded in the current avatar.
Downloads the current avatar, appends serialized preferences, and re-uploads. The avatar image is preserved — only the trailing payload changes.
If the user has no avatar, the server's generated placeholder is used as the base image, which becomes the user's new avatar.
Clears the dirty flag on success.
Implementation
Future<void> syncUp() async {
final userDto = await _authRepository.refreshLogin();
final filename = userDto.avatarFilename ?? '';
final avatarBytes = await _portalService.getAvatar(filename);
// Strip any existing payload to avoid nesting
final (:jpeg, version: _, data: _) = decodeAvatarPayload(avatarBytes);
final prefs = await _toMap();
final combined = encodeAvatarPayload(jpeg, prefs);
final newFilename = await _portalService.uploadAvatar(combined, filename);
final user = await _database.select(_database.users).getSingle();
await (_database.update(_database.users)
..where((u) => u.id.equals(user.id)))
.write(UsersCompanion(avatarFilename: Value(newFilename)));
_dirty = false;
}