using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Polly;
using SQLite;
using Xamarin.Essentials;
namespace SpecialForcesDirectory.Code
{
public abstract class BaseContentDatabase
{
public static readonly string DatabasePath = Path.Combine(FileSystem.AppDataDirectory, Settings.DataBaseName);
static readonly Lazy<SQLiteAsyncConnection> DatabaseConnectionHolder = new Lazy<SQLiteAsyncConnection>(() => new SQLiteAsyncConnection(DatabasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache));
private static SQLiteAsyncConnection DatabaseConnection => DatabaseConnectionHolder.Value;
protected static async ValueTask<SQLiteAsyncConnection> GetDatabaseConnection<T>()
{
if (DatabaseConnection.TableMappings.Any(x => x.MappedType == typeof(T))) return DatabaseConnection;
// On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution
await DatabaseConnection.EnableWriteAheadLoggingAsync().ConfigureAwait(false);
await DatabaseConnection.CreateTablesAsync(CreateFlags.None, typeof(T)).ConfigureAwait(false);
return DatabaseConnection;
}
public static Task<T> AttemptAndRetry<T>(Func<Task<T>> action, int numRetries = 10)
{
return Policy.Handle<SQLiteException>().WaitAndRetryAsync(numRetries, PollyRetryAttempt).ExecuteAsync(action);
static TimeSpan PollyRetryAttempt(int attemptNumber) => TimeSpan.FromMilliseconds(Math.Pow(2, attemptNumber));
}
protected static async Task Close()
{
await DatabaseConnection.CloseAsync();
}
}
public class ContentDatabase : BaseContentDatabase
{
#region Category repository
private async Task<SQLiteAsyncConnection> GetCategoryConn()
{
return await GetDatabaseConnection<Category>().ConfigureAwait(false);
}
public async Task<IEnumerable<Category>> GetCategories()
{
var conn = await GetCategoryConn();
return await AttemptAndRetry(() => conn.Table<Category>().ToListAsync()).ConfigureAwait(false);
}
public async Task<Category> GetCategory(int id)
{
var conn = await GetCategoryConn();
return await AttemptAndRetry(() => conn.GetAsync<Category>(id)).ConfigureAwait(false);
}
#endregion
#region Content Repository
private async Task<SQLiteAsyncConnection> GetCtxConn()
{
return await GetDatabaseConnection<Content>().ConfigureAwait(false);
}
public async Task<IEnumerable<Content>> GetItems()
{
var conn = await GetCtxConn();
return await AttemptAndRetry(() => conn.Table<Content>().ToListAsync()).ConfigureAwait(false);
}
public async Task<Content> GetItem(int id)
{
var conn = await GetCtxConn();
return await AttemptAndRetry(() => conn.GetAsync<Content>(id)).ConfigureAwait(false);
}
public async Task<int> DeleteItem(int id)
{
var conn = await GetCtxConn();
return await AttemptAndRetry(() => conn.DeleteAsync<Content>(id)).ConfigureAwait(false);
}
public async Task SaveItem(Content item)
{
var conn = await GetCtxConn();
if (item.Id == 0) await AttemptAndRetry(() => conn.InsertAsync(item)).ConfigureAwait(false);
await AttemptAndRetry(() => conn.UpdateAsync(item)).ConfigureAwait(false);
}
public async Task<IEnumerable<SRawItem>> GetItemsByQuery(string q, int lim)
{
var qu = q.ToUpper();
var list = new List<SRawItem>();
var conn = await GetCtxConn();
var result = conn.Table<Content>()
.Where(x => x.EnableTab1 == 1 && x.Tab1.ToUpper().Contains(qu)
|| x.EnableTab2 == 1 && x.Tab2.ToUpper().Contains(qu)
|| x.EnableTab3 == 1 && x.Tab3.ToUpper().Contains(qu)).Take(lim);
var r = await result.ToListAsync();
foreach (var content in r)
{
var st = GetSt(content, qu);
var title = await conn.Table<Category>().Where(x => x.Id == content.CatId).FirstAsync();
var ni = new SRawItem
{
Body = st.Body,
CatId = content.CatId.ToString(),
Title = title.Title,
Id = content.Id.ToString(),
MType = "a",
Tab = st.Tab
};
list.Add(ni);
}
return list;
}
private static TabStruct GetSt(Content content, string q)
{
if (content.Tab1.ToUpper().Contains(q))
return new TabStruct { Tab = "1", Body = content.Tab1 };
if (content.Tab2.ToUpper().Contains(q))
return new TabStruct { Tab = "2", Body = content.Tab2 };
return new TabStruct { Tab = "3", Body = content.Tab3 };
}
private struct TabStruct
{
public string Body { get; set; }
public string Tab { get; set; }
}
#endregion
public async Task Clear()
{
await BaseContentDatabase.Close();
}
}
[Table("quote")]
public class Quote
{
[PrimaryKey]
[AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("author")] public string Author { get; set; }
[Column("body")] public string Body { get; set; }
[Column("image")] public string Image { get; set; }
[Column("created")] public DateTime Created { get; set; }
}
public class QuoteRepository : BaseUserDatabase
{
private async Task<SQLiteAsyncConnection> GetConn()
{
return await GetDatabaseConnection<Quote>().ConfigureAwait(false);
}
public async Task<IEnumerable<Quote>> GetItems()
{
var conn = await GetConn();
return await AttemptAndRetry(() => conn.Table<Quote>().ToListAsync()).ConfigureAwait(false);
}
public async Task<Quote> GetItem(int id)
{
var conn = await GetConn();
return await AttemptAndRetry(() => conn.GetAsync<Quote>(id)).ConfigureAwait(false);
}
public async Task<int> DeleteItem(int id)
{
var conn = await GetConn();
return await AttemptAndRetry(() => conn.DeleteAsync<Quote>(id)).ConfigureAwait(false);
}
public async Task<int> SaveItem(Quote item)
{
var conn = await GetConn();
return await AttemptAndRetry(() => conn.InsertOrReplaceAsync(item)).ConfigureAwait(false);
}
public async Task DeleteAll()
{
var conn = await GetConn();
await AttemptAndRetry(() => conn.DeleteAllAsync<Quote>()).ConfigureAwait(false);
}
}
}
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public static string DbPath => DependencyService.Get<ISqLite>().GetDatabasePath("user.db");
#region License
// Разработано: Коротенко Владимиром Николаевичем (Vladimir N. Korotenko)
// email: koroten@ya.ru
// skype:vladimir-korotenko
// https://vkorotenko.ru
// Создано: 09.04.2019 22:38
#endregion
using System;
using System.IO;
using SpecialForcesDirectory.Code;
using SpecialForcesDirectory.Droid;
using Xamarin.Forms;
[assembly: Dependency(typeof(SQLite_Android))]
namespace SpecialForcesDirectory.Droid
{
public class SQLite_Android : ISqLite
{
public SQLite_Android() { }
public string GetDatabasePath(string sqliteFilename)
{
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = Path.Combine(documentsPath, sqliteFilename);
return path;
}
}
}
public async Task<PageItem> GetContent(string cat, bool offline)
{
try
{
if (offline)
{
var catId = int.Parse(cat);
var ctx = DataContext.Instance;
var data = (await ctx.Content.GetItems())
.First(x => x.CatId == catId);
var result = _mapper.Map<PageItem>(data);
result.Tab1 = ReplaceImages(result.Tab1);
result.Tab2 = ReplaceImages(result.Tab2);
result.Tab3 = ReplaceImages(result.Tab3);
result.FavUrl = $"{cat}";
return result;
}
else
{
//return $"{BaseUrl}content.php?cat={cat}&tab={tab}";
var da = new LoadDataAdapter();
var json = await da.GetJson(Settings.GetContent(cat));
var data = JsonConvert.DeserializeObject<PageItem>(json, new JsonBooleanConverter());
data.FavUrl = cat;
return data;
}
}
catch (Exception ex)
{
throw new ArgumentNullException("Ошибка загрузки.", ex);
}
}
private class Model : BaseViewModel
{
private const double KlConst = 273.15;
private const double InitialKelvin = KlConst + 20;
public Model()
{
Title = Resource.ConverterTemperatureTitle;
ActiveButton = nameof(KValue);
KValue = InitialKelvin;
}
#region Props
private double K2C() => KValue - KlConst;
private double C2K() => CValue + KlConst;
private double K2F() => (KValue - KlConst) * (9D / 5) + 32;
private double F2K() => (FValue - 32) * 5d / 9 + KlConst;
private double K2Re() => (4d / 5) * (KValue - KlConst);
private double Re2K() => (5d / 4) * ReValue + KlConst;
private void Calculate()
{
if (ActiveButton != nameof(CValue)) CValue = K2C();
if (ActiveButton != nameof(FValue)) FValue = K2F();
if (ActiveButton != nameof(ReValue)) ReValue = K2Re();
}
#region CValue
private double _cValue;
public double CValue
{
get => _cValue;
set
{
SetProperty(ref _cValue, value);
if (ActiveButton != nameof(CValue)) return;
KValue = C2K();
Calculate();
}
}
#endregion
#region FValue
private double _fValue;
public double FValue
{
get => _fValue;
set
{
SetProperty(ref _fValue, value);
if (ActiveButton != nameof(FValue)) return;
KValue = F2K();
Calculate();
}
}
#endregion
#region ReValue
private double _reValue;
public double ReValue
{
get => _reValue;
set
{
SetProperty(ref _reValue, value);
if (ActiveButton != nameof(ReValue)) return;
KValue = Re2K();
Calculate();
}
}
#endregion
#region KValue
private double _kValue;
public double KValue
{
get => _kValue;
set
{
SetProperty(ref _kValue, value);
if (ActiveButton != nameof(KValue)) return;
Calculate();
}
}
#endregion
#endregion
#region ActiveButton
private string _activeButton = "";
public string ActiveButton
{
get => _activeButton;
set => SetProperty(ref _activeButton, value);
}
#endregion
}