mirror of
https://github.com/bitwarden/mobile.git
synced 2025-01-02 18:07:56 +01:00
save last sync in settings
This commit is contained in:
parent
decd3fc24e
commit
71be9f8780
@ -2,6 +2,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Acr.UserDialogs;
|
using Acr.UserDialogs;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
|
using Plugin.Connectivity.Abstractions;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using XLabs.Ioc;
|
using XLabs.Ioc;
|
||||||
|
|
||||||
@ -11,11 +12,13 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
private readonly ISyncService _syncService;
|
private readonly ISyncService _syncService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
|
private readonly IConnectivity _connectivity;
|
||||||
|
|
||||||
public SyncPage()
|
public SyncPage()
|
||||||
{
|
{
|
||||||
_syncService = Resolver.Resolve<ISyncService>();
|
_syncService = Resolver.Resolve<ISyncService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
@ -34,10 +37,21 @@ namespace Bit.App.Pages
|
|||||||
Title = "Sync";
|
Title = "Sync";
|
||||||
Content = stackLayout;
|
Content = stackLayout;
|
||||||
Icon = "fa-refresh";
|
Icon = "fa-refresh";
|
||||||
|
|
||||||
|
if(!_connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
AlertNoConnection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SyncAsync()
|
public async Task SyncAsync()
|
||||||
{
|
{
|
||||||
|
if(!_connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
AlertNoConnection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading("Syncing...", MaskType.Black);
|
_userDialogs.ShowLoading("Syncing...", MaskType.Black);
|
||||||
var succeeded = await _syncService.SyncAsync();
|
var succeeded = await _syncService.SyncAsync();
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
@ -50,5 +64,10 @@ namespace Bit.App.Pages
|
|||||||
_userDialogs.ErrorToast("Syncing failed.");
|
_userDialogs.ErrorToast("Syncing failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AlertNoConnection()
|
||||||
|
{
|
||||||
|
DisplayAlert("No internet connection", "Adding a new folder required an internet connection. Please connect to the internet before continuing.", "Ok");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using Acr.UserDialogs;
|
using Acr.UserDialogs;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
|
using Plugin.Connectivity.Abstractions;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using XLabs.Ioc;
|
using XLabs.Ioc;
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ namespace Bit.App.Pages
|
|||||||
var siteService = Resolver.Resolve<ISiteService>();
|
var siteService = Resolver.Resolve<ISiteService>();
|
||||||
var folderService = Resolver.Resolve<IFolderService>();
|
var folderService = Resolver.Resolve<IFolderService>();
|
||||||
var userDialogs = Resolver.Resolve<IUserDialogs>();
|
var userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
|
var connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
|
|
||||||
var folders = folderService.GetAllAsync().GetAwaiter().GetResult().OrderBy(f => f.Name?.Decrypt());
|
var folders = folderService.GetAllAsync().GetAwaiter().GetResult().OrderBy(f => f.Name?.Decrypt());
|
||||||
|
|
||||||
@ -57,6 +59,12 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
var saveToolBarItem = new ToolbarItem("Save", null, async () =>
|
var saveToolBarItem = new ToolbarItem("Save", null, async () =>
|
||||||
{
|
{
|
||||||
|
if(!connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
AlertNoConnection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(uriEntry.Text))
|
if(string.IsNullOrWhiteSpace(uriEntry.Text))
|
||||||
{
|
{
|
||||||
await DisplayAlert("An error has occurred", "The Uri field is required.", "Ok");
|
await DisplayAlert("An error has occurred", "The Uri field is required.", "Ok");
|
||||||
@ -95,6 +103,17 @@ namespace Bit.App.Pages
|
|||||||
Title = "Add Site";
|
Title = "Add Site";
|
||||||
Content = scrollView;
|
Content = scrollView;
|
||||||
ToolbarItems.Add(saveToolBarItem);
|
ToolbarItems.Add(saveToolBarItem);
|
||||||
|
|
||||||
|
if(!connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
AlertNoConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AlertNoConnection()
|
||||||
|
{
|
||||||
|
DisplayAlert("No internet connection", "Adding a new folder required an internet connection. Please connect to the internet before continuing.", "Ok");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Models.Api;
|
using Bit.App.Models.Api;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Plugin.Settings.Abstractions;
|
using Plugin.Settings.Abstractions;
|
||||||
|
|
||||||
namespace Bit.App.Services
|
namespace Bit.App.Services
|
||||||
|
@ -3,43 +3,56 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Models.Data;
|
using Bit.App.Models.Data;
|
||||||
|
using Plugin.Settings.Abstractions;
|
||||||
|
|
||||||
namespace Bit.App.Services
|
namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
public class SyncService : ISyncService
|
public class SyncService : ISyncService
|
||||||
{
|
{
|
||||||
|
private const string LastSyncKey = "lastSync";
|
||||||
|
|
||||||
private readonly IFolderApiRepository _folderApiRepository;
|
private readonly IFolderApiRepository _folderApiRepository;
|
||||||
private readonly ISiteApiRepository _siteApiRepository;
|
private readonly ISiteApiRepository _siteApiRepository;
|
||||||
private readonly IFolderRepository _folderRepository;
|
private readonly IFolderRepository _folderRepository;
|
||||||
private readonly ISiteRepository _siteRepository;
|
private readonly ISiteRepository _siteRepository;
|
||||||
private readonly IAuthService _authService;
|
private readonly IAuthService _authService;
|
||||||
|
private readonly ISettings _settings;
|
||||||
|
|
||||||
public SyncService(
|
public SyncService(
|
||||||
IFolderApiRepository folderApiRepository,
|
IFolderApiRepository folderApiRepository,
|
||||||
ISiteApiRepository siteApiRepository,
|
ISiteApiRepository siteApiRepository,
|
||||||
IFolderRepository folderRepository,
|
IFolderRepository folderRepository,
|
||||||
ISiteRepository siteRepository,
|
ISiteRepository siteRepository,
|
||||||
IAuthService authService)
|
IAuthService authService,
|
||||||
|
ISettings settings)
|
||||||
{
|
{
|
||||||
_folderApiRepository = folderApiRepository;
|
_folderApiRepository = folderApiRepository;
|
||||||
_siteApiRepository = siteApiRepository;
|
_siteApiRepository = siteApiRepository;
|
||||||
_folderRepository = folderRepository;
|
_folderRepository = folderRepository;
|
||||||
_siteRepository = siteRepository;
|
_siteRepository = siteRepository;
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SyncAsync()
|
public async Task<bool> SyncAsync()
|
||||||
{
|
{
|
||||||
// TODO: store now in settings and only fetch from last time stored
|
var now = DateTime.UtcNow;
|
||||||
var now = DateTime.UtcNow.AddYears(-100);
|
var lastSync = _settings.GetValueOrDefault(LastSyncKey, now.AddYears(-100));
|
||||||
|
|
||||||
var siteTask = await SyncSitesAsync(now);
|
var siteTask = SyncSitesAsync(lastSync);
|
||||||
var folderTask = await SyncFoldersAsync(now);
|
var folderTask = SyncFoldersAsync(lastSync);
|
||||||
|
await Task.WhenAll(siteTask, folderTask);
|
||||||
|
|
||||||
return siteTask && folderTask;
|
if(await siteTask && await folderTask && folderTask.Exception == null && siteTask.Exception == null)
|
||||||
|
{
|
||||||
|
_settings.AddOrUpdateValue(LastSyncKey, now);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> SyncFoldersAsync(DateTime now)
|
private async Task<bool> SyncFoldersAsync(DateTime lastSync)
|
||||||
{
|
{
|
||||||
var folderResponse = await _folderApiRepository.GetAsync();
|
var folderResponse = await _folderApiRepository.GetAsync();
|
||||||
if(!folderResponse.Succeeded)
|
if(!folderResponse.Succeeded)
|
||||||
@ -48,12 +61,12 @@ namespace Bit.App.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var serverFolders = folderResponse.Result.Data;
|
var serverFolders = folderResponse.Result.Data;
|
||||||
var folders = await _folderRepository.GetAllByUserIdAsync(_authService.UserId);
|
var localFolders = await _folderRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
|
|
||||||
foreach(var serverFolder in serverFolders.Where(f => f.RevisionDate >= now))
|
foreach(var serverFolder in serverFolders.Where(f => f.RevisionDate >= lastSync))
|
||||||
{
|
{
|
||||||
var data = new FolderData(serverFolder, _authService.UserId);
|
var data = new FolderData(serverFolder, _authService.UserId);
|
||||||
var existingLocalFolder = folders.SingleOrDefault(f => f.Id == serverFolder.Id);
|
var existingLocalFolder = localFolders.SingleOrDefault(f => f.Id == serverFolder.Id);
|
||||||
if(existingLocalFolder == null)
|
if(existingLocalFolder == null)
|
||||||
{
|
{
|
||||||
await _folderRepository.InsertAsync(data);
|
await _folderRepository.InsertAsync(data);
|
||||||
@ -64,7 +77,7 @@ namespace Bit.App.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var folder in folders.Where(localFolder => !serverFolders.Any(serverFolder => serverFolder.Id == localFolder.Id)))
|
foreach(var folder in localFolders.Where(localFolder => !serverFolders.Any(serverFolder => serverFolder.Id == localFolder.Id)))
|
||||||
{
|
{
|
||||||
await _folderRepository.DeleteAsync(folder.Id);
|
await _folderRepository.DeleteAsync(folder.Id);
|
||||||
}
|
}
|
||||||
@ -72,7 +85,7 @@ namespace Bit.App.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> SyncSitesAsync(DateTime now)
|
private async Task<bool> SyncSitesAsync(DateTime lastSync)
|
||||||
{
|
{
|
||||||
var siteResponse = await _siteApiRepository.GetAsync();
|
var siteResponse = await _siteApiRepository.GetAsync();
|
||||||
if(!siteResponse.Succeeded)
|
if(!siteResponse.Succeeded)
|
||||||
@ -81,12 +94,12 @@ namespace Bit.App.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var serverSites = siteResponse.Result.Data;
|
var serverSites = siteResponse.Result.Data;
|
||||||
var sites = await _siteRepository.GetAllByUserIdAsync(_authService.UserId);
|
var localSites = await _siteRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
|
|
||||||
foreach(var serverSite in serverSites.Where(s => s.RevisionDate >= now))
|
foreach(var serverSite in serverSites.Where(s => s.RevisionDate >= lastSync))
|
||||||
{
|
{
|
||||||
var data = new SiteData(serverSite, _authService.UserId);
|
var data = new SiteData(serverSite, _authService.UserId);
|
||||||
var existingLocalSite = sites.SingleOrDefault(s => s.Id == serverSite.Id);
|
var existingLocalSite = localSites.SingleOrDefault(s => s.Id == serverSite.Id);
|
||||||
if(existingLocalSite == null)
|
if(existingLocalSite == null)
|
||||||
{
|
{
|
||||||
await _siteRepository.InsertAsync(data);
|
await _siteRepository.InsertAsync(data);
|
||||||
@ -97,7 +110,7 @@ namespace Bit.App.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var site in sites.Where(localSite => !serverSites.Any(serverSite => serverSite.Id == localSite.Id)))
|
foreach(var site in localSites.Where(localSite => !serverSites.Any(serverSite => serverSite.Id == localSite.Id)))
|
||||||
{
|
{
|
||||||
await _siteRepository.DeleteAsync(site.Id);
|
await _siteRepository.DeleteAsync(site.Id);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user