mirror of
https://github.com/bitwarden/mobile
synced 2025-12-28 06:03:40 +00:00
reset for v2
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDataObject<T> where T : IEquatable<T>
|
||||
{
|
||||
T Id { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ITreeNodeObject
|
||||
{
|
||||
string Id { get; set; }
|
||||
string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAccountsApiRepository
|
||||
{
|
||||
Task<ApiResult<PreloginResponse>> PostPreloginAsync(PreloginRequest requestObj);
|
||||
Task<ApiResult> PostRegisterAsync(RegisterRequest requestObj);
|
||||
Task<ApiResult> PostPasswordHintAsync(PasswordHintRequest requestObj);
|
||||
Task<ApiResult<DateTime?>> GetAccountRevisionDateAsync();
|
||||
Task<ApiResult<ProfileResponse>> GetProfileAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IApiRepository<TRequest, TResponse, TId>
|
||||
where TRequest : class
|
||||
where TResponse : class
|
||||
where TId : IEquatable<TId>
|
||||
{
|
||||
Task<ApiResult<TResponse>> GetByIdAsync(TId id);
|
||||
Task<ApiResult<ListResponse<TResponse>>> GetAsync();
|
||||
Task<ApiResult<TResponse>> PostAsync(TRequest requestObj);
|
||||
Task<ApiResult<TResponse>> PutAsync(TId id, TRequest requestObj);
|
||||
Task<ApiResult> DeleteAsync(TId id);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAttachmentRepository : IRepository<AttachmentData, string>
|
||||
{
|
||||
Task<IEnumerable<AttachmentData>> GetAllByCipherIdAsync(string cipherId);
|
||||
Task<IEnumerable<AttachmentData>> GetAllByUserIdAsync(string userId);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherApiRepository : IApiRepository<CipherRequest, CipherResponse, string>
|
||||
{
|
||||
Task<ApiResult<CipherResponse>> PostAttachmentAsync(string cipherId, byte[] data, string key, string fileName);
|
||||
Task<ApiResult> DeleteAttachmentAsync(string cipherId, string attachmentId);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherCollectionRepository
|
||||
{
|
||||
Task<IEnumerable<CipherCollectionData>> GetAllByUserIdAsync(string userId);
|
||||
Task<IEnumerable<CipherCollectionData>> GetAllByUserIdCollectionAsync(string userId, string collectionId);
|
||||
Task InsertAsync(CipherCollectionData obj);
|
||||
Task DeleteAsync(CipherCollectionData obj);
|
||||
Task DeleteByUserIdAsync(string userId);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherRepository : IRepository<CipherData, string>
|
||||
{
|
||||
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId);
|
||||
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId, bool favorite);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICollectionRepository : IRepository<CollectionData, string>
|
||||
{
|
||||
Task<IEnumerable<CollectionData>> GetAllByUserIdAsync(string userId);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IConnectApiRepository
|
||||
{
|
||||
Task<ApiResult<TokenResponse>> PostTokenAsync(TokenRequest requestObj);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Repositories;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDeviceApiRepository : IApiRepository<DeviceRequest, DeviceResponse, string>
|
||||
{
|
||||
Task<ApiResult> PutTokenAsync(string identifier, DeviceTokenRequest request);
|
||||
Task<ApiResult> PutClearTokenAsync(string identifier);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IFolderApiRepository : IApiRepository<FolderRequest, FolderResponse, string>
|
||||
{ }
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IFolderRepository : IRepository<FolderData, string>
|
||||
{
|
||||
Task<IEnumerable<FolderData>> GetAllByUserIdAsync(string userId);
|
||||
Task DeleteWithCipherUpdateAsync(string id, DateTime revisionDate);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IRepository<T, TId>
|
||||
where T : class, IDataObject<TId>, new()
|
||||
where TId : IEquatable<TId>
|
||||
{
|
||||
Task<T> GetByIdAsync(TId id);
|
||||
Task<IEnumerable<T>> GetAllAsync();
|
||||
Task UpdateAsync(T obj);
|
||||
Task InsertAsync(T obj);
|
||||
Task UpsertAsync(T obj);
|
||||
Task DeleteAsync(TId id);
|
||||
Task DeleteAsync(T obj);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISettingsApiRepository
|
||||
{
|
||||
Task<ApiResult<DomainsResponse>> GetDomains(bool excluded = false);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISettingsRepository : IRepository<SettingsData, string>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISyncApiRepository
|
||||
{
|
||||
Task<ApiResult<SyncResponse>> Get();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ITwoFactorApiRepository
|
||||
{
|
||||
Task<ApiResult> PostSendEmailLoginAsync(TwoFactorEmailRequest requestObj);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAppIdService
|
||||
{
|
||||
string AppId { get; }
|
||||
string AnonymousAppId { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAppInfoService
|
||||
{
|
||||
string Build { get; }
|
||||
string Version { get; }
|
||||
bool AutofillAccessibilityServiceEnabled { get; }
|
||||
bool AutofillServiceEnabled { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAppSettingsService
|
||||
{
|
||||
bool Locked { get; set; }
|
||||
int FailedPinAttempts { get; set; }
|
||||
DateTime LastActivity { get; set; }
|
||||
DateTime LastCacheClear { get; set; }
|
||||
bool AutofillPersistNotification { get; set; }
|
||||
bool AutofillPasswordField { get; set; }
|
||||
bool DisableWebsiteIcons { get; set; }
|
||||
string SecurityStamp { get; set; }
|
||||
string BaseUrl { get; set; }
|
||||
string WebVaultUrl { get; set; }
|
||||
string ApiUrl { get; set; }
|
||||
string IdentityUrl { get; set; }
|
||||
string IconsUrl { get; set; }
|
||||
bool ClearCiphersCache { get; set; }
|
||||
bool ClearExtensionCiphersCache { get; set; }
|
||||
bool OrganizationGivesPremium { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using Bit.App.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAuthService
|
||||
{
|
||||
bool IsAuthenticated { get; }
|
||||
string UserId { get; set; }
|
||||
string PreviousUserId { get; }
|
||||
bool UserIdChanged { get; }
|
||||
string Email { get; set; }
|
||||
KdfType Kdf { get; set; }
|
||||
int KdfIterations { get; set; }
|
||||
string PIN { get; set; }
|
||||
bool BelongsToOrganization(string orgId);
|
||||
void LogOut(string logoutMessage = null);
|
||||
Task<FullLoginResult> TokenPostAsync(string email, string masterPassword);
|
||||
Task<LoginResult> TokenPostTwoFactorAsync(TwoFactorProviderType type, string token, bool remember, string email,
|
||||
string masterPasswordHash, SymmetricCryptoKey key);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Models.Api;
|
||||
using System;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherService
|
||||
{
|
||||
Task<Cipher> GetByIdAsync(string id);
|
||||
Task<IEnumerable<Cipher>> GetAllAsync();
|
||||
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
|
||||
Task<IEnumerable<Cipher>> GetAllByFolderAsync(string folderId);
|
||||
Task<IEnumerable<Cipher>> GetAllByCollectionAsync(string collectionId);
|
||||
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
|
||||
Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher);
|
||||
Task UpsertDataAsync(CipherData cipher, bool sendMessage, bool created);
|
||||
Task<ApiResult> DeleteAsync(string id);
|
||||
Task DeleteDataAsync(string id, bool sendMessage);
|
||||
Task<byte[]> DownloadAndDecryptAttachmentAsync(string url, CipherString key, string orgId = null);
|
||||
Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Cipher cipher, byte[] data, string fileName);
|
||||
Task UpsertAttachmentDataAsync(IEnumerable<AttachmentData> attachments);
|
||||
Task<ApiResult> DeleteAttachmentAsync(Cipher cipher, string attachmentId);
|
||||
Task DeleteAttachmentDataAsync(string attachmentId);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICollectionService
|
||||
{
|
||||
Task<Collection> GetByIdAsync(string id);
|
||||
Task<IEnumerable<Collection>> GetAllAsync();
|
||||
Task<IEnumerable<Tuple<string, string>>> GetAllCipherAssociationsAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Models.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICryptoService
|
||||
{
|
||||
SymmetricCryptoKey Key { get; set; }
|
||||
SymmetricCryptoKey EncKey { get; }
|
||||
byte[] PrivateKey { get; }
|
||||
IDictionary<string, SymmetricCryptoKey> OrgKeys { get; }
|
||||
void SetEncKey(CipherString encKeyEnc);
|
||||
void SetPrivateKey(CipherString privateKeyEnc);
|
||||
void SetOrgKeys(ProfileResponse profile);
|
||||
void SetOrgKeys(Dictionary<string, string> orgKeysEncDict);
|
||||
SymmetricCryptoKey GetOrgKey(string orgId);
|
||||
void ClearKeys();
|
||||
string Decrypt(CipherString encyptedValue, SymmetricCryptoKey key = null);
|
||||
byte[] DecryptToBytes(CipherString encyptedValue, SymmetricCryptoKey key = null);
|
||||
byte[] DecryptToBytes(byte[] encyptedValue, SymmetricCryptoKey key = null);
|
||||
byte[] RsaDecryptToBytes(CipherString encyptedValue, byte[] privateKey);
|
||||
CipherString Encrypt(string plaintextValue, SymmetricCryptoKey key = null);
|
||||
byte[] EncryptToBytes(byte[] plainBytes, SymmetricCryptoKey key = null);
|
||||
SymmetricCryptoKey MakeKeyFromPassword(string password, string salt, KdfType kdf, int kdfIterations);
|
||||
byte[] HashPassword(SymmetricCryptoKey key, string password);
|
||||
string HashPasswordBase64(SymmetricCryptoKey key, string password);
|
||||
Tuple<SymmetricCryptoKey, CipherString> MakeEncKey(SymmetricCryptoKey key);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDatabaseService
|
||||
{
|
||||
void CreateTables();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDeviceActionService
|
||||
{
|
||||
Task ShowLoadingAsync(string text);
|
||||
Task HideLoadingAsync();
|
||||
void Toast(string text, bool longDuration = false);
|
||||
void CopyToClipboard(string text);
|
||||
bool OpenFile(byte[] fileData, string id, string fileName);
|
||||
bool CanOpenFile(string fileName);
|
||||
Task SelectFileAsync();
|
||||
void ClearCache();
|
||||
void Autofill(Models.Page.VaultListPageModel.Cipher cipher);
|
||||
void CloseAutofill();
|
||||
void Background();
|
||||
void RateApp();
|
||||
void DismissKeyboard();
|
||||
void OpenAccessibilitySettings();
|
||||
void OpenAutofillSettings();
|
||||
Task LaunchAppAsync(string appName, Page page);
|
||||
Task<string> DisplayPromptAync(string title = null, string description = null, string text = null);
|
||||
Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDeviceInfoService
|
||||
{
|
||||
string Type { get; }
|
||||
string Model { get; }
|
||||
int Version { get; }
|
||||
float Scale { get; }
|
||||
bool NfcEnabled { get; }
|
||||
bool HasCamera { get; }
|
||||
bool AutofillServiceSupported { get; }
|
||||
bool HasFaceIdSupport { get; }
|
||||
bool IsExtension { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IFolderService
|
||||
{
|
||||
Task<Folder> GetByIdAsync(string id);
|
||||
Task<IEnumerable<Folder>> GetAllAsync();
|
||||
Task<ApiResult<FolderResponse>> SaveAsync(Folder folder);
|
||||
Task<ApiResult> DeleteAsync(string folderId);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IGoogleAnalyticsService
|
||||
{
|
||||
void TrackPage(string pageName);
|
||||
void TrackAppEvent(string eventName, string label = null);
|
||||
void TrackExtensionEvent(string eventName, string label = null);
|
||||
void TrackAutofillExtensionEvent(string eventName, string label = null);
|
||||
void TrackEvent(string category, string eventName, string label = null);
|
||||
void TrackException(string message, bool fatal);
|
||||
void Dispatch(Action completionHandler = null);
|
||||
void SetAppOptOut(bool optOut);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IHttpService
|
||||
{
|
||||
ApiHttpClient ApiClient { get; }
|
||||
IdentityHttpClient IdentityClient { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IKeyDerivationService
|
||||
{
|
||||
byte[] DeriveKey(byte[] password, byte[] salt, uint rounds);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementations of this interface MUST convert iOS and Android
|
||||
/// platform-specific locales to a value supported in .NET because
|
||||
/// ONLY valid .NET cultures can have their RESX resources loaded and used.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lists of valid .NET cultures can be found here:
|
||||
/// http://www.localeplanet.com/dotnet/
|
||||
/// http://www.csharp-examples.net/culture-names/
|
||||
/// You should always test all the locales implemented in your application.
|
||||
/// </remarks>
|
||||
public interface ILocalizeService
|
||||
{
|
||||
/// <summary>
|
||||
/// This method must evaluate platform-specific locale settings
|
||||
/// and convert them (when necessary) to a valid .NET locale.
|
||||
/// </summary>
|
||||
CultureInfo GetCurrentCultureInfo();
|
||||
|
||||
/// <summary>
|
||||
/// CurrentCulture and CurrentUICulture must be set in the platform project,
|
||||
/// because the Thread object can't be accessed in a PCL.
|
||||
/// </summary>
|
||||
void SetLocale(CultureInfo ci);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ILockService
|
||||
{
|
||||
void UpdateLastActivity();
|
||||
Task<LockType> GetLockTypeAsync(bool forceLock, bool onlyIfAlreadyLocked = false);
|
||||
Task CheckLockAsync(bool forceLock, bool onlyIfAlreadyLocked = false);
|
||||
bool TopPageIsLock();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ILogService
|
||||
{
|
||||
void WriteLine(string message);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPasswordGenerationService
|
||||
{
|
||||
string GeneratePassword(
|
||||
int? length = null,
|
||||
bool? uppercase = null,
|
||||
bool? lowercase = null,
|
||||
bool? numbers = null,
|
||||
bool? special = null,
|
||||
bool? ambiguous = null,
|
||||
int? minUppercase = null,
|
||||
int? minLowercase = null,
|
||||
int? minNumbers = null,
|
||||
int? minSpecial = null);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationService
|
||||
{
|
||||
string Token { get; }
|
||||
void Register();
|
||||
void Unregister();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationListener
|
||||
{
|
||||
void OnMessage(JObject values, string device);
|
||||
void OnRegistered(string token, string device);
|
||||
void OnUnregistered(string device);
|
||||
void OnError(string message, string device);
|
||||
bool ShouldShowNotification();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISecureStorageService
|
||||
{
|
||||
void Store(string key, byte[] dataBytes);
|
||||
byte[] Retrieve(string key);
|
||||
void Delete(string key);
|
||||
bool Contains(string key);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
Task<IEnumerable<IEnumerable<string>>> GetEquivalentDomainsAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using SQLite;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISqlService
|
||||
{
|
||||
SQLiteConnection GetConnection();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ISyncService
|
||||
{
|
||||
bool SyncInProgress { get; }
|
||||
Task<bool> SyncCipherAsync(string id);
|
||||
Task<bool> SyncFolderAsync(string id);
|
||||
Task<bool> SyncDeleteFolderAsync(string id, DateTime revisionDate);
|
||||
Task<bool> SyncDeleteCipherAsync(string id);
|
||||
Task<bool> SyncSettingsAsync();
|
||||
Task<bool> SyncProfileAsync();
|
||||
Task<bool> FullSyncAsync(bool forceSync = false);
|
||||
Task<bool> FullSyncAsync(TimeSpan syncThreshold, bool forceSync = false);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ITokenService
|
||||
{
|
||||
string Token { get; set; }
|
||||
string RefreshToken { get; set; }
|
||||
string GetTwoFactorToken(string email);
|
||||
void SetTwoFactorToken(string email, string token);
|
||||
DateTime TokenExpiration { get; }
|
||||
string TokenIssuer { get; }
|
||||
bool TokenExpired { get; }
|
||||
TimeSpan TokenTimeRemaining { get; }
|
||||
bool TokenNeedsRefresh { get; }
|
||||
string TokenUserId { get; }
|
||||
string TokenEmail { get; }
|
||||
string TokenName { get; }
|
||||
bool TokenPremium { get; }
|
||||
}
|
||||
}
|
||||
327
src/App/App.cs
327
src/App/App.cs
@@ -1,327 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Pages;
|
||||
using Xamarin.Forms;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Plugin.Settings.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Plugin.Connectivity.Abstractions;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.App.Models;
|
||||
|
||||
namespace Bit.App
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
private AppOptions _options;
|
||||
private readonly IAuthService _authService;
|
||||
private readonly IDatabaseService _databaseService;
|
||||
private readonly IConnectivity _connectivity;
|
||||
private readonly ISyncService _syncService;
|
||||
private readonly ISettings _settings;
|
||||
private readonly ILockService _lockService;
|
||||
private readonly ILocalizeService _localizeService;
|
||||
private readonly IAppInfoService _appInfoService;
|
||||
private readonly IAppSettingsService _appSettingsService;
|
||||
private readonly IDeviceActionService _deviceActionService;
|
||||
|
||||
public App(
|
||||
AppOptions options,
|
||||
IAuthService authService,
|
||||
IConnectivity connectivity,
|
||||
IDatabaseService databaseService,
|
||||
ISyncService syncService,
|
||||
ISettings settings,
|
||||
ILockService lockService,
|
||||
ILocalizeService localizeService,
|
||||
IAppInfoService appInfoService,
|
||||
IAppSettingsService appSettingsService,
|
||||
IDeviceActionService deviceActionService)
|
||||
{
|
||||
_options = options ?? new AppOptions();
|
||||
_authService = authService;
|
||||
_databaseService = databaseService;
|
||||
_connectivity = connectivity;
|
||||
_syncService = syncService;
|
||||
_settings = settings;
|
||||
_lockService = lockService;
|
||||
_localizeService = localizeService;
|
||||
_appInfoService = appInfoService;
|
||||
_appSettingsService = appSettingsService;
|
||||
_deviceActionService = deviceActionService;
|
||||
|
||||
SetCulture();
|
||||
SetStyles();
|
||||
|
||||
if(authService.IsAuthenticated)
|
||||
{
|
||||
if(_options.FromAutofillFramework && _options.SaveType.HasValue)
|
||||
{
|
||||
MainPage = new ExtendedNavigationPage(new VaultAddCipherPage(_options));
|
||||
}
|
||||
else if(_options.Uri != null)
|
||||
{
|
||||
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options));
|
||||
}
|
||||
else
|
||||
{
|
||||
MainPage = new MainPage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MainPage = new ExtendedNavigationPage(new HomePage());
|
||||
}
|
||||
|
||||
MessagingCenter.Subscribe<Application, bool>(Current, "Resumed", async (sender, forceLock) =>
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(async () => await _lockService.CheckLockAsync(forceLock));
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected async override void OnStart()
|
||||
{
|
||||
// Handle when your app starts
|
||||
await _lockService.CheckLockAsync(false);
|
||||
|
||||
if(string.IsNullOrWhiteSpace(_options.Uri))
|
||||
{
|
||||
var updated = Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService, _syncService);
|
||||
if(!updated)
|
||||
{
|
||||
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
if((DateTime.UtcNow - _appSettingsService.LastCacheClear).TotalDays >= 1)
|
||||
{
|
||||
await Task.Run(() => _deviceActionService.ClearCache()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Debug.WriteLine("OnStart");
|
||||
}
|
||||
|
||||
protected override void OnSleep()
|
||||
{
|
||||
// Handle when your app sleeps
|
||||
Debug.WriteLine("OnSleep");
|
||||
|
||||
SetMainPageFromAutofill();
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android && !_lockService.TopPageIsLock())
|
||||
{
|
||||
_lockService.UpdateLastActivity();
|
||||
}
|
||||
}
|
||||
|
||||
protected async override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
|
||||
// workaround for app compat bug
|
||||
// ref https://forums.xamarin.com/discussion/62414/app-resuming-results-in-crash-with-formsappcompatactivity
|
||||
await Task.Delay(10);
|
||||
|
||||
// Handle when your app resumes
|
||||
Debug.WriteLine("OnResume");
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
await _lockService.CheckLockAsync(false);
|
||||
}
|
||||
|
||||
var lockPinPage = Current.MainPage.Navigation.ModalStack.LastOrDefault() as LockPinPage;
|
||||
if(lockPinPage != null)
|
||||
{
|
||||
lockPinPage.PinControl.Entry.FocusWithDelay();
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
if((now - _appSettingsService.LastCacheClear).TotalDays >= 1
|
||||
&& (now - _appSettingsService.LastActivity).TotalHours >= 1)
|
||||
{
|
||||
await Task.Run(() => _deviceActionService.ClearCache()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetMainPageFromAutofill()
|
||||
{
|
||||
if(Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(_options.Uri) &&
|
||||
!_options.FromAutofillFramework)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
Current.MainPage = new MainPage();
|
||||
_options.Uri = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FullSyncAsync()
|
||||
{
|
||||
if(_connectivity.IsConnected)
|
||||
{
|
||||
var attempt = 0;
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
await _syncService.FullSyncAsync(TimeSpan.FromMinutes(30)).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
catch(WebException)
|
||||
{
|
||||
Debug.WriteLine("Failed to full sync.");
|
||||
if(attempt >= 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
attempt++;
|
||||
}
|
||||
catch(Exception e) when(e is TaskCanceledException || e is OperationCanceledException)
|
||||
{
|
||||
Debug.WriteLine("Cancellation exception.");
|
||||
break;
|
||||
}
|
||||
} while(attempt <= 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("Not connected.");
|
||||
}
|
||||
}
|
||||
|
||||
private void SetStyles()
|
||||
{
|
||||
var gray = Color.FromHex("333333");
|
||||
var grayLight = Color.FromHex("777777");
|
||||
var grayLighter = Color.FromHex("d2d6de");
|
||||
var primaryColor = Color.FromHex("3c8dbc");
|
||||
var primaryColorAccent = Color.FromHex("286090");
|
||||
|
||||
Resources = new ResourceDictionary();
|
||||
|
||||
// Labels
|
||||
|
||||
Resources.Add("text-muted", new Style(typeof(Label))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Label.TextColorProperty, Value = grayLight }
|
||||
}
|
||||
});
|
||||
|
||||
// Buttons
|
||||
|
||||
Resources.Add("btn-default", new Style(typeof(Button))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.TextColorProperty, Value = gray }
|
||||
}
|
||||
});
|
||||
|
||||
Resources.Add("btn-primary", new Style(typeof(Button))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.TextColorProperty, Value = Color.White },
|
||||
new Setter { Property = Button.BackgroundColorProperty, Value = primaryColor },
|
||||
new Setter { Property = Button.FontAttributesProperty, Value = FontAttributes.Bold },
|
||||
new Setter { Property = Button.BorderRadiusProperty, Value = 0 }
|
||||
}
|
||||
});
|
||||
|
||||
Resources.Add("btn-primaryAccent", new Style(typeof(Button))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.TextColorProperty, Value = primaryColorAccent }
|
||||
}
|
||||
});
|
||||
|
||||
Resources.Add("btn-white", new Style(typeof(Button))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.BackgroundColorProperty, Value = Color.White },
|
||||
new Setter { Property = Button.TextColorProperty, Value = primaryColor },
|
||||
new Setter { Property = Button.FontAttributesProperty, Value = FontAttributes.Bold },
|
||||
new Setter { Property = Button.BorderRadiusProperty, Value = 0 }
|
||||
}
|
||||
});
|
||||
|
||||
Resources.Add(new Style(typeof(Button))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.TextColorProperty, Value = primaryColor }
|
||||
}
|
||||
});
|
||||
|
||||
Resources.Add(new Style(typeof(ExtendedButton))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = Button.TextColorProperty, Value = primaryColor }
|
||||
}
|
||||
});
|
||||
|
||||
// List View
|
||||
|
||||
Resources.Add(new Style(typeof(ExtendedListView))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = ListView.SeparatorColorProperty, Value = grayLighter }
|
||||
}
|
||||
});
|
||||
|
||||
// Search Bar
|
||||
|
||||
Resources.Add(new Style(typeof(SearchBar))
|
||||
{
|
||||
Setters = {
|
||||
new Setter { Property = SearchBar.CancelButtonColorProperty, Value = primaryColor }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void SetCulture()
|
||||
{
|
||||
Debug.WriteLine("====== resource debug info =========");
|
||||
var assembly = typeof(App).GetTypeInfo().Assembly;
|
||||
foreach(var res in assembly.GetManifestResourceNames())
|
||||
{
|
||||
Debug.WriteLine("found resource: " + res);
|
||||
}
|
||||
Debug.WriteLine("====================================");
|
||||
|
||||
// This lookup NOT required for Windows platforms - the Culture will be automatically set
|
||||
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
var ci = _localizeService.GetCurrentCultureInfo();
|
||||
AppResources.Culture = ci;
|
||||
_localizeService.SetLocale(ci);
|
||||
}
|
||||
|
||||
// Calendars are removed by linker. ref https://bugzilla.xamarin.com/show_bug.cgi?id=59077
|
||||
new System.Globalization.ThaiBuddhistCalendar();
|
||||
new System.Globalization.HijriCalendar();
|
||||
new System.Globalization.UmAlQuraCalendar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net471</TargetFrameworks>
|
||||
<RootNamespace>Bit.App</RootNamespace>
|
||||
<AssemblyName>BitwardenApp</AssemblyName>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Configurations>Debug;Release;FDroid</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)' == 'FDroid|netstandard2.0|AnyCPU'">
|
||||
<DefineConstants>TRACE;FDROID;NETSTANDARD2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)' == 'FDroid|net471|AnyCPU'">
|
||||
<DefineConstants>TRACE;FDROID;NET471</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\public_suffix_list.dat" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\public_suffix_list.dat" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HockeySDK.Xamarin" Version="5.1.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="PCLCrypto" Version="2.0.147" />
|
||||
<PackageReference Include="Plugin.Fingerprint" Version="1.4.9" />
|
||||
<PackageReference Include="Refractored.FloatingActionButtonForms" Version="2.1.0" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.5.231" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.2.0" />
|
||||
<PackageReference Include="Xam.Plugins.Settings" Version="3.1.1" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.4.859" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.4.0.1008975" />
|
||||
<PackageReference Include="XLabs.IoC" Version="2.0.5782" />
|
||||
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.1.47" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\AppResources.cs.Designer.cs">
|
||||
<DependentUpon>AppResources.cs.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.da.Designer.cs">
|
||||
<DependentUpon>AppResources.da.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.de.Designer.cs">
|
||||
<DependentUpon>AppResources.de.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>AppResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.es.Designer.cs">
|
||||
<DependentUpon>AppResources.es.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.fi.Designer.cs">
|
||||
<DependentUpon>AppResources.fi.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.fr.Designer.cs">
|
||||
<DependentUpon>AppResources.fr.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.hi.Designer.cs">
|
||||
<DependentUpon>AppResources.hi.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.hr.Designer.cs">
|
||||
<DependentUpon>AppResources.hr.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.hu.Designer.cs">
|
||||
<DependentUpon>AppResources.hu.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.id.Designer.cs">
|
||||
<DependentUpon>AppResources.id.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.it.Designer.cs">
|
||||
<DependentUpon>AppResources.it.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.ja.Designer.cs">
|
||||
<DependentUpon>AppResources.ja.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.nl.Designer.cs">
|
||||
<DependentUpon>AppResources.nl.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.pl.Designer.cs">
|
||||
<DependentUpon>AppResources.pl.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.pt-BR.Designer.cs">
|
||||
<DependentUpon>AppResources.pt-BR.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.pt-PT.Designer.cs">
|
||||
<DependentUpon>AppResources.pt-PT.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.ro.Designer.cs">
|
||||
<DependentUpon>AppResources.ro.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.ru.Designer.cs">
|
||||
<DependentUpon>AppResources.ru.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.sk.Designer.cs">
|
||||
<DependentUpon>AppResources.sk.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.sv.Designer.cs">
|
||||
<DependentUpon>AppResources.sv.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.th.Designer.cs">
|
||||
<DependentUpon>AppResources.th.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.tr.Designer.cs">
|
||||
<DependentUpon>AppResources.tr.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.uk.Designer.cs">
|
||||
<DependentUpon>AppResources.uk.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.vi.Designer.cs">
|
||||
<DependentUpon>AppResources.vi.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.zh-Hans.Designer.cs">
|
||||
<DependentUpon>AppResources.zh-Hans.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
<Compile Update="Resources\AppResources.zh-Hant.Designer.cs">
|
||||
<DependentUpon>AppResources.zh-Hant.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\AppResources.cs.resx">
|
||||
<LastGenOutput>AppResources.cs.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.da.resx">
|
||||
<LastGenOutput>AppResources.da.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.de.resx">
|
||||
<LastGenOutput>AppResources.de.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.es.resx">
|
||||
<LastGenOutput>AppResources.es.Designer.cs</LastGenOutput>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.fi.resx">
|
||||
<LastGenOutput>AppResources.fi.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.fr.resx">
|
||||
<LastGenOutput>AppResources.fr.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.hi.resx">
|
||||
<LastGenOutput>AppResources.hi.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.hr.resx">
|
||||
<LastGenOutput>AppResources.hr.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.hu.resx">
|
||||
<LastGenOutput>AppResources.hu.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.id.resx">
|
||||
<LastGenOutput>AppResources.id.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.it.resx">
|
||||
<LastGenOutput>AppResources.it.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.ja.resx">
|
||||
<LastGenOutput>AppResources.ja.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.nl.resx">
|
||||
<LastGenOutput>AppResources.nl.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.pl.resx">
|
||||
<LastGenOutput>AppResources.pl.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.pt-BR.resx">
|
||||
<LastGenOutput>AppResources.pt-BR.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.pt-PT.resx">
|
||||
<LastGenOutput>AppResources.pt-PT.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.ro.resx">
|
||||
<LastGenOutput>AppResources.ro.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.ru.resx">
|
||||
<LastGenOutput>AppResources.ru.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.sk.resx">
|
||||
<LastGenOutput>AppResources.sk.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.sv.resx">
|
||||
<LastGenOutput>AppResources.sv.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.th.resx">
|
||||
<LastGenOutput>AppResources.th.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.tr.resx">
|
||||
<LastGenOutput>AppResources.tr.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.uk.resx">
|
||||
<LastGenOutput>AppResources.uk.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.vi.resx">
|
||||
<LastGenOutput>AppResources.vi.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.zh-Hans.resx">
|
||||
<LastGenOutput>AppResources.zh-Hans.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\AppResources.zh-Hant.resx">
|
||||
<LastGenOutput>AppResources.zh-Hant.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,56 +0,0 @@
|
||||
namespace Bit.App
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string AndroidAppProtocol = "androidapp://";
|
||||
public const string iOSAppProtocol = "iosapp://";
|
||||
|
||||
public const string SettingFingerprintUnlockOn = "setting:fingerprintUnlockOn";
|
||||
public const string SettingPinUnlockOn = "setting:pinUnlockOn";
|
||||
public const string SettingLockSeconds = "setting:lockSeconds";
|
||||
public const string SettingGaOptOut = "setting:googleAnalyticsOptOut";
|
||||
public const string SettingDisableWebsiteIcons = "setting:disableWebsiteIcons";
|
||||
public const string SettingDisableTotpCopy = "setting:disableAutoCopyTotp";
|
||||
public const string AutofillPersistNotification = "setting:persistNotification";
|
||||
public const string AutofillPasswordField = "setting:autofillPasswordField";
|
||||
|
||||
public const string PasswordGeneratorLength = "pwGenerator:length";
|
||||
public const string PasswordGeneratorUppercase = "pwGenerator:uppercase";
|
||||
public const string PasswordGeneratorLowercase = "pwGenerator:lowercase";
|
||||
public const string PasswordGeneratorNumbers = "pwGenerator:numbers";
|
||||
public const string PasswordGeneratorMinNumbers = "pwGenerator:minNumbers";
|
||||
public const string PasswordGeneratorSpecial = "pwGenerator:special";
|
||||
public const string PasswordGeneratorMinSpecial = "pwGenerator:minSpecial";
|
||||
public const string PasswordGeneratorAmbiguous = "pwGenerator:ambiguous";
|
||||
|
||||
public const string PushInitialPromptShown = "push:initialPromptShown";
|
||||
public const string PushLastRegistrationDate = "push:lastRegistrationDate";
|
||||
public const string PushCurrentToken = "push:currentToken";
|
||||
public const string PushRegisteredToken = "push:registeredToken";
|
||||
|
||||
public const string ExtensionStarted = "extension:started";
|
||||
public const string ExtensionActivated = "extension:activated";
|
||||
|
||||
public const string SecurityStamp = "other:securityStamp";
|
||||
public const string LastActivityDate = "other:lastActivityDate";
|
||||
public const string LastActivityLockTime = "other:lastActivityLockTime";
|
||||
public const string LastCacheClearDate = "other:cacheClearDate";
|
||||
public const string Locked = "other:locked";
|
||||
public const string LockTimerId = "other:lockTimerId";
|
||||
public const string LastLoginEmail = "other:lastLoginEmail";
|
||||
public const string LastSync = "other:lastSync";
|
||||
public const string LastBuildKey = "LastBuild";
|
||||
public const string BaseUrl = "other:baseUrl";
|
||||
public const string WebVaultUrl = "other:webVaultUrl";
|
||||
public const string ApiUrl = "other:apiUrl";
|
||||
public const string IdentityUrl = "other:identityUrl";
|
||||
public const string IconsUrl = "other:iconsUrl";
|
||||
public const string FailedPinAttempts = "other:failedPinAttempts";
|
||||
public const string ClearCiphersCache = "other:clearCiphersCache";
|
||||
public const string ClearExtensionCiphersCache = "other:clearExtensionCiphersCache";
|
||||
public const string OrgGivesPremium = "other:orgGivesPremium";
|
||||
|
||||
public const int SelectFileRequestCode = 42;
|
||||
public const int SelectFilePermissionRequestCode = 43;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class AddCipherToolBarItem : ExtendedToolbarItem
|
||||
{
|
||||
public AddCipherToolBarItem(Page page, string folderId)
|
||||
: base(() => Helpers.AddCipher(page, folderId))
|
||||
{
|
||||
Text = AppResources.Add;
|
||||
Icon = "plus.png";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class DismissModalToolBarItem : ExtendedToolbarItem, IDisposable
|
||||
{
|
||||
private readonly ContentPage _page;
|
||||
|
||||
public DismissModalToolBarItem(ContentPage page, string text = null, Action cancelClickedAction = null)
|
||||
: base(cancelClickedAction)
|
||||
{
|
||||
_page = page;
|
||||
// TODO: init and dispose events from pages
|
||||
InitEvents();
|
||||
Text = text ?? AppResources.Close;
|
||||
Icon = Helpers.ToolbarImage("ion_chevron_left.png");
|
||||
Priority = -1;
|
||||
}
|
||||
|
||||
protected async override void ClickedItem(object sender, EventArgs e)
|
||||
{
|
||||
base.ClickedItem(sender, e);
|
||||
await _page.Navigation.PopForDeviceAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using Bit.App.Utilities;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedButton : Button
|
||||
{
|
||||
public static readonly BindableProperty PaddingProperty =
|
||||
BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(ExtendedButton), default(Thickness));
|
||||
public static readonly BindableProperty UppercaseProperty =
|
||||
BindableProperty.Create(nameof(Uppercase), typeof(bool), typeof(ExtendedButton),
|
||||
Helpers.OnPlatform(iOS: false, Android: true, Windows: false));
|
||||
|
||||
public Thickness Padding
|
||||
{
|
||||
get { return (Thickness)GetValue(PaddingProperty); }
|
||||
set { SetValue(PaddingProperty, value); }
|
||||
}
|
||||
|
||||
public bool Uppercase
|
||||
{
|
||||
get { return (bool)GetValue(UppercaseProperty); }
|
||||
set { SetValue(UppercaseProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Pages;
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Ioc;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedContentPage : ContentPage
|
||||
{
|
||||
private ISyncService _syncService;
|
||||
private IGoogleAnalyticsService _googleAnalyticsService;
|
||||
private ILockService _lockService;
|
||||
private IDeviceActionService _deviceActionService;
|
||||
private IAuthService _authService;
|
||||
private bool _syncIndicator;
|
||||
private bool _updateActivity;
|
||||
private bool _requireAuth;
|
||||
|
||||
public ExtendedContentPage(bool syncIndicator = false, bool updateActivity = true, bool requireAuth = true)
|
||||
{
|
||||
_syncIndicator = syncIndicator;
|
||||
_updateActivity = updateActivity;
|
||||
_requireAuth = requireAuth;
|
||||
_syncService = Resolver.Resolve<ISyncService>();
|
||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||
_lockService = Resolver.Resolve<ILockService>();
|
||||
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
|
||||
_authService = Resolver.Resolve<IAuthService>();
|
||||
|
||||
BackgroundColor = Color.FromHex("efeff4");
|
||||
}
|
||||
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
if(_requireAuth && !_authService.IsAuthenticated)
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(
|
||||
() => Application.Current.MainPage = new ExtendedNavigationPage(new HomePage()));
|
||||
}
|
||||
|
||||
if(_syncIndicator)
|
||||
{
|
||||
MessagingCenter.Subscribe<Application, bool>(Application.Current, "SyncCompleted",
|
||||
(sender, success) => Device.BeginInvokeOnMainThread(() => IsBusy = _syncService.SyncInProgress));
|
||||
MessagingCenter.Subscribe<ISyncService>(Application.Current, "SyncStarted",
|
||||
(sender) => Device.BeginInvokeOnMainThread(() => IsBusy = _syncService.SyncInProgress));
|
||||
}
|
||||
|
||||
if(_syncIndicator)
|
||||
{
|
||||
IsBusy = _syncService.SyncInProgress;
|
||||
}
|
||||
|
||||
_googleAnalyticsService.TrackPage(GetType().Name);
|
||||
await _lockService.CheckLockAsync(false, true);
|
||||
base.OnAppearing();
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
if(_syncIndicator)
|
||||
{
|
||||
MessagingCenter.Unsubscribe<Application, bool>(Application.Current, "SyncCompleted");
|
||||
MessagingCenter.Unsubscribe<Application>(Application.Current, "SyncStarted");
|
||||
}
|
||||
|
||||
if(_syncIndicator)
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
|
||||
if(_updateActivity)
|
||||
{
|
||||
_lockService.UpdateLastActivity();
|
||||
}
|
||||
|
||||
base.OnDisappearing();
|
||||
_deviceActionService.DismissKeyboard();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedEditor : Editor
|
||||
{
|
||||
public static readonly BindableProperty HasBorderProperty =
|
||||
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEditor), true);
|
||||
|
||||
public bool HasBorder
|
||||
{
|
||||
get { return (bool)GetValue(HasBorderProperty); }
|
||||
set { SetValue(HasBorderProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedEntry : Entry
|
||||
{
|
||||
public ExtendedEntry()
|
||||
{
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
PlaceholderColor = Color.FromHex("c7c7cd");
|
||||
}
|
||||
|
||||
IsPasswordFromToggled = IsPassword;
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HasBorderProperty =
|
||||
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true);
|
||||
|
||||
public static readonly BindableProperty HasOnlyBottomBorderProperty =
|
||||
BindableProperty.Create(nameof(HasOnlyBottomBorder), typeof(bool), typeof(ExtendedEntry), false);
|
||||
|
||||
public static readonly BindableProperty BottomBorderColorProperty =
|
||||
BindableProperty.Create(nameof(BottomBorderColor), typeof(Color), typeof(ExtendedEntry), Color.Default);
|
||||
|
||||
public static readonly BindableProperty TargetMaxLengthProperty =
|
||||
BindableProperty.Create(nameof(TargetMaxLength), typeof(int), typeof(ExtendedEntry), int.MaxValue);
|
||||
|
||||
public bool HasBorder
|
||||
{
|
||||
get { return (bool)GetValue(HasBorderProperty); }
|
||||
set { SetValue(HasBorderProperty, value); }
|
||||
}
|
||||
|
||||
public bool HasOnlyBottomBorder
|
||||
{
|
||||
get { return (bool)GetValue(HasOnlyBottomBorderProperty); }
|
||||
set { SetValue(HasOnlyBottomBorderProperty, value); }
|
||||
}
|
||||
|
||||
public Color BottomBorderColor
|
||||
{
|
||||
get { return (Color)GetValue(BottomBorderColorProperty); }
|
||||
set { SetValue(BottomBorderColorProperty, value); }
|
||||
}
|
||||
|
||||
public int TargetMaxLength
|
||||
{
|
||||
get { return (int)GetValue(TargetMaxLengthProperty); }
|
||||
set { SetValue(TargetMaxLengthProperty, value); }
|
||||
}
|
||||
|
||||
public Enums.ReturnType? TargetReturnType { get; set; }
|
||||
public bool? Autocorrect { get; set; }
|
||||
public bool DisableAutocapitalize { get; set; }
|
||||
public bool AllowClear { get; set; }
|
||||
public bool HideCursor { get; set; }
|
||||
public bool NumbersOnly { get; set; }
|
||||
|
||||
// Need to overwrite default handler because we cant Invoke otherwise
|
||||
public new event EventHandler Completed;
|
||||
|
||||
public void InvokeCompleted()
|
||||
{
|
||||
Completed?.Invoke(this, null);
|
||||
}
|
||||
|
||||
public virtual void InvokeToggleIsPassword()
|
||||
{
|
||||
if(ToggleIsPassword == null)
|
||||
{
|
||||
IsPassword = IsPasswordFromToggled = !IsPassword;
|
||||
Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
ToggleIsPassword.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler ToggleIsPassword;
|
||||
public bool IsPasswordFromToggled { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedListView : ListView
|
||||
{
|
||||
public static readonly BindableProperty BottomPaddingProperty =
|
||||
BindableProperty.Create(nameof(BottomPadding), typeof(int), typeof(ExtendedTableView), 0);
|
||||
|
||||
public ExtendedListView() { }
|
||||
public ExtendedListView(ListViewCachingStrategy cachingStrategy)
|
||||
: base(cachingStrategy) { }
|
||||
|
||||
public int BottomPadding { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedNavigationPage : NavigationPage
|
||||
{
|
||||
public ExtendedNavigationPage()
|
||||
: base()
|
||||
{
|
||||
SetDefaults();
|
||||
}
|
||||
|
||||
public ExtendedNavigationPage(Page root)
|
||||
: base(root)
|
||||
{
|
||||
SetDefaults();
|
||||
}
|
||||
|
||||
private void SetDefaults()
|
||||
{
|
||||
// default colors for our app
|
||||
BarBackgroundColor = Color.FromHex("3c8dbc");
|
||||
BarTextColor = Color.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedPicker : Picker
|
||||
{
|
||||
// TODO: text color
|
||||
|
||||
public static readonly BindableProperty HasBorderProperty =
|
||||
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true);
|
||||
|
||||
public bool HasBorder
|
||||
{
|
||||
get { return (bool)GetValue(HasBorderProperty); }
|
||||
set { SetValue(HasBorderProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedSwitchCell : SwitchCell
|
||||
{
|
||||
public static readonly BindableProperty BackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedSwitchCell), Color.White);
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get { return (Color)GetValue(BackgroundColorProperty); }
|
||||
set { SetValue(BackgroundColorProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedTabbedPage : TabbedPage
|
||||
{
|
||||
public ExtendedTabbedPage()
|
||||
{
|
||||
BackgroundColor = Color.FromHex("efeff4");
|
||||
}
|
||||
|
||||
public static readonly BindableProperty TintColorProperty =
|
||||
BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(ExtendedTabbedPage), Color.White);
|
||||
|
||||
public Color TintColor
|
||||
{
|
||||
get { return (Color)GetValue(TintColorProperty); }
|
||||
set { SetValue(TintColorProperty, value); }
|
||||
}
|
||||
|
||||
public bool NoBorder { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedTableView : TableView
|
||||
{
|
||||
public static readonly BindableProperty EnableScrollingProperty =
|
||||
BindableProperty.Create(nameof(EnableScrolling), typeof(bool), typeof(ExtendedTableView), true);
|
||||
|
||||
public static readonly BindableProperty EnableSelectionProperty =
|
||||
BindableProperty.Create(nameof(EnableSelection), typeof(bool), typeof(ExtendedTableView), true);
|
||||
|
||||
public static readonly BindableProperty SeparatorColorProperty =
|
||||
BindableProperty.Create(nameof(SeparatorColor), typeof(Color), typeof(ExtendedTableView), Color.FromHex("d2d6de"));
|
||||
|
||||
public static readonly BindableProperty BottomPaddingProperty =
|
||||
BindableProperty.Create(nameof(BottomPadding), typeof(int), typeof(ExtendedTableView), 0);
|
||||
|
||||
public bool EnableScrolling
|
||||
{
|
||||
get { return (bool)GetValue(EnableScrollingProperty); }
|
||||
set { SetValue(EnableScrollingProperty, value); }
|
||||
}
|
||||
|
||||
public bool EnableSelection
|
||||
{
|
||||
get { return (bool)GetValue(EnableSelectionProperty); }
|
||||
set { SetValue(EnableSelectionProperty, value); }
|
||||
}
|
||||
|
||||
public Color SeparatorColor
|
||||
{
|
||||
get { return (Color)GetValue(SeparatorColorProperty); }
|
||||
set { SetValue(SeparatorColorProperty, value); }
|
||||
}
|
||||
|
||||
public int EstimatedRowHeight { get; set; }
|
||||
public bool NoHeader { get; set; }
|
||||
public bool NoFooter { get; set; }
|
||||
public int BottomPadding { get; set; }
|
||||
public Func<RedrawableStackLayout> WrappingStackLayout { get; set; }
|
||||
|
||||
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if(!VerticalOptions.Expands && Device.RuntimePlatform != Device.UWP)
|
||||
{
|
||||
var baseOnSizeRequest = GetVisualElementOnSizeRequest();
|
||||
return baseOnSizeRequest(widthConstraint, heightConstraint);
|
||||
}
|
||||
|
||||
return base.OnSizeRequest(widthConstraint, heightConstraint);
|
||||
}
|
||||
|
||||
private Func<double, double, SizeRequest> GetVisualElementOnSizeRequest()
|
||||
{
|
||||
var handle = typeof(VisualElement).GetMethod(
|
||||
"OnSizeRequest",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||
null,
|
||||
new Type[] { typeof(double), typeof(double) },
|
||||
null)?.MethodHandle;
|
||||
|
||||
if(!handle.HasValue)
|
||||
{
|
||||
throw new ArgumentNullException("handle could not be found.");
|
||||
}
|
||||
|
||||
var pointer = handle.Value.GetFunctionPointer();
|
||||
if(pointer == null)
|
||||
{
|
||||
throw new ArgumentNullException("pointer could not be found.");
|
||||
}
|
||||
|
||||
return (Func<double, double, SizeRequest>)Activator.CreateInstance(
|
||||
typeof(Func<double, double, SizeRequest>), this, pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedTextCell : TextCell
|
||||
{
|
||||
public ExtendedTextCell()
|
||||
{
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
TextColor = Color.Black;
|
||||
}
|
||||
|
||||
DetailColor = Color.FromHex("777777");
|
||||
}
|
||||
|
||||
public static readonly BindableProperty BackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedTextCell), Color.White);
|
||||
|
||||
public static readonly BindableProperty ShowDisclousureProperty =
|
||||
BindableProperty.Create(nameof(ShowDisclousure), typeof(bool), typeof(ExtendedTextCell), false);
|
||||
|
||||
public static readonly BindableProperty DisclousureImageProperty =
|
||||
BindableProperty.Create(nameof(DisclousureImage), typeof(string), typeof(ExtendedTextCell), string.Empty);
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get { return (Color)GetValue(BackgroundColorProperty); }
|
||||
set { SetValue(BackgroundColorProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShowDisclousure
|
||||
{
|
||||
get { return (bool)GetValue(ShowDisclousureProperty); }
|
||||
set { SetValue(ShowDisclousureProperty, value); }
|
||||
}
|
||||
|
||||
public string DisclousureImage
|
||||
{
|
||||
get { return (string)GetValue(DisclousureImageProperty); }
|
||||
set { SetValue(DisclousureImageProperty, value); }
|
||||
}
|
||||
|
||||
public LineBreakMode DetailLineBreakMode { get; set; } = LineBreakMode.TailTruncation;
|
||||
|
||||
public event EventHandler DisclousureTapped;
|
||||
|
||||
public void OnDisclousureTapped()
|
||||
{
|
||||
if(DisclousureTapped == null)
|
||||
{
|
||||
OnTapped();
|
||||
return;
|
||||
}
|
||||
|
||||
DisclousureTapped.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedToolbarItem : ToolbarItem, IDisposable
|
||||
{
|
||||
public ExtendedToolbarItem(Action clickAction = null)
|
||||
{
|
||||
ClickAction = clickAction;
|
||||
}
|
||||
|
||||
public Action ClickAction { get; set; }
|
||||
|
||||
protected virtual void ClickedItem(object sender, EventArgs e)
|
||||
{
|
||||
ClickAction?.Invoke();
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
Clicked += ClickedItem;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Clicked -= ClickedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedViewCell : ViewCell
|
||||
{
|
||||
public static readonly BindableProperty BackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedViewCell), Color.White);
|
||||
|
||||
public static readonly BindableProperty ShowDisclousureProperty =
|
||||
BindableProperty.Create(nameof(ShowDisclousure), typeof(bool), typeof(ExtendedViewCell), false);
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get { return (Color)GetValue(BackgroundColorProperty); }
|
||||
set { SetValue(BackgroundColorProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShowDisclousure
|
||||
{
|
||||
get { return (bool)GetValue(ShowDisclousureProperty); }
|
||||
set { SetValue(ShowDisclousureProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Refractored.FabControl;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class Fab : FloatingActionButtonView
|
||||
{
|
||||
public Fab(FabLayout fabLayout, string icon, Action<object, EventArgs> clickedAction)
|
||||
{
|
||||
ImageName = icon;
|
||||
ColorNormal = Color.FromHex("3c8dbc");
|
||||
ColorPressed = Color.FromHex("3883af");
|
||||
ColorRipple = Color.FromHex("3883af");
|
||||
Clicked = clickedAction;
|
||||
|
||||
AbsoluteLayout.SetLayoutFlags(this, AbsoluteLayoutFlags.PositionProportional);
|
||||
AbsoluteLayout.SetLayoutBounds(this, new Rectangle(1, 1, AbsoluteLayout.AutoSize,
|
||||
AbsoluteLayout.AutoSize));
|
||||
|
||||
fabLayout.Children.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class FabLayout : AbsoluteLayout
|
||||
{
|
||||
public FabLayout(View mainView)
|
||||
{
|
||||
VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand;
|
||||
SetLayoutFlags(mainView, AbsoluteLayoutFlags.All);
|
||||
SetLayoutBounds(mainView, new Rectangle(0, 0, 1, 1));
|
||||
Children.Add(mainView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class FormEditorCell : ExtendedViewCell, IDisposable
|
||||
{
|
||||
public FormEditorCell(Keyboard entryKeyboard = null, double? height = null)
|
||||
{
|
||||
Editor = new ExtendedEditor
|
||||
{
|
||||
Keyboard = entryKeyboard,
|
||||
HasBorder = false,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Editor))
|
||||
};
|
||||
|
||||
if(height.HasValue)
|
||||
{
|
||||
Editor.HeightRequest = height.Value;
|
||||
}
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(15, 10)
|
||||
};
|
||||
|
||||
stackLayout.Children.Add(Editor);
|
||||
|
||||
Editor.AdjustMarginsForDevice();
|
||||
stackLayout.AdjustPaddingForDevice();
|
||||
|
||||
View = stackLayout;
|
||||
}
|
||||
|
||||
public ExtendedEditor Editor { get; private set; }
|
||||
|
||||
private void FormEditorCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
Editor.Focus();
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
Tapped += FormEditorCell_Tapped;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Tapped -= FormEditorCell_Tapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using FFImageLoading.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Ioc;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class FormEntryCell : ExtendedViewCell, IDisposable
|
||||
{
|
||||
private VisualElement _nextElement;
|
||||
private TapGestureRecognizer _tgr;
|
||||
private StackLayout _buttonStackLayout = null;
|
||||
|
||||
public FormEntryCell(
|
||||
string labelText,
|
||||
Keyboard entryKeyboard = null,
|
||||
bool isPassword = false,
|
||||
VisualElement nextElement = null,
|
||||
bool useLabelAsPlaceholder = false,
|
||||
string imageSource = null,
|
||||
Thickness? containerPadding = null,
|
||||
string button1 = null,
|
||||
string button2 = null)
|
||||
{
|
||||
if(!useLabelAsPlaceholder)
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
Text = labelText,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand
|
||||
};
|
||||
}
|
||||
|
||||
Entry = new ExtendedEntry
|
||||
{
|
||||
Keyboard = entryKeyboard,
|
||||
HasBorder = false,
|
||||
IsPassword = isPassword,
|
||||
AllowClear = true,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
WidthRequest = 1,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Entry))
|
||||
};
|
||||
|
||||
if(useLabelAsPlaceholder)
|
||||
{
|
||||
Entry.Placeholder = labelText;
|
||||
}
|
||||
|
||||
NextElement = nextElement;
|
||||
|
||||
var imageStackLayout = new StackLayout
|
||||
{
|
||||
Padding = containerPadding ?? new Thickness(15, 10),
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Spacing = 10,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand
|
||||
};
|
||||
|
||||
if(imageSource != null)
|
||||
{
|
||||
_tgr = new TapGestureRecognizer();
|
||||
|
||||
var theImage = new CachedImage
|
||||
{
|
||||
Source = imageSource,
|
||||
HorizontalOptions = LayoutOptions.Start,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
WidthRequest = 18,
|
||||
HeightRequest = 18
|
||||
};
|
||||
theImage.GestureRecognizers.Add(_tgr);
|
||||
|
||||
imageStackLayout.Children.Add(theImage);
|
||||
}
|
||||
|
||||
var formStackLayout = new StackLayout
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand
|
||||
};
|
||||
|
||||
if(!useLabelAsPlaceholder)
|
||||
{
|
||||
formStackLayout.Children.Add(Label);
|
||||
}
|
||||
|
||||
formStackLayout.Children.Add(Entry);
|
||||
imageStackLayout.Children.Add(formStackLayout);
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(button1) || !string.IsNullOrWhiteSpace(button2))
|
||||
{
|
||||
_buttonStackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
Spacing = 5
|
||||
};
|
||||
imageStackLayout.Children.Add(_buttonStackLayout);
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(button1))
|
||||
{
|
||||
Button1 = new ExtendedButton { Image = button1 };
|
||||
_buttonStackLayout.Children.Add(Button1);
|
||||
Button1.Padding = new Thickness(0);
|
||||
Button1.BackgroundColor = Color.Transparent;
|
||||
Button1.WidthRequest = 40;
|
||||
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(button2))
|
||||
{
|
||||
Button2 = new ExtendedButton { Image = button2 };
|
||||
_buttonStackLayout.Children.Add(Button2);
|
||||
Button2.Padding = new Thickness(0);
|
||||
Button2.BackgroundColor = Color.Transparent;
|
||||
Button2.WidthRequest = 40;
|
||||
Button2.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
}
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
var deviceInfo = Resolver.Resolve<IDeviceInfoService>();
|
||||
if(useLabelAsPlaceholder)
|
||||
{
|
||||
if(deviceInfo.Version < 21)
|
||||
{
|
||||
Entry.Margin = new Thickness(-9, 1, -9, 0);
|
||||
}
|
||||
else if(deviceInfo.Version == 21)
|
||||
{
|
||||
Entry.Margin = new Thickness(0, 4, 0, -4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.AdjustMarginsForDevice();
|
||||
}
|
||||
|
||||
if(containerPadding == null)
|
||||
{
|
||||
imageStackLayout.AdjustPaddingForDevice();
|
||||
}
|
||||
}
|
||||
else if(Device.RuntimePlatform == Device.UWP)
|
||||
{
|
||||
if(_buttonStackLayout != null)
|
||||
{
|
||||
_buttonStackLayout.Spacing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
View = imageStackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public ExtendedEntry Entry { get; private set; }
|
||||
public ExtendedButton Button1 { get; private set; }
|
||||
public ExtendedButton Button2 { get; private set; }
|
||||
public VisualElement NextElement
|
||||
{
|
||||
get => _nextElement;
|
||||
set
|
||||
{
|
||||
_nextElement = value;
|
||||
if(_nextElement != null && Entry != null)
|
||||
{
|
||||
Entry.TargetReturnType = Enums.ReturnType.Next;
|
||||
}
|
||||
else if(Entry != null)
|
||||
{
|
||||
Entry.TargetReturnType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Dictionary<string, object> MetaData { get; set; }
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
if(_nextElement != null)
|
||||
{
|
||||
Entry.Completed += Entry_Completed;
|
||||
}
|
||||
|
||||
if(_tgr != null)
|
||||
{
|
||||
_tgr.Tapped += Tgr_Tapped;
|
||||
}
|
||||
|
||||
Tapped += FormEntryCell_Tapped;
|
||||
}
|
||||
|
||||
private void Tgr_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
Entry.Focus();
|
||||
}
|
||||
|
||||
private void FormEntryCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
Entry.Focus();
|
||||
}
|
||||
|
||||
private void Entry_Completed(object sender, EventArgs e)
|
||||
{
|
||||
_nextElement?.Focus();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if(_tgr != null)
|
||||
{
|
||||
_tgr.Tapped -= Tgr_Tapped;
|
||||
}
|
||||
|
||||
Tapped -= FormEntryCell_Tapped;
|
||||
Entry.Completed -= Entry_Completed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class FormPickerCell : ExtendedViewCell
|
||||
{
|
||||
public FormPickerCell(string labelText, string[] pickerItems)
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
Text = labelText,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
TextColor = Color.FromHex("777777")
|
||||
};
|
||||
|
||||
Picker = new ExtendedPicker
|
||||
{
|
||||
HasBorder = false
|
||||
};
|
||||
|
||||
foreach(var item in pickerItems)
|
||||
{
|
||||
Picker.Items.Add(item);
|
||||
}
|
||||
Picker.SelectedIndex = 0;
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(15, 10),
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand
|
||||
};
|
||||
|
||||
stackLayout.Children.Add(Label);
|
||||
stackLayout.Children.Add(Picker);
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
stackLayout.Spacing = 0;
|
||||
}
|
||||
Picker.AdjustMarginsForDevice();
|
||||
stackLayout.AdjustPaddingForDevice();
|
||||
|
||||
View = stackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public ExtendedPicker Picker { get; private set; }
|
||||
|
||||
private void FormPickerCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
Picker.Focus();
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
Tapped += FormPickerCell_Tapped;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Tapped -= FormPickerCell_Tapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class FormSwitchCell : ExtendedViewCell
|
||||
{
|
||||
public FormSwitchCell(string labelText, string button1 = null)
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
Text = labelText,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalTextAlignment = TextAlignment.Center,
|
||||
TextColor = Color.Black,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
|
||||
};
|
||||
Switch = new Switch
|
||||
{
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(15, 5),
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Children = { Label, Switch }
|
||||
};
|
||||
stackLayout.AdjustPaddingForDevice();
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(button1))
|
||||
{
|
||||
Button1 = new ExtendedButton { Image = button1 };
|
||||
stackLayout.Children.Add(Button1);
|
||||
Button1.BackgroundColor = Color.Transparent;
|
||||
Button1.Padding = new Thickness(0);
|
||||
Button1.WidthRequest = 40;
|
||||
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
}
|
||||
|
||||
View = stackLayout;
|
||||
}
|
||||
|
||||
public Switch Switch { get; private set; }
|
||||
public Label Label { get; set; }
|
||||
public ExtendedButton Button1 { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class HybridWebView : View
|
||||
{
|
||||
private Action<string> _func;
|
||||
|
||||
public static readonly BindableProperty UriProperty = BindableProperty.Create(propertyName: nameof(Uri),
|
||||
returnType: typeof(string), declaringType: typeof(HybridWebView), defaultValue: default(string));
|
||||
|
||||
public string Uri
|
||||
{
|
||||
get { return (string)GetValue(UriProperty); }
|
||||
set { SetValue(UriProperty, value); }
|
||||
}
|
||||
|
||||
public void RegisterAction(Action<string> callback)
|
||||
{
|
||||
_func = callback;
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
_func = null;
|
||||
}
|
||||
|
||||
public void InvokeAction(string data)
|
||||
{
|
||||
_func?.Invoke(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using FFImageLoading.Forms;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class LabeledDetailCell : ExtendedViewCell
|
||||
{
|
||||
public LabeledDetailCell()
|
||||
{
|
||||
Icon = new CachedImage
|
||||
{
|
||||
WidthRequest = 20,
|
||||
HeightRequest = 20,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
ErrorPlaceholder = "login.png",
|
||||
CacheDuration = TimeSpan.FromDays(30),
|
||||
BitmapOptimizations = true
|
||||
};
|
||||
|
||||
Label = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
|
||||
};
|
||||
|
||||
Detail = new Label
|
||||
{
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
Style = (Style)Application.Current.Resources["text-muted"]
|
||||
};
|
||||
|
||||
LabelIcon = new CachedImage
|
||||
{
|
||||
WidthRequest = 16,
|
||||
HeightRequest = 16,
|
||||
HorizontalOptions = LayoutOptions.Start,
|
||||
Margin = new Thickness(5, 0, 0, 0)
|
||||
};
|
||||
|
||||
LabelIcon2 = new CachedImage
|
||||
{
|
||||
WidthRequest = 16,
|
||||
HeightRequest = 16,
|
||||
HorizontalOptions = LayoutOptions.Start,
|
||||
Margin = new Thickness(5, 0, 0, 0)
|
||||
};
|
||||
|
||||
Button = new ExtendedButton
|
||||
{
|
||||
WidthRequest = 60
|
||||
};
|
||||
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnSpacing = 0,
|
||||
RowSpacing = 0,
|
||||
Padding = new Thickness(3, 3, 0, 3)
|
||||
};
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(40, GridUnitType.Absolute) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(60, GridUnitType.Absolute) });
|
||||
grid.Children.Add(Icon, 0, 0);
|
||||
grid.Children.Add(Label, 1, 0);
|
||||
grid.Children.Add(Detail, 1, 1);
|
||||
grid.Children.Add(LabelIcon, 2, 0);
|
||||
grid.Children.Add(LabelIcon2, 3, 0);
|
||||
grid.Children.Add(Button, 4, 0);
|
||||
Grid.SetRowSpan(Icon, 2);
|
||||
Grid.SetRowSpan(Button, 2);
|
||||
Grid.SetColumnSpan(Detail, 3);
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Label.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
View = grid;
|
||||
}
|
||||
|
||||
public CachedImage Icon { get; private set; }
|
||||
public Label Label { get; private set; }
|
||||
public Label Detail { get; private set; }
|
||||
public CachedImage LabelIcon { get; private set; }
|
||||
public CachedImage LabelIcon2 { get; private set; }
|
||||
public Button Button { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using FFImageLoading.Forms;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class LabeledRightDetailCell : ExtendedViewCell
|
||||
{
|
||||
public LabeledRightDetailCell(bool showIcon = true)
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
|
||||
HorizontalOptions = LayoutOptions.StartAndExpand,
|
||||
};
|
||||
|
||||
Detail = new Label
|
||||
{
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
StackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Padding = new Thickness(15, 10),
|
||||
Children = { Label, Detail }
|
||||
};
|
||||
|
||||
if(showIcon)
|
||||
{
|
||||
Icon = new CachedImage
|
||||
{
|
||||
WidthRequest = 16,
|
||||
HeightRequest = 16,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Margin = new Thickness(5, 0, 0, 0)
|
||||
};
|
||||
|
||||
StackLayout.Children.Add(Icon);
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Label.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
View = StackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public Label Detail { get; private set; }
|
||||
public CachedImage Icon { get; private set; }
|
||||
public StackLayout StackLayout { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class LabeledValueCell : ExtendedViewCell
|
||||
{
|
||||
public LabeledValueCell(
|
||||
string labelText = null,
|
||||
string valueText = null,
|
||||
string button1Image = null,
|
||||
string button2Image = null,
|
||||
string subText = null)
|
||||
{
|
||||
var containerStackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(15, 10),
|
||||
Orientation = StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
var labelValueStackLayout = new StackLayout
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.StartAndExpand,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand
|
||||
};
|
||||
|
||||
if(labelText != null)
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
Text = labelText,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"]
|
||||
};
|
||||
|
||||
labelValueStackLayout.Children.Add(Label);
|
||||
}
|
||||
|
||||
Value = new Label
|
||||
{
|
||||
Text = valueText,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
|
||||
LineBreakMode = LineBreakMode.TailTruncation
|
||||
};
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Value.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
labelValueStackLayout.Children.Add(Value);
|
||||
|
||||
containerStackLayout.Children.Add(labelValueStackLayout);
|
||||
|
||||
var buttonStackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
Spacing = 5
|
||||
};
|
||||
|
||||
if(subText != null)
|
||||
{
|
||||
Sub = new Label
|
||||
{
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
buttonStackLayout.Children.Add(Sub);
|
||||
}
|
||||
|
||||
if(button1Image != null)
|
||||
{
|
||||
Button1 = new ExtendedButton
|
||||
{
|
||||
Image = button1Image,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
Margin = new Thickness(0),
|
||||
Padding = new Thickness(0),
|
||||
BackgroundColor = Color.Transparent,
|
||||
WidthRequest = 40
|
||||
};
|
||||
|
||||
buttonStackLayout.Children.Add(Button1);
|
||||
}
|
||||
|
||||
if(button2Image != null)
|
||||
{
|
||||
Button2 = new ExtendedButton
|
||||
{
|
||||
Image = button2Image,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
Margin = new Thickness(0),
|
||||
Padding = new Thickness(0),
|
||||
BackgroundColor = Color.Transparent,
|
||||
WidthRequest = 40
|
||||
};
|
||||
|
||||
buttonStackLayout.Children.Add(Button2);
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
containerStackLayout.AdjustPaddingForDevice();
|
||||
}
|
||||
else if(Device.RuntimePlatform == Device.UWP)
|
||||
{
|
||||
buttonStackLayout.Spacing = 0;
|
||||
|
||||
if(Button1 != null)
|
||||
{
|
||||
Button1.BackgroundColor = Color.Transparent;
|
||||
}
|
||||
if(Button2 != null)
|
||||
{
|
||||
Button2.BackgroundColor = Color.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
if(Sub != null && Button1 != null)
|
||||
{
|
||||
Sub.Margin = new Thickness(0, 0, 10, 0);
|
||||
}
|
||||
|
||||
containerStackLayout.Children.Add(buttonStackLayout);
|
||||
View = containerStackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public Label Value { get; private set; }
|
||||
public Label Sub { get; private set; }
|
||||
public ExtendedButton Button1 { get; private set; }
|
||||
public ExtendedButton Button2 { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Bit.App.Utilities;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class PinControl
|
||||
{
|
||||
public EventHandler OnPinEntered;
|
||||
|
||||
public PinControl()
|
||||
{
|
||||
Label = new Label
|
||||
{
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
FontSize = 35,
|
||||
FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier")
|
||||
};
|
||||
|
||||
Entry = new ExtendedEntry
|
||||
{
|
||||
Keyboard = Keyboard.Numeric,
|
||||
TargetMaxLength = 4,
|
||||
HideCursor = true,
|
||||
NumbersOnly = true
|
||||
};
|
||||
|
||||
Entry.BackgroundColor = Entry.TextColor = Color.Transparent;
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Label.TextColor = Color.Black;
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.Margin = new Thickness(0, int.MaxValue, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Label Label { get; set; }
|
||||
public ExtendedEntry Entry { get; set; }
|
||||
|
||||
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if(e.NewTextValue.Length >= 4)
|
||||
{
|
||||
OnPinEntered.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
Entry.TextChanged += Entry_TextChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Entry.TextChanged -= Entry_TextChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class RedrawableStackLayout : StackLayout
|
||||
{
|
||||
private DateTime _lastRedraw = DateTime.MinValue;
|
||||
private TimeSpan _redrawThreshold = TimeSpan.FromMilliseconds(1000);
|
||||
|
||||
public async Task RedrawIfNeededAsync(int delay = 0, bool force = false)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if(Device.RuntimePlatform == Device.iOS && (force || (now - _lastRedraw) > _redrawThreshold))
|
||||
{
|
||||
_lastRedraw = now;
|
||||
if(delay > 0)
|
||||
{
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
|
||||
InvalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Bit.App.Utilities;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class SectionHeaderViewCell : ExtendedViewCell
|
||||
{
|
||||
public SectionHeaderViewCell(string bindingName, string countBindingName = null, Thickness? padding = null)
|
||||
{
|
||||
var label = new Label
|
||||
{
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
VerticalTextAlignment = TextAlignment.Center,
|
||||
HorizontalOptions = LayoutOptions.StartAndExpand
|
||||
};
|
||||
|
||||
label.SetBinding(Label.TextProperty, bindingName);
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Padding = padding ?? new Thickness(16, 8),
|
||||
Children = { label },
|
||||
Orientation = StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(countBindingName))
|
||||
{
|
||||
var countLabel = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.NoWrap,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalTextAlignment = TextAlignment.Center
|
||||
};
|
||||
countLabel.SetBinding(Label.TextProperty, countBindingName);
|
||||
stackLayout.Children.Add(countLabel);
|
||||
}
|
||||
|
||||
View = stackLayout;
|
||||
BackgroundColor = Color.FromHex("efeff4");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using Bit.App.Utilities;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class StepperCell : ExtendedViewCell
|
||||
{
|
||||
private Action _changedAction;
|
||||
|
||||
public StepperCell(string labelText, double value, double min, double max, double increment, Action changed = null)
|
||||
{
|
||||
_changedAction = changed;
|
||||
|
||||
Label = new Label
|
||||
{
|
||||
Text = labelText,
|
||||
HorizontalOptions = LayoutOptions.Start,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
|
||||
};
|
||||
|
||||
StepperValueLabel = new Label
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
HorizontalTextAlignment = TextAlignment.Start,
|
||||
Text = value.ToString(),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
|
||||
};
|
||||
|
||||
Stepper = new Stepper
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
Minimum = min,
|
||||
Maximum = max,
|
||||
Increment = increment,
|
||||
Value = value
|
||||
};
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Children = { Label, StepperValueLabel, Stepper },
|
||||
Spacing = 15,
|
||||
Padding = Helpers.OnPlatform(
|
||||
iOS: new Thickness(15, 8),
|
||||
Android: new Thickness(15, 2),
|
||||
Windows: new Thickness(15, 8))
|
||||
};
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Label.TextColor = Color.Black;
|
||||
}
|
||||
stackLayout.AdjustPaddingForDevice();
|
||||
|
||||
View = stackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public Label StepperValueLabel { get; private set; }
|
||||
public Stepper Stepper { get; private set; }
|
||||
|
||||
private void Stepper_ValueChanged(object sender, ValueChangedEventArgs e)
|
||||
{
|
||||
StepperValueLabel.Text = e.NewValue.ToString();
|
||||
_changedAction?.Invoke();
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
Stepper.ValueChanged += Stepper_ValueChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stepper.ValueChanged -= Stepper_ValueChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Bit.App.Models.Page;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class VaultAttachmentsViewCell : LabeledRightDetailCell
|
||||
{
|
||||
public VaultAttachmentsViewCell()
|
||||
{
|
||||
Label.SetBinding(Label.TextProperty, nameof(VaultAttachmentsPageModel.Attachment.Name));
|
||||
Detail.SetBinding(Label.TextProperty, nameof(VaultAttachmentsPageModel.Attachment.SizeName));
|
||||
Icon.Source = "trash";
|
||||
Detail.MinimumWidthRequest = 100;
|
||||
BackgroundColor = Color.White;
|
||||
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
StackLayout.BackgroundColor = Color.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using Bit.App.Models.Page;
|
||||
using FFImageLoading.Forms;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class VaultGroupingViewCell : ExtendedViewCell
|
||||
{
|
||||
public VaultGroupingViewCell()
|
||||
{
|
||||
Icon = new CachedImage
|
||||
{
|
||||
WidthRequest = 20,
|
||||
HeightRequest = 20,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Source = "folder.png",
|
||||
Margin = new Thickness(0, 0, 10, 0)
|
||||
};
|
||||
|
||||
Label = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
|
||||
HorizontalOptions = LayoutOptions.StartAndExpand
|
||||
};
|
||||
Label.SetBinding(Label.TextProperty, string.Format("{0}.Node.{1}",
|
||||
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.Name)));
|
||||
|
||||
CountLabel = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.NoWrap,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
HorizontalOptions = LayoutOptions.End
|
||||
};
|
||||
CountLabel.SetBinding(Label.TextProperty, string.Format("{0}.Node.{1}",
|
||||
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.Count)));
|
||||
CountLabel.SetBinding(VisualElement.IsVisibleProperty, string.Format("{0}.Node.{1}",
|
||||
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.ShowCount)));
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Spacing = 0,
|
||||
Padding = new Thickness(16, 10),
|
||||
Children = { Icon, Label, CountLabel },
|
||||
Orientation = StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
Label.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
View = stackLayout;
|
||||
BackgroundColor = Color.White;
|
||||
}
|
||||
|
||||
public CachedImage Icon { get; private set; }
|
||||
public Label Label { get; private set; }
|
||||
public Label CountLabel { get; private set; }
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
if(BindingContext is VaultListPageModel.GroupingOrCipher model)
|
||||
{
|
||||
Icon.Source = model.Grouping.Node.Folder ?
|
||||
$"folder{(model.Grouping.Node.Id == null ? "_o" : string.Empty)}.png" : "cube.png";
|
||||
}
|
||||
|
||||
base.OnBindingContextChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using Bit.App.Models.Page;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class VaultListViewCell : LabeledDetailCell
|
||||
{
|
||||
public static readonly BindableProperty CipherParameterProperty = BindableProperty.Create(nameof(CipherParameter),
|
||||
typeof(VaultListPageModel.Cipher), typeof(VaultListViewCell), null);
|
||||
public static readonly BindableProperty GroupingOrCipherParameterProperty =
|
||||
BindableProperty.Create(nameof(GroupingOrCipherParameter), typeof(VaultListPageModel.GroupingOrCipher),
|
||||
typeof(VaultListViewCell), null);
|
||||
|
||||
public VaultListViewCell(Action<VaultListPageModel.Cipher> moreClickedAction, bool groupingOrCipherBinding = false)
|
||||
{
|
||||
string bindingPrefix = null;
|
||||
if(groupingOrCipherBinding)
|
||||
{
|
||||
SetBinding(GroupingOrCipherParameterProperty, new Binding("."));
|
||||
bindingPrefix = string.Concat(nameof(VaultListPageModel.GroupingOrCipher.Cipher), ".");
|
||||
Button.Command = new Command(() => moreClickedAction?.Invoke(GroupingOrCipherParameter?.Cipher));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBinding(CipherParameterProperty, new Binding("."));
|
||||
Button.Command = new Command(() => moreClickedAction?.Invoke(CipherParameter));
|
||||
}
|
||||
|
||||
Label.SetBinding(Label.TextProperty, bindingPrefix + nameof(VaultListPageModel.Cipher.Name));
|
||||
Detail.SetBinding(Label.TextProperty, bindingPrefix + nameof(VaultListPageModel.Cipher.Subtitle));
|
||||
LabelIcon.SetBinding(VisualElement.IsVisibleProperty,
|
||||
bindingPrefix + nameof(VaultListPageModel.Cipher.Shared));
|
||||
LabelIcon2.SetBinding(VisualElement.IsVisibleProperty,
|
||||
bindingPrefix + nameof(VaultListPageModel.Cipher.HasAttachments));
|
||||
|
||||
Button.Image = "more.png";
|
||||
Button.BackgroundColor = Color.Transparent;
|
||||
|
||||
LabelIcon.Source = "share.png";
|
||||
LabelIcon2.Source = "paperclip.png";
|
||||
|
||||
BackgroundColor = Color.White;
|
||||
}
|
||||
|
||||
public VaultListPageModel.Cipher CipherParameter
|
||||
{
|
||||
get { return GetValue(CipherParameterProperty) as VaultListPageModel.Cipher; }
|
||||
set { SetValue(CipherParameterProperty, value); }
|
||||
}
|
||||
|
||||
public VaultListPageModel.GroupingOrCipher GroupingOrCipherParameter
|
||||
{
|
||||
get { return GetValue(GroupingOrCipherParameterProperty) as VaultListPageModel.GroupingOrCipher; }
|
||||
set { SetValue(GroupingOrCipherParameterProperty, value); }
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
Icon.Source = null;
|
||||
|
||||
VaultListPageModel.Cipher cipher = null;
|
||||
if(BindingContext is VaultListPageModel.Cipher item)
|
||||
{
|
||||
cipher = item;
|
||||
}
|
||||
else if(BindingContext is VaultListPageModel.GroupingOrCipher groupingOrCipherItem)
|
||||
{
|
||||
cipher = groupingOrCipherItem.Cipher;
|
||||
}
|
||||
|
||||
if(cipher != null)
|
||||
{
|
||||
if(cipher.Type == Enums.CipherType.Login)
|
||||
{
|
||||
Icon.LoadingPlaceholder = "login.png";
|
||||
}
|
||||
Icon.Source = cipher.Icon;
|
||||
}
|
||||
|
||||
base.OnBindingContextChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum CipherType : short
|
||||
{
|
||||
// Folder deprecated
|
||||
//Folder = 0,
|
||||
Login = 1,
|
||||
SecureNote = 2,
|
||||
Card = 3,
|
||||
Identity = 4
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum DeviceType
|
||||
{
|
||||
Android = 0,
|
||||
iOS = 1,
|
||||
UWP = 16
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum EncryptionType : byte
|
||||
{
|
||||
AesCbc256_B64 = 0,
|
||||
AesCbc128_HmacSha256_B64 = 1,
|
||||
AesCbc256_HmacSha256_B64 = 2,
|
||||
Rsa2048_OaepSha256_B64 = 3,
|
||||
Rsa2048_OaepSha1_B64 = 4,
|
||||
Rsa2048_OaepSha256_HmacSha256_B64 = 5,
|
||||
Rsa2048_OaepSha1_HmacSha256_B64 = 6
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum FieldType : byte
|
||||
{
|
||||
Text = 0,
|
||||
Hidden = 1,
|
||||
Boolean = 2
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum KdfType : short
|
||||
{
|
||||
PBKDF2_SHA256 = 0
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum LockType : short
|
||||
{
|
||||
None = 0,
|
||||
Fingerprint = 1,
|
||||
PIN = 2,
|
||||
Password = 3
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum OrganizationUserStatusType : byte
|
||||
{
|
||||
Invited = 0,
|
||||
Accepted = 1,
|
||||
Confirmed = 2
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum OrganizationUserType : byte
|
||||
{
|
||||
Owner = 0,
|
||||
Admin = 1,
|
||||
User = 2
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum PushType : short
|
||||
{
|
||||
SyncCipherUpdate = 0,
|
||||
SyncCipherCreate = 1,
|
||||
SyncLoginDelete = 2,
|
||||
SyncFolderDelete = 3,
|
||||
SyncCiphers = 4,
|
||||
|
||||
SyncVault = 5,
|
||||
SyncOrgKeys = 6,
|
||||
SyncFolderCreate = 7,
|
||||
SyncFolderUpdate = 8,
|
||||
SyncCipherDelete = 9,
|
||||
SyncSettings = 10,
|
||||
|
||||
LogOut = 11,
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum ReturnType
|
||||
{
|
||||
Done,
|
||||
Go,
|
||||
Next,
|
||||
Search,
|
||||
Send
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum SecureNoteType : byte
|
||||
{
|
||||
Generic = 0
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum TwoFactorProviderType : byte
|
||||
{
|
||||
Authenticator = 0,
|
||||
Email = 1,
|
||||
Duo = 2,
|
||||
YubiKey = 3,
|
||||
U2f = 4,
|
||||
Remember = 5,
|
||||
OrganizationDuo = 6
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum UriMatchType : byte
|
||||
{
|
||||
Domain = 0,
|
||||
Host = 1,
|
||||
StartsWith = 2,
|
||||
Exact = 3,
|
||||
RegularExpression = 4,
|
||||
Never = 5
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Net;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class ApiError
|
||||
{
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class ApiResult<T>
|
||||
{
|
||||
private List<ApiError> m_errors = new List<ApiError>();
|
||||
|
||||
public bool Succeeded { get; private set; }
|
||||
public T Result { get; set; }
|
||||
public IEnumerable<ApiError> Errors => m_errors;
|
||||
public HttpStatusCode StatusCode { get; private set; }
|
||||
|
||||
public static ApiResult<T> Success(T result, HttpStatusCode statusCode)
|
||||
{
|
||||
return new ApiResult<T>
|
||||
{
|
||||
Succeeded = true,
|
||||
Result = result,
|
||||
StatusCode = statusCode
|
||||
};
|
||||
}
|
||||
|
||||
public static ApiResult<T> Failed(HttpStatusCode statusCode, params ApiError[] errors)
|
||||
{
|
||||
var result = new ApiResult<T>
|
||||
{
|
||||
Succeeded = false,
|
||||
StatusCode = statusCode
|
||||
};
|
||||
|
||||
if(errors != null)
|
||||
{
|
||||
result.m_errors.AddRange(errors);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class ApiResult
|
||||
{
|
||||
private List<ApiError> m_errors = new List<ApiError>();
|
||||
|
||||
public bool Succeeded { get; private set; }
|
||||
public IEnumerable<ApiError> Errors => m_errors;
|
||||
public HttpStatusCode StatusCode { get; private set; }
|
||||
|
||||
public static ApiResult Success(HttpStatusCode statusCode)
|
||||
{
|
||||
return new ApiResult
|
||||
{
|
||||
Succeeded = true,
|
||||
StatusCode = statusCode
|
||||
};
|
||||
}
|
||||
|
||||
public static ApiResult Failed(HttpStatusCode statusCode, params ApiError[] errors)
|
||||
{
|
||||
var result = new ApiResult
|
||||
{
|
||||
Succeeded = false,
|
||||
StatusCode = statusCode
|
||||
};
|
||||
|
||||
if(errors != null)
|
||||
{
|
||||
result.m_errors.AddRange(errors);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class CardType
|
||||
{
|
||||
public CardType() { }
|
||||
|
||||
public CardType(Cipher cipher)
|
||||
{
|
||||
CardholderName = cipher.Card.CardholderName?.EncryptedString;
|
||||
Brand = cipher.Card.Brand?.EncryptedString;
|
||||
Number = cipher.Card.Number?.EncryptedString;
|
||||
ExpMonth = cipher.Card.ExpMonth?.EncryptedString;
|
||||
ExpYear = cipher.Card.ExpYear?.EncryptedString;
|
||||
Code = cipher.Card.Code?.EncryptedString;
|
||||
}
|
||||
|
||||
public string CardholderName { get; set; }
|
||||
public string Brand { get; set; }
|
||||
public string Number { get; set; }
|
||||
public string ExpMonth { get; set; }
|
||||
public string ExpYear { get; set; }
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class FieldType
|
||||
{
|
||||
public FieldType() { }
|
||||
|
||||
public FieldType(Field field)
|
||||
{
|
||||
Type = field.Type;
|
||||
Name = field.Name?.EncryptedString;
|
||||
Value = field.Value?.EncryptedString;
|
||||
}
|
||||
|
||||
public Enums.FieldType Type { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class IdentityType
|
||||
{
|
||||
public IdentityType() { }
|
||||
|
||||
public IdentityType(Cipher cipher)
|
||||
{
|
||||
Title = cipher.Identity.Title?.EncryptedString;
|
||||
FirstName = cipher.Identity.FirstName?.EncryptedString;
|
||||
MiddleName = cipher.Identity.MiddleName?.EncryptedString;
|
||||
LastName = cipher.Identity.LastName?.EncryptedString;
|
||||
Address1 = cipher.Identity.Address1?.EncryptedString;
|
||||
Address2 = cipher.Identity.Address2?.EncryptedString;
|
||||
Address3 = cipher.Identity.Address3?.EncryptedString;
|
||||
City = cipher.Identity.City?.EncryptedString;
|
||||
State = cipher.Identity.State?.EncryptedString;
|
||||
PostalCode = cipher.Identity.PostalCode?.EncryptedString;
|
||||
Country = cipher.Identity.Country?.EncryptedString;
|
||||
Company = cipher.Identity.Company?.EncryptedString;
|
||||
Email = cipher.Identity.Email?.EncryptedString;
|
||||
Phone = cipher.Identity.Phone?.EncryptedString;
|
||||
SSN = cipher.Identity.SSN?.EncryptedString;
|
||||
Username = cipher.Identity.Username?.EncryptedString;
|
||||
PassportNumber = cipher.Identity.PassportNumber?.EncryptedString;
|
||||
LicenseNumber = cipher.Identity.LicenseNumber?.EncryptedString;
|
||||
}
|
||||
|
||||
public string Title { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string MiddleName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Address1 { get; set; }
|
||||
public string Address2 { get; set; }
|
||||
public string Address3 { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string Company { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string SSN { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string PassportNumber { get; set; }
|
||||
public string LicenseNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class LoginType
|
||||
{
|
||||
public LoginType() { }
|
||||
|
||||
public LoginType(Cipher cipher)
|
||||
{
|
||||
Uris = cipher.Login.Uris?.Select(u => new LoginUriType(u));
|
||||
Username = cipher.Login.Username?.EncryptedString;
|
||||
Password = cipher.Login.Password?.EncryptedString;
|
||||
PasswordRevisionDate = cipher.Login.PasswordRevisionDate;
|
||||
Totp = cipher.Login.Totp?.EncryptedString;
|
||||
}
|
||||
|
||||
public IEnumerable<LoginUriType> Uris { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public System.DateTime? PasswordRevisionDate { get; set; }
|
||||
public string Totp { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class LoginUriType
|
||||
{
|
||||
public LoginUriType() { }
|
||||
|
||||
public LoginUriType(LoginUri u)
|
||||
{
|
||||
Uri = u.Uri?.EncryptedString;
|
||||
Match = u.Match;
|
||||
}
|
||||
|
||||
public string Uri { get; set; }
|
||||
public UriMatchType? Match { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class CipherRequest
|
||||
{
|
||||
public CipherRequest(Cipher cipher)
|
||||
{
|
||||
Type = cipher.Type;
|
||||
OrganizationId = cipher.OrganizationId;
|
||||
FolderId = cipher.FolderId;
|
||||
Name = cipher.Name?.EncryptedString;
|
||||
Notes = cipher.Notes?.EncryptedString;
|
||||
Favorite = cipher.Favorite;
|
||||
|
||||
if(cipher.Fields != null)
|
||||
{
|
||||
Fields = cipher.Fields.Select(f => new FieldType(f));
|
||||
}
|
||||
|
||||
if(cipher.PasswordHistory != null)
|
||||
{
|
||||
PasswordHistory = cipher.PasswordHistory.Select(h => new PasswordHistoryRequest(h));
|
||||
}
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
Login = new LoginType(cipher);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
Card = new CardType(cipher);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
Identity = new IdentityType(cipher);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
SecureNote = new SecureNoteType(cipher);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public CipherType Type { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public IEnumerable<FieldType> Fields { get; set; }
|
||||
public IEnumerable<PasswordHistoryRequest> PasswordHistory { get; set; }
|
||||
|
||||
public LoginType Login { get; set; }
|
||||
public CardType Card { get; set; }
|
||||
public IdentityType Identity { get; set; }
|
||||
public SecureNoteType SecureNote { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Enums;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class DeviceRequest
|
||||
{
|
||||
public DeviceRequest() { }
|
||||
|
||||
public DeviceRequest(IAppIdService appIdService, IDeviceInfoService deviceInfoService)
|
||||
{
|
||||
Identifier = appIdService.AppId;
|
||||
Name = deviceInfoService.Model;
|
||||
Type = Device.RuntimePlatform == Device.Android ? DeviceType.Android : DeviceType.iOS;
|
||||
}
|
||||
|
||||
public DeviceType Type { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Identifier { get; set; }
|
||||
public string PushToken { get; set; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user