diff --git a/Storage/Storage.Standard/LCApplication.cs b/Storage/Storage.Standard/LCApplication.cs
new file mode 100644
index 0000000..714e264
--- /dev/null
+++ b/Storage/Storage.Standard/LCApplication.cs
@@ -0,0 +1,16 @@
+using LeanCloud.Storage.Internal.Storage;
+
+namespace LeanCloud {
+ public class LCApplication {
+ public static void Initialize(string appId,
+ string appKey,
+ string server = null,
+ string masterKey = null) {
+ LCLogger.Debug("Application Initializes on Standard.");
+
+ LCInternalApplication.Initialize(appId, appKey, server, masterKey);
+
+ LCInternalApplication.StorageController = new StorageController(null);
+ }
+ }
+}
diff --git a/Storage/Storage.Standard/StandardStorage.cs b/Storage/Storage.Standard/StandardStorage.cs
new file mode 100644
index 0000000..4941ea9
--- /dev/null
+++ b/Storage/Storage.Standard/StandardStorage.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace LeanCloud.Storage.Internal.Storage {
+ public class StandardStorage : IStorage {
+ public string GetStoragePath() {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Storage/Storage.Standard/Storage.Standard.csproj b/Storage/Storage.Standard/Storage.Standard.csproj
new file mode 100644
index 0000000..5b6caa2
--- /dev/null
+++ b/Storage/Storage.Standard/Storage.Standard.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+ 0.7.2
+ Storage.Standard
+ true
+
+
+
+
+
+
+
diff --git a/Storage/Storage.Unity/LCApplication.cs b/Storage/Storage.Unity/LCApplication.cs
new file mode 100644
index 0000000..ae6aff7
--- /dev/null
+++ b/Storage/Storage.Unity/LCApplication.cs
@@ -0,0 +1,16 @@
+using LeanCloud.Storage.Internal.Storage;
+
+namespace LeanCloud {
+ public class LCApplication {
+ public static void Initialize(string appId,
+ string appKey,
+ string server = null,
+ string masterKey = null) {
+ LCLogger.Debug("Application Initializes on Unity.");
+
+ LCInternalApplication.Initialize(appId, appKey, server, masterKey);
+
+ LCInternalApplication.StorageController = new StorageController(new UnityStorage());
+ }
+ }
+}
diff --git a/Storage/Storage.Unity/Storage.Unity.csproj b/Storage/Storage.Unity/Storage.Unity.csproj
new file mode 100644
index 0000000..c0699e9
--- /dev/null
+++ b/Storage/Storage.Unity/Storage.Unity.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netstandard2.0
+ 0.7.2
+ Storage.Unity
+ true
+
+
+
+
+
+
+
+ ..\..\Unity\UnityEngine.dll
+
+
+
diff --git a/Storage/Storage.Unity/UnityStorage.cs b/Storage/Storage.Unity/UnityStorage.cs
new file mode 100644
index 0000000..039b744
--- /dev/null
+++ b/Storage/Storage.Unity/UnityStorage.cs
@@ -0,0 +1,9 @@
+using UnityEngine;
+
+namespace LeanCloud.Storage.Internal.Storage {
+ public class UnityStorage : IStorage {
+ public string GetStoragePath() {
+ return Application.persistentDataPath;
+ }
+ }
+}
diff --git a/Storage/Storage/Internal/Http/LCHttpClient.cs b/Storage/Storage/Internal/Http/LCHttpClient.cs
index 4fd4a2e..7a4b0e9 100644
--- a/Storage/Storage/Internal/Http/LCHttpClient.cs
+++ b/Storage/Storage/Internal/Http/LCHttpClient.cs
@@ -120,7 +120,7 @@ namespace LeanCloud.Storage.Internal.Http {
}
async Task BuildUrl(string path, Dictionary queryParams = null) {
- string apiServer = await LCApplication.AppRouter.GetApiServer();
+ string apiServer = await LCInternalApplication.AppRouter.GetApiServer();
string url = $"{apiServer}/{apiVersion}/{path}";
if (queryParams != null) {
IEnumerable queryPairs = queryParams.Select(kv => $"{kv.Key}={kv.Value}");
@@ -137,9 +137,9 @@ namespace LeanCloud.Storage.Internal.Http {
headers.Add(kv.Key, kv.Value.ToString());
}
}
- if (LCApplication.UseMasterKey && !string.IsNullOrEmpty(LCApplication.MasterKey)) {
+ if (LCInternalApplication.UseMasterKey && !string.IsNullOrEmpty(LCInternalApplication.MasterKey)) {
// Master Key
- headers.Add("X-LC-Key", $"{LCApplication.MasterKey},master");
+ headers.Add("X-LC-Key", $"{LCInternalApplication.MasterKey},master");
} else {
// 签名
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@@ -148,8 +148,8 @@ namespace LeanCloud.Storage.Internal.Http {
string sign = $"{hash},{timestamp}";
headers.Add("X-LC-Sign", sign);
}
- if (LCApplication.AdditionalHeaders.Count > 0) {
- foreach (KeyValuePair kv in LCApplication.AdditionalHeaders) {
+ if (LCInternalApplication.AdditionalHeaders.Count > 0) {
+ foreach (KeyValuePair kv in LCInternalApplication.AdditionalHeaders) {
headers.Add(kv.Key, kv.Value);
}
}
diff --git a/Storage/Storage/Internal/Storage/IStorage.cs b/Storage/Storage/Internal/Storage/IStorage.cs
new file mode 100644
index 0000000..4f0cf1e
--- /dev/null
+++ b/Storage/Storage/Internal/Storage/IStorage.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace LeanCloud.Storage.Internal.Storage {
+ public interface IStorage {
+ string GetStoragePath();
+ }
+}
diff --git a/Storage/Storage/Internal/Storage/StorageController.cs b/Storage/Storage/Internal/Storage/StorageController.cs
new file mode 100644
index 0000000..3a79c50
--- /dev/null
+++ b/Storage/Storage/Internal/Storage/StorageController.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Reflection;
+using System.Linq;
+using System.Threading.Tasks;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+
+using IOFile = System.IO.File;
+
+namespace LeanCloud.Storage.Internal.Storage {
+ public class StorageController {
+ private readonly IStorage storage;
+
+ public StorageController(IStorage storage) {
+ this.storage = storage;
+ }
+
+ public async Task WriteText(string filename, string text) {
+ if (storage == null) {
+ return;
+ }
+
+ string path = GetFileFullPath(filename);
+ LCLogger.Debug($"WRITE: {path}");
+ LCLogger.Debug($"WRITE: {text}");
+ using (FileStream fs = IOFile.OpenWrite(path)) {
+ byte[] buffer = Encoding.UTF8.GetBytes(text);
+ await fs.WriteAsync(buffer, 0, buffer.Length);
+ }
+ }
+
+ public async Task ReadText(string filename) {
+ if (storage == null) {
+ return null;
+ }
+
+ string path = GetFileFullPath(filename);
+ LCLogger.Debug($"READ: {path}");
+ if (IOFile.Exists(path)) {
+ string text;
+ using (FileStream fs = IOFile.OpenRead(path)) {
+ byte[] buffer = new byte[fs.Length];
+ await fs.ReadAsync(buffer, 0, (int)fs.Length);
+ text = Encoding.UTF8.GetString(buffer);
+ }
+ LCLogger.Debug($"READ: {text}");
+ return text;
+ }
+ return null;
+ }
+
+ public void Delete(string filename) {
+ if (storage == null) {
+ return;
+ }
+
+ string path = GetFileFullPath(filename);
+ IOFile.Delete(path);
+ }
+
+ private string GetFileFullPath(string filename) {
+ if (storage == null) {
+ throw new Exception("no IStrorage.");
+ }
+ return Path.Combine(storage.GetStoragePath(), filename);
+ }
+ }
+}
diff --git a/Storage/Storage/LCCaptchaClient.cs b/Storage/Storage/LCCaptchaClient.cs
index f18d040..386e645 100644
--- a/Storage/Storage/LCCaptchaClient.cs
+++ b/Storage/Storage/LCCaptchaClient.cs
@@ -33,7 +33,7 @@ namespace LeanCloud.Storage {
{ "width", width },
{ "height", height }
};
- Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: queryParams);
+ Dictionary response = await LCInternalApplication.HttpClient.Get>(path, queryParams: queryParams);
return new LCCapture {
Url = response["captcha_url"] as string,
Token = response["captcha_token"] as string
@@ -60,7 +60,7 @@ namespace LeanCloud.Storage {
{ "captcha_code", code },
{ "captcha_token", token }
};
- await LCApplication.HttpClient.Post>(path, data: data);
+ await LCInternalApplication.HttpClient.Post>(path, data: data);
}
}
}
diff --git a/Storage/Storage/LCCloud.cs b/Storage/Storage/LCCloud.cs
index 99fcdda..188ee3a 100644
--- a/Storage/Storage/LCCloud.cs
+++ b/Storage/Storage/LCCloud.cs
@@ -30,7 +30,7 @@ namespace LeanCloud.Storage {
{ PRODUCTION_KEY, IsProduction ? 1 : 0 }
};
object encodeParams = LCEncoder.Encode(parameters);
- Dictionary response = await LCApplication.HttpClient.Post>(path,
+ Dictionary response = await LCInternalApplication.HttpClient.Post>(path,
headers: headers,
data: encodeParams);
return response;
@@ -57,7 +57,7 @@ namespace LeanCloud.Storage {
{ PRODUCTION_KEY, IsProduction ? 1 : 0 }
};
object encodeParams = Encode(parameters);
- Dictionary response = await LCApplication.HttpClient.Post>(path,
+ Dictionary response = await LCInternalApplication.HttpClient.Post>(path,
headers: headers,
data: encodeParams);
return LCDecoder.Decode(response["result"]);
diff --git a/Storage/Storage/LCFile.cs b/Storage/Storage/LCFile.cs
index a27db7b..cb7c892 100644
--- a/Storage/Storage/LCFile.cs
+++ b/Storage/Storage/LCFile.cs
@@ -92,12 +92,12 @@ namespace LeanCloud.Storage {
}
LCObjectData objectData = LCObjectData.Decode(uploadToken);
Merge(objectData);
- _ = LCApplication.HttpClient.Post>("fileCallback", data: new Dictionary {
+ _ = LCInternalApplication.HttpClient.Post>("fileCallback", data: new Dictionary {
{ "result", true },
{ "token", token }
});
} catch (Exception e) {
- _ = LCApplication.HttpClient.Post>("fileCallback", data: new Dictionary {
+ _ = LCInternalApplication.HttpClient.Post>("fileCallback", data: new Dictionary {
{ "result", false },
{ "token", token }
});
@@ -112,7 +112,7 @@ namespace LeanCloud.Storage {
return;
}
string path = $"files/{ObjectId}";
- await LCApplication.HttpClient.Delete(path);
+ await LCInternalApplication.HttpClient.Delete(path);
}
public string GetThumbnailUrl(int width, int height, int quality = 100, bool scaleToFit = true, string format = "png") {
@@ -128,7 +128,7 @@ namespace LeanCloud.Storage {
{ "mime_type", MimeType },
{ "metaData", MetaData }
};
- return await LCApplication.HttpClient.Post>("fileTokens", data: data);
+ return await LCInternalApplication.HttpClient.Post>("fileTokens", data: data);
}
public static LCQuery GetQuery() {
diff --git a/Storage/Storage/LCFriendship.cs b/Storage/Storage/LCFriendship.cs
index 40c0d13..4f91ab1 100644
--- a/Storage/Storage/LCFriendship.cs
+++ b/Storage/Storage/LCFriendship.cs
@@ -19,7 +19,7 @@ namespace LeanCloud.Storage {
if (attributes != null) {
data["friendship"] = attributes;
}
- await LCApplication.HttpClient.Post>(path, data: data);
+ await LCInternalApplication.HttpClient.Post>(path, data: data);
}
public static async Task AcceptRequest(LCFriendshipRequest request, Dictionary attributes = null) {
@@ -33,7 +33,7 @@ namespace LeanCloud.Storage {
{ "friendship", attributes }
};
}
- await LCApplication.HttpClient.Put>(path, data: data);
+ await LCInternalApplication.HttpClient.Put>(path, data: data);
}
public static async Task DeclineRequest(LCFriendshipRequest request) {
@@ -41,7 +41,7 @@ namespace LeanCloud.Storage {
throw new ArgumentNullException(nameof(request));
}
string path = $"users/friendshipRequests/{request.ObjectId}/decline";
- await LCApplication.HttpClient.Put>(path);
+ await LCInternalApplication.HttpClient.Put>(path);
}
}
}
diff --git a/Storage/Storage/LCApplication.cs b/Storage/Storage/LCInternalApplication.cs
similarity index 93%
rename from Storage/Storage/LCApplication.cs
rename to Storage/Storage/LCInternalApplication.cs
index 8c00ce3..08dc6d0 100644
--- a/Storage/Storage/LCApplication.cs
+++ b/Storage/Storage/LCInternalApplication.cs
@@ -3,12 +3,13 @@ using System.Collections.Generic;
using LeanCloud.Common;
using LeanCloud.Storage;
using LeanCloud.Storage.Internal.Http;
+using LeanCloud.Storage.Internal.Storage;
namespace LeanCloud {
///
/// LeanCloud Application
///
- public class LCApplication {
+ public class LCInternalApplication {
// SDK 版本号,用于 User-Agent 统计
public const string SDKVersion = "0.7.2";
@@ -43,6 +44,10 @@ namespace LeanCloud {
get; set;
}
+ public static StorageController StorageController {
+ get; set;
+ }
+
internal static Dictionary AdditionalHeaders {
get;
} = new Dictionary();
diff --git a/Storage/Storage/LCObject.cs b/Storage/Storage/LCObject.cs
index d50523a..980c1e5 100644
--- a/Storage/Storage/LCObject.cs
+++ b/Storage/Storage/LCObject.cs
@@ -304,7 +304,7 @@ namespace LeanCloud.Storage {
{ "requests", LCEncoder.Encode(requestList) }
};
- List> results = await LCApplication.HttpClient.Post>>("batch", data: data);
+ List> results = await LCInternalApplication.HttpClient.Post>>("batch", data: data);
List resultList = results.Select(item => {
if (item.TryGetValue("error", out object error)) {
Dictionary err = error as Dictionary;
@@ -342,8 +342,8 @@ namespace LeanCloud.Storage {
queryParams["where"] = query.BuildWhere();
}
Dictionary response = ObjectId == null ?
- await LCApplication.HttpClient.Post>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams) :
- await LCApplication.HttpClient.Put>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams);
+ await LCInternalApplication.HttpClient.Post>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams) :
+ await LCInternalApplication.HttpClient.Put>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams);
LCObjectData data = LCObjectData.Decode(response);
Merge(data);
return this;
@@ -368,7 +368,7 @@ namespace LeanCloud.Storage {
return;
}
string path = $"classes/{ClassName}/{ObjectId}";
- await LCApplication.HttpClient.Delete(path);
+ await LCInternalApplication.HttpClient.Delete(path);
}
public static async Task DeleteAll(IEnumerable objects) {
@@ -377,7 +377,7 @@ namespace LeanCloud.Storage {
}
HashSet objectSet = new HashSet(objects.Where(item => item.ObjectId != null));
List> requestList = objectSet.Select(item => {
- string path = $"/{LCApplication.APIVersion}/classes/{item.ClassName}/{item.ObjectId}";
+ string path = $"/{LCInternalApplication.APIVersion}/classes/{item.ClassName}/{item.ObjectId}";
return new Dictionary {
{ "path", path },
{ "method", "DELETE" }
@@ -386,7 +386,7 @@ namespace LeanCloud.Storage {
Dictionary data = new Dictionary {
{ "requests", LCEncoder.Encode(requestList) }
};
- await LCApplication.HttpClient.Post>("batch", data: data);
+ await LCInternalApplication.HttpClient.Post>("batch", data: data);
}
public async Task Fetch(IEnumerable keys = null, IEnumerable includes = null) {
@@ -398,7 +398,7 @@ namespace LeanCloud.Storage {
queryParams["include"] = string.Join(",", includes);
}
string path = $"classes/{ClassName}/{ObjectId}";
- Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: queryParams);
+ Dictionary response = await LCInternalApplication.HttpClient.Get>(path, queryParams: queryParams);
LCObjectData objectData = LCObjectData.Decode(response);
Merge(objectData);
return this;
@@ -411,7 +411,7 @@ namespace LeanCloud.Storage {
IEnumerable uniqueObjects = objects.Where(item => item.ObjectId != null);
List> requestList = uniqueObjects.Select(item => {
- string path = $"/{LCApplication.APIVersion}/classes/{item.ClassName}/{item.ObjectId}";
+ string path = $"/{LCInternalApplication.APIVersion}/classes/{item.ClassName}/{item.ObjectId}";
return new Dictionary {
{ "path", path },
{ "method", "GET" }
@@ -421,7 +421,7 @@ namespace LeanCloud.Storage {
Dictionary data = new Dictionary {
{ "requests", LCEncoder.Encode(requestList) }
};
- List> results = await LCApplication.HttpClient.Post>>("batch",
+ List> results = await LCInternalApplication.HttpClient.Post>>("batch",
data: data);
Dictionary dict = new Dictionary();
foreach (Dictionary item in results) {
@@ -455,7 +455,7 @@ namespace LeanCloud.Storage {
public override string ToString() {
Dictionary originalData = LCObjectData.Encode(data);
Dictionary currentData = estimatedData.Union(originalData.Where(kv => !estimatedData.ContainsKey(kv.Key)))
- .ToDictionary(k => k.Key, v => v.Value);
+ .ToDictionary(k => k.Key, v => LCEncoder.Encode(v.Value));
return JsonConvert.SerializeObject(currentData);
}
diff --git a/Storage/Storage/LCQuery.cs b/Storage/Storage/LCQuery.cs
index b04d457..52b417f 100644
--- a/Storage/Storage/LCQuery.cs
+++ b/Storage/Storage/LCQuery.cs
@@ -342,7 +342,7 @@ namespace LeanCloud.Storage {
Dictionary parameters = BuildParams();
parameters["limit"] = 0;
parameters["count"] = 1;
- Dictionary ret = await LCApplication.HttpClient.Get>(path, queryParams: parameters);
+ Dictionary ret = await LCInternalApplication.HttpClient.Get>(path, queryParams: parameters);
return (int)ret["count"];
}
@@ -358,14 +358,14 @@ namespace LeanCloud.Storage {
{ "include", includes }
};
}
- Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: queryParams);
+ Dictionary response = await LCInternalApplication.HttpClient.Get>(path, queryParams: queryParams);
return DecodeLCObject(response);
}
public async Task> Find() {
string path = $"classes/{ClassName}";
Dictionary parameters = BuildParams();
- Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: parameters);
+ Dictionary response = await LCInternalApplication.HttpClient.Get>(path, queryParams: parameters);
List