com.amanotes.gdk 0.1.18 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/Packages/AmaGDKConfig.unitypackage +0 -0
  3. package/Packages/AmaGDKExample.unitypackage +0 -0
  4. package/Packages/AmaGDKTest.unitypackage +0 -0
  5. package/{Tests/TestScene00.unity.meta → Packages/AmaGDKTest.unitypackage.meta} +1 -1
  6. package/Packages/AppsflyerAdapter_v6.5.4.unitypackage +0 -0
  7. package/Packages/FirebaseAnalyticsAdapter_v9.1.0.unitypackage +0 -0
  8. package/Runtime/AmaGDK.Adapters.cs +28 -47
  9. package/Runtime/AmaGDK.Analytics.cs +120 -23
  10. package/Runtime/AmaGDK.Config.cs +1 -1
  11. package/Runtime/AmaGDK.Internal.cs +11 -3
  12. package/Runtime/AmaGDK.UserProfile.cs +10 -11
  13. package/Runtime/AmaGDK.Utils.cs +196 -7
  14. package/Runtime/AmaGDK.WebUtils.cs +106 -17
  15. package/Runtime/AmaGDK.cs +20 -18
  16. package/Runtime/AmaPassport/AmaGDK.AmaPassport.cs +444 -0
  17. package/{Tests/Runtime/AmaGDKCoreTest.cs.meta → Runtime/AmaPassport/AmaGDK.AmaPassport.cs.meta} +1 -1
  18. package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdCallback.java +7 -0
  19. package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdCallback.java.meta +32 -0
  20. package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.cs +96 -0
  21. package/{Tests/Runtime/MigrationTest.cs.meta → Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.cs.meta} +1 -1
  22. package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.java +79 -0
  23. package/Runtime/AmaPassport/Plugins/Android/AdvertisingIdFetcher.java.meta +32 -0
  24. package/{Tests/Editor.meta → Runtime/AmaPassport/Plugins/Android.meta} +1 -1
  25. package/Runtime/AmaPassport/Plugins/iOS/KeyChain.cs +59 -0
  26. package/Runtime/AmaPassport/Plugins/iOS/KeyChain.cs.meta +11 -0
  27. package/Runtime/AmaPassport/Plugins/iOS/KeyChainPlugin.mm +52 -0
  28. package/Runtime/AmaPassport/Plugins/iOS/KeyChainPlugin.mm.meta +33 -0
  29. package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.h +281 -0
  30. package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.h.meta +33 -0
  31. package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.m +1393 -0
  32. package/Runtime/AmaPassport/Plugins/iOS/UICKeyChainStore.m.meta +33 -0
  33. package/Runtime/AmaPassport/Plugins/iOS.meta +8 -0
  34. package/{Tests.meta → Runtime/AmaPassport/Plugins.meta} +1 -1
  35. package/{Tests/Runtime.meta → Runtime/AmaPassport.meta} +1 -1
  36. package/package.json +5 -2
  37. package/Packages/AppsFlyerAdapter_v6.5.4.unitypackage +0 -0
  38. package/Tests/Editor/AmaGDK.Editor.Test.asmdef +0 -23
  39. package/Tests/Editor/AmaGDK.Editor.Test.asmdef.meta +0 -7
  40. package/Tests/Runtime/AmaGDK.Test.asmdef +0 -20
  41. package/Tests/Runtime/AmaGDK.Test.asmdef.meta +0 -7
  42. package/Tests/Runtime/AmaGDKCoreTest.cs +0 -228
  43. package/Tests/Runtime/MigrationTest.cs +0 -165
  44. package/Tests/TestScene00.unity +0 -125
  45. package/Tests/TestScene01.unity +0 -199
  46. package/Tests/TestScene01.unity.meta +0 -7
  47. package/Tests/TestScene02.unity +0 -209
  48. package/Tests/TestScene02.unity.meta +0 -7
  49. package/Tests/TestScene03.unity +0 -599
  50. package/Tests/TestScene03.unity.meta +0 -7
  51. /package/Packages/{AppsFlyerAdapter_v6.5.4.unitypackage.meta → AppsflyerAdapter_v6.5.4.unitypackage.meta} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.20 - 2023-04-20]
4
+ ### Refactor Adapter architure to support reading adapter config from Core
5
+ ### Add session stat for Analytics module
6
+ ### Unit test for Json parser and Analytics module
7
+
8
+ ## [0.1.19 - 2023-04-11]
9
+ ### Move AmaGDKTest out of AmaGDKCore
10
+
3
11
  ## [0.1.18 - 2023-03-27]
4
12
  ### Fix AmaGDK's autoInit saving issue
5
13
 
Binary file
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: d0b6ac2d48f974ba48ae61cbae556c4b
2
+ guid: 4e129ed8b608d4cfcabb2a4e8c558f14
3
3
  DefaultImporter:
4
4
  externalObjects: {}
5
5
  userData:
@@ -1,26 +1,23 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
 
4
- using ConfigAsset = Amanotes.Core.Internal.ConfigAsset;
5
- using Status = Amanotes.Core.Internal.Status;
6
4
  using static Amanotes.Core.Internal.Logging;
7
- using static Amanotes.Core.Internal.Messsage;
8
5
  using System.Linq;
9
6
 
10
7
  namespace Amanotes.Core.Internal
11
8
  {
12
-
13
- [Serializable] public class AdapterInfo
9
+ public abstract class AdapterContext
14
10
  {
15
- public string id;
16
- public string version;
11
+ public string adapterId;
12
+ public string adapterVersion;
17
13
  public int initOrder;
14
+
15
+ // Status support
18
16
  public Status status = Status.None;
19
- public IAdapter adapter;
20
-
21
- public bool IsReady { get { return status == Status.Ready; }}
22
-
23
- public void Init(){
17
+ public bool IsReady { get { return status == Status.Ready; } }
18
+
19
+ public void Init()
20
+ {
24
21
  if (status != Status.None)
25
22
  {
26
23
  LogWarning($"Invalid status: {status}");
@@ -28,62 +25,46 @@ namespace Amanotes.Core.Internal
28
25
  }
29
26
 
30
27
  status = Status.Initialize;
31
- adapter.Init((success) =>
28
+ Init((success) =>
32
29
  {
33
30
  status = success ? Status.Ready : Status.Failed;
34
31
  });
35
32
  }
36
33
 
37
- public T GetAdapterApi<T>(){ return (T)adapter; }
38
- }
39
-
40
- public interface IAdapter
41
- {
42
- void Init(Action<bool> onCompleted);
34
+ protected virtual void Init(Action<bool> onCompleted) { }
35
+ public T GetAdapterApi<T>() { return (T)(object)this; }
36
+ public abstract T GetAdapterConfig<T>() where T : class;
43
37
  }
44
38
 
45
- // public static class AdapterExtension
46
- // {
47
- // public static string GetId<T>(this T adapter) where T: IAdapter {
48
- // return Adapter.GetId(typeof(T));
49
- // }
50
- // }
51
-
52
39
  public static class Adapter
53
40
  {
54
- internal static readonly List<AdapterInfo> listAdapters = new List<AdapterInfo>();
55
-
56
- public static string GetId(Type adapterType) {
41
+ internal static readonly List<AdapterContext> listAdapters = new List<AdapterContext>();
42
+
43
+ public static string GetId(Type adapterType)
44
+ {
57
45
  return adapterType.Name.Replace("Adapter", string.Empty);
58
46
  }
59
47
 
60
- public static void Register<T>(string version) where T : IAdapter, new()
48
+ public static void Register<T>(Func<ConfigAsset, T> createFunc) where T : AdapterContext
61
49
  {
62
- var typeT = typeof(T);
63
- var id = GetId(typeT);
64
-
65
50
  if (AmaGDK._status != Status.None)
66
51
  {
67
52
  LogWarningOnce($"RegisterAdapter - Invalid status: {AmaGDK._status}");
68
53
  return;
69
54
  }
70
55
 
71
- var orderConfig = AmaGDK.Config.initOrder.FirstOrDefault(item => item.id == id);
72
- listAdapters.Add(new AdapterInfo()
73
- {
74
- id = id,
75
- version = version,
76
- initOrder = (orderConfig != null) ? orderConfig.order : 0,
77
- adapter = new T()
78
- });
56
+ var adapter = createFunc(AmaGDK.Config);
57
+ var orderConfig = AmaGDK.Config.initOrder.FirstOrDefault(item => item.id == adapter.adapterId);
58
+ if (orderConfig != null) adapter.initOrder = orderConfig.order;
59
+ listAdapters.Add(adapter);
79
60
  }
80
-
81
- public static AdapterInfo Find<T>()
61
+
62
+ public static AdapterContext Find<T>()
82
63
  {
83
64
  for (var i = 0; i < listAdapters.Count; i++)
84
65
  {
85
66
  var item = listAdapters[i];
86
- var itemType = item.adapter.GetType();
67
+ var itemType = item.GetType();
87
68
  if (!typeof(T).IsAssignableFrom(itemType)) continue;
88
69
  return item;
89
70
  }
@@ -91,13 +72,13 @@ namespace Amanotes.Core.Internal
91
72
  return default;
92
73
  }
93
74
 
94
- public static List<AdapterInfo> FindAll<T>()
75
+ public static List<AdapterContext> FindAll<T>()
95
76
  {
96
- var result = new List<AdapterInfo>();
77
+ var result = new List<AdapterContext>();
97
78
  for (var i = 0; i < listAdapters.Count; i++)
98
79
  {
99
80
  var item = listAdapters[i];
100
- var itemType = item.adapter.GetType();
81
+ var itemType = item.GetType();
101
82
  if (!typeof(T).IsAssignableFrom(itemType)) continue;
102
83
  result.Add(item);
103
84
  }
@@ -1,6 +1,7 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
  using UnityEngine;
4
+ using System.Text;
4
5
 
5
6
  using Amanotes.Core.Internal;
6
7
  using static Amanotes.Core.Internal.Logging;
@@ -10,7 +11,7 @@ using EventParams = Amanotes.Core.AmaGDK.Analytics.EventParams;
10
11
  namespace Amanotes.Core
11
12
  {
12
13
  [Serializable]
13
- public class AnalyticsAdapterBaseConfig
14
+ public class AnalyticsAdapterConfig
14
15
  {
15
16
  public bool SendEventByDefault;
16
17
 
@@ -75,7 +76,7 @@ namespace Amanotes.Core
75
76
  if (!sendAtCount.TryGetValue(eventName, out var sendAtCountConfig)) return false;
76
77
 
77
78
  int accumulatedCount = GetAccumulatedCount(eventName, sendAtCountConfig.withinSession);
78
- return sendAtCountConfig.listCount == null ? false : !sendAtCountConfig.listCount.Contains(accumulatedCount);
79
+ return sendAtCountConfig.listCount != null && !sendAtCountConfig.listCount.Contains(accumulatedCount);
79
80
  }
80
81
  }
81
82
 
@@ -230,8 +231,11 @@ namespace Amanotes.Core
230
231
  {
231
232
  foreach (var adapterID in adapterIDs)
232
233
  {
233
- var adapter = listAdapters.Find(a => a.id == adapterID)?.GetAdapterApi<IAnalyticAdapter>();
234
- adapter?.OnlyAllowEvents(eventNames);
234
+ var adapter = listAdapters.Find(a => a.adapterId == adapterID);
235
+ if (adapter == null) continue;
236
+
237
+ var config = adapter.GetAdapterConfig<AnalyticsAdapterConfig>();
238
+ config.AlwaysSend = eventNames;
235
239
  }
236
240
  }
237
241
 
@@ -239,8 +243,11 @@ namespace Amanotes.Core
239
243
  {
240
244
  foreach (var adapterID in adapterIDs)
241
245
  {
242
- var adapter = listAdapters.Find(a => a.id == adapterID)?.GetAdapterApi<IAnalyticAdapter>();
243
- adapter?.OnlyBanEvents(eventNames);
246
+ var adapter = listAdapters.Find(a => a.adapterId == adapterID);
247
+ if (adapter == null) continue;
248
+
249
+ var config = adapter.GetAdapterConfig<AnalyticsAdapterConfig>();
250
+ config.NeverSend = eventNames;
244
251
  }
245
252
  }
246
253
 
@@ -280,8 +287,9 @@ namespace Amanotes.Core
280
287
  internal static readonly Dictionary<string, EventConfig> sendAtCount = new Dictionary<string, EventConfig>();
281
288
  internal static Predicate<EventDetail> logEventHook = null;
282
289
  internal static readonly Queue<EventParams> eventQueue = new Queue<EventParams>();
283
- internal static readonly List<AdapterInfo> listAdapters = new List<AdapterInfo>();
290
+ internal static readonly List<AdapterContext> listAdapters = new List<AdapterContext>();
284
291
  internal static readonly AnalyticsData localData = new AnalyticsData().LoadJsonFromFile();
292
+ internal static readonly SessionStat sessionStat = new SessionStat();
285
293
 
286
294
  internal static void Init()
287
295
  {
@@ -296,6 +304,7 @@ namespace Amanotes.Core
296
304
  {
297
305
  if (eventQueue.Count <= 0) return;
298
306
  bool showAnalyticsLog = Config.common.showAnalyticsLog;
307
+ sessionStat.ClearLastFrameEventInfo();
299
308
 
300
309
  while (eventQueue.Count > 0)
301
310
  {
@@ -313,14 +322,36 @@ namespace Amanotes.Core
313
322
  var eventNameToSend = GetEventNameToSend(eventData.eventName, countInSession, totalCount);
314
323
  NormalizeEventName(ref eventNameToSend);
315
324
 
316
- if (showAnalyticsLog) Debug.Log($"[AmaGDK] Event <{eventNameToSend}> (in session: {countInSession}, total: {totalCount})");
325
+ if (showAnalyticsLog) Debug.Log($"[AmaGDK] Event <{eventNameToSend}> (in session: {countInSession}, total: {totalCount})\n" +
326
+ $"Params:\n{JsonUtils.DictionaryToJson(eventData.parameters, true)}");
327
+
328
+ var inUseAdapterIDs = new List<string>();
317
329
  foreach (var m in listAdapters)
318
330
  {
319
- m.GetAdapterApi<IAnalyticAdapter>().LogEvent(eventNameToSend, eventData);
331
+ var api = m.GetAdapterApi<IAnalyticAdapter>();
332
+ var config = m.GetAdapterConfig<AnalyticsAdapterConfig>();
333
+
334
+ if (eventData.overrideConfig)
335
+ {
336
+ // IMPORTANT NOTE:
337
+ //
338
+ // Once set overrideConfig, we should skip the adapter config completely!!!
339
+ //
340
+ if (eventData.IsAdapterForbidden(m.adapterId)) continue;
341
+ }
342
+ else // Do not remove else
343
+ {
344
+ if (config.IsForbidden(eventData.eventName)) continue;
345
+ }
346
+
347
+ api.LogEvent(eventNameToSend, eventData.parameters);
348
+ inUseAdapterIDs.Add(m.adapterId);
320
349
  }
350
+ sessionStat.Add(eventNameToSend, eventData, inUseAdapterIDs);
321
351
  }
322
352
 
323
353
  localData.SaveIfDirty();
354
+ sessionStat.Save();
324
355
  }
325
356
 
326
357
  internal static string GetEventNameToSend(string eventName, int countInSession, int totalCount)
@@ -331,11 +362,17 @@ namespace Amanotes.Core
331
362
  return $"{eventName}_{(config.withinSession ? countInSession : totalCount).ToString(config.numberFormat)}";
332
363
  }
333
364
 
334
- internal static bool NormalizeEventName(ref string eventName)
365
+ internal static void NormalizeEventName(ref string eventName)
335
366
  {
336
367
  var sb = tmpWarningSB;
337
368
  sb.Clear();
338
369
 
370
+ if (string.IsNullOrEmpty(eventName))
371
+ {
372
+ sb.AppendLine($" - EventName should not be empty");
373
+ return;
374
+ }
375
+
339
376
  var normalizedEventName = eventName.Trim()
340
377
  .Replace(' ', '_')
341
378
  .Replace('-', '_');
@@ -355,7 +392,6 @@ namespace Amanotes.Core
355
392
  if (!char.IsLetter(eventName[0])) sb.AppendLine($" - EventName must start with a letter: <{eventName}> ");
356
393
  if (eventName.Length > 40) sb.AppendLine($" - EventName is too long ({eventName.Length} > 40): <{eventName}> ");
357
394
  if (sb.Length > 0) LogWarningOnce(sb.ToString(), $"NormalizeEventName<{eventName}>");
358
- return true;
359
395
  }
360
396
 
361
397
  internal static bool ShouldSendEvent(EventParams eventData)
@@ -395,6 +431,26 @@ namespace Amanotes.Core
395
431
  public int totalCount;
396
432
  }
397
433
 
434
+ [Serializable]
435
+ internal class EventStat
436
+ {
437
+ public string eventNameToSend;
438
+ public List<string> adapters;
439
+ public string parameters;
440
+
441
+ public EventStat(string eventNameToSend, EventParams eventParams, List<string> adapterIDs)
442
+ {
443
+ this.eventNameToSend = eventNameToSend;
444
+ parameters = JsonUtils.DictionaryToJson(eventParams.parameters, false);
445
+ adapters = adapterIDs;
446
+ }
447
+
448
+ public string ToTsv()
449
+ {
450
+ return $"{eventNameToSend}\t{string.Join(",", adapters)}\t{parameters}";
451
+ }
452
+ }
453
+
398
454
  [Flags]
399
455
  internal enum IntegrityFlag
400
456
  {
@@ -414,10 +470,12 @@ namespace Amanotes.Core
414
470
 
415
471
  public Dictionary<string, object> ToDictionary()
416
472
  {
417
- var result = new Dictionary<string, object>();
418
- result.Add("device_id", deviceId);
419
- result.Add("app_version", appVersion);
420
- result.Add("amagdk_version", amaGDKVersion);
473
+ var result = new Dictionary<string, object>
474
+ {
475
+ { "device_id", deviceId },
476
+ { "app_version", appVersion },
477
+ { "amagdk_version", amaGDKVersion }
478
+ };
421
479
  return result;
422
480
  }
423
481
  }
@@ -425,14 +483,16 @@ namespace Amanotes.Core
425
483
  [Serializable]
426
484
  internal class AnalyticsData : IJsonFile
427
485
  {
428
- [NonSerialized] internal bool _dirty = false;
486
+ [NonSerialized] internal bool _dirty = false;
429
487
 
430
488
  public List<string> funnelSignatures = new List<string>();
431
489
  public List<EventDetail> eventDetails = new List<EventDetail>();
432
- public MigrationLog migrationLog = new MigrationLog();
490
+ public MigrationLog migrationLog = new MigrationLog();
433
491
 
434
492
  internal EventDetail GetEventDetail(string eventName, bool autoNew = false)
435
493
  {
494
+ if (string.IsNullOrEmpty(eventName)) return null;
495
+
436
496
  var result = eventDetails.Find(e => e.eventName == eventName);
437
497
  if (result != null) return result;
438
498
  if (autoNew == false) return null;
@@ -497,8 +557,47 @@ namespace Amanotes.Core
497
557
 
498
558
  _dirty = true;
499
559
  SaveIfDirty();
560
+ }
561
+ }
562
+
563
+ internal class SessionStat
564
+ {
565
+ public List<EventStat> lastFrameEventStats = new List<EventStat>();
566
+
567
+ const string TSV_HEADER_ROW = "EventName\tAdapters\tParameters";
568
+ string fileName = nameof(SessionStat) + DateTime.Now.ToString("_yyMMdd_HHmmss") + ".tsv";
569
+ bool isFirstSave = true;
570
+ StringBuilder contents = new StringBuilder();
571
+
572
+ internal void Add(string eventNameToSend, EventParams eventParams, List<string> adapterIDs)
573
+ {
574
+ var eventStat = new EventStat(eventNameToSend, eventParams, adapterIDs);
575
+ lastFrameEventStats.Add(eventStat);
576
+ }
577
+
578
+ internal void ClearLastFrameEventInfo()
579
+ {
580
+ lastFrameEventStats.Clear();
500
581
  }
501
- }
582
+
583
+ internal void Save()
584
+ {
585
+ if (!Config.common.enableEventStat || lastFrameEventStats.Count == 0) return;
586
+
587
+ contents.Clear();
588
+ if (isFirstSave)
589
+ {
590
+ contents = contents.AppendLine(TSV_HEADER_ROW);
591
+ isFirstSave = false;
592
+ }
593
+ foreach (var stat in lastFrameEventStats)
594
+ {
595
+ contents.AppendLine(stat.ToTsv());
596
+ }
597
+
598
+ FileUtils.SaveAppend(fileName, contents.ToString());
599
+ }
600
+ }
502
601
  }
503
602
  }
504
603
 
@@ -512,6 +611,7 @@ namespace Amanotes.Core
512
611
  data.funnelSignature = string.IsNullOrEmpty(signature) ? data.eventName : signature;
513
612
  return ap;
514
613
  }
614
+
515
615
  public static IEventParamsBuilder SetAsAccumulated(this IEventParamsBuilder ap, bool withinSession = false)
516
616
  {
517
617
  if (ap == null) return null;
@@ -647,18 +747,15 @@ namespace Amanotes.Core.Internal
647
747
  public bool showAnalyticsLog = true;
648
748
  public bool normalizeEventName = true;
649
749
  public bool checkMigrationIntegrity = true;
750
+ public bool enableEventStat;
650
751
  }
651
752
 
652
753
  public interface IAnalyticAdapter
653
754
  {
654
- void LogEvent(string eventNameToSend, EventParams eventData);
755
+ void LogEvent(string eventNameToSend, Dictionary<string, object> parameters);
655
756
 
656
757
  void SetUserId(string userId);
657
758
 
658
759
  void SetUserProperty(string key, string value);
659
-
660
- void OnlyAllowEvents(List<string> eventNames);
661
-
662
- void OnlyBanEvents(List<string> eventNames);
663
760
  }
664
761
  }
@@ -48,7 +48,7 @@ namespace Amanotes.Core.Internal {
48
48
  initOrder.Clear();
49
49
 
50
50
  var counter = 0;
51
- foreach (var adapter in GetAllAdapters<IAdapter>())
51
+ foreach (var adapter in GetAllAdapters<AdapterContext>())
52
52
  {
53
53
  var id = adapter.Name.Replace("Adapter", string.Empty);
54
54
  initOrder.Add(new InitOrder(){ id = id, order = counter++ });
@@ -1,9 +1,9 @@
1
- using System.Linq;
2
1
  using System.Text;
3
2
  using System.Collections.Generic;
4
3
 
5
4
  using UnityEngine;
6
5
  using UnityObject = UnityEngine.Object;
6
+ using static Amanotes.Core.AmaGDK.Analytics;
7
7
 
8
8
  #if UNITY_EDITOR
9
9
  using UnityEditor;
@@ -123,8 +123,16 @@ namespace Amanotes.Core.Internal
123
123
  AmaGDK._status = Status.None;
124
124
  AmaGDK._allowInit = false;
125
125
 
126
- // TODO: Destroy adapters?
127
- Adapter.listAdapters.Clear();
126
+ // TODO: Destroy adapters? - Don't do this. An adapter registers just 1 time. Clear adapters cause Analytics test fail.
127
+ //Adapter.listAdapters.Clear();
128
+ }
129
+
130
+ public static void ClearAnalyticsData()
131
+ {
132
+ AnalyticsData analyticsData = AmaGDK.Analytics.localData;
133
+ analyticsData.funnelSignatures.Clear();
134
+ analyticsData.eventDetails.Clear();
135
+ analyticsData.migrationLog = new AmaGDK.Analytics.MigrationLog();
128
136
  }
129
137
  }
130
138
  }
@@ -1,6 +1,6 @@
1
1
  using System;
2
+ using Amanotes.Core.Internal;
2
3
  using UnityEngine;
3
- using static Amanotes.Core.Internal.Logging;
4
4
  using FileUtils = Amanotes.Core.Internal.FileUtils;
5
5
 
6
6
  namespace Amanotes.Core
@@ -10,19 +10,11 @@ namespace Amanotes.Core
10
10
  public static readonly UserProfile User = new UserProfile().Load();
11
11
 
12
12
  [Serializable]
13
- public class UserProfile
13
+ public partial class UserProfile: IJsonFile
14
14
  {
15
+ [NonSerialized] internal bool _dirty = false;
15
16
  const string FILE_NAME = nameof(UserProfile);
16
17
 
17
- public string amaId;
18
- public string amaDeviceId;
19
- public string gaId;
20
- public string androidId;
21
- public string idfa;
22
- public string idfv;
23
- public string appsFlyerId;
24
- public string firebaseUserPseudoId;
25
-
26
18
  public void Save()
27
19
  {
28
20
  FileUtils.Save(FILE_NAME, JsonUtility.ToJson(this));
@@ -36,6 +28,13 @@ namespace Amanotes.Core
36
28
  JsonUtility.FromJsonOverwrite(json, this);
37
29
  return this;
38
30
  }
31
+
32
+ internal void SaveIfDirty()
33
+ {
34
+ if (!_dirty) return;
35
+ _dirty = false;
36
+ this.SaveJsonToFile();
37
+ }
39
38
  }
40
39
  }
41
40
  }