com.amanotes.gdk 0.2.81-alpha.5 → 0.2.81-alpha.6

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 (34) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  3. package/Extra/AutoEventQC.unitypackage +0 -0
  4. package/Extra/CheckDiskSpace.unitypackage +0 -0
  5. package/Extra/Consent.unitypackage +0 -0
  6. package/Extra/CrashlyticHook.unitypackage +0 -0
  7. package/Extra/ForceUpdate.unitypackage +0 -0
  8. package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
  9. package/Extra/PostProcessor.unitypackage +0 -0
  10. package/Packages/AmaGDKConfig.unitypackage +0 -0
  11. package/Packages/AmaGDKExample.unitypackage +0 -0
  12. package/Packages/AmaGDKTest.unitypackage +0 -0
  13. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
  14. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  15. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  16. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  17. package/Packages/IronSourceAdapter.AdQuality.unitypackage +0 -0
  18. package/Packages/IronSourceAdapter.unitypackage +0 -0
  19. package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
  20. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  21. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  22. package/Runtime/AmaGDK.cs +1 -1
  23. package/Runtime/Consent/AmaGDK.Consent.cs +224 -0
  24. package/Runtime/Consent/GDKPrivacyButton.cs +25 -0
  25. package/Runtime/Consent/GDKPrivacyButton.cs.meta +3 -0
  26. package/Runtime/Consent/GDKPrivacyButton.prefab +148 -0
  27. package/Runtime/Consent/GDKPrivacyButton.prefab.meta +7 -0
  28. package/Runtime/Consent.meta +3 -0
  29. package/Runtime/Core/GDKTaskTracker.cs +118 -0
  30. package/Runtime/Core/GDKTaskTracker.cs.meta +3 -0
  31. package/Runtime/Utils/GDKUtils.cs +8 -0
  32. package/package.json +1 -1
  33. package/Runtime/AmaGDK.Consent.cs +0 -256
  34. /package/Runtime/{AmaGDK.Consent.cs.meta → Consent/AmaGDK.Consent.cs.meta} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [v0.2.81-alpha.6] - 2024-12-10
2
+ - [Dev] Refactor Consent module
3
+ - [Dev] Add GDKTaskTracker
4
+ - [Release] 0.2.81-alpha.5
5
+ - [Dev] Save build info
6
+ - Revert "[Dev] Analytics save file in async"
7
+ - [Dev] Make GDKDebug thread-safe
8
+ - [Dev] Add GDKPostBuildAsset
9
+ - [Fix] Retrieve the correct app version from CI variable
10
+ - [Dev] Improve GDK editor experience before config asset imported
11
+ - [Dev] Analytics save file in async
12
+ - [Dev] Move GDKFileUtils to a separated file
13
+ - [Dev] Update game ops model
14
+ - [Dev] Add ABLab
15
+ - [Dev] Move imported GDK Adapter from RawData to Modules
16
+
1
17
  # Changelog
2
18
 
3
19
  ## [0.2.80] - 2024-11-13
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/Runtime/AmaGDK.cs CHANGED
@@ -27,7 +27,7 @@ namespace Amanotes.Core
27
27
  {
28
28
  public partial class AmaGDK : MonoBehaviour
29
29
  {
30
- public const string VERSION = "0.2.80";
30
+ public const string VERSION = "v0.2.81-alpha.6";
31
31
 
32
32
  internal static Status _status = Status.None;
33
33
  internal static ConfigAsset _config = null;
@@ -0,0 +1,224 @@
1
+ using System;
2
+ using Amanotes.Core.Internal;
3
+ using UnityEngine;
4
+ using static Amanotes.Core.GDKDebug;
5
+
6
+ namespace Amanotes.Core
7
+ {
8
+ public partial class AmaGDK //Consent
9
+ {
10
+ public static partial class Consent //Public
11
+ {
12
+ private static readonly GDKTaskTracker _allConsentTaskTracker = new GDKTaskTracker();
13
+ public static void RequestAllConsents(Action onComplete)
14
+ {
15
+ _allConsentTaskTracker.RegisterOnCompleteCallback(onComplete);
16
+ if (_allConsentTaskTracker.HasStarted) return;
17
+
18
+ _allConsentTaskTracker.MarkStarted();
19
+
20
+ void CompleteRequestAllConsents()
21
+ {
22
+ _allConsentTaskTracker.MarkCompleted();
23
+ }
24
+ void ShowConsentIfRequired()
25
+ {
26
+ CMP.ShowConsentFormIfRequired(
27
+ _ => CompleteRequestAllConsents(),
28
+ _ => CompleteRequestAllConsents());
29
+ }
30
+ #if UNITY_IOS
31
+ ATT.Request(
32
+ allow =>
33
+ {
34
+ if (allow)
35
+ {
36
+ ShowConsentIfRequired();
37
+ return;
38
+ }
39
+ CompleteRequestAllConsents();
40
+ });
41
+ #else
42
+ ShowConsentIfRequired();
43
+ #endif
44
+ }
45
+ }
46
+
47
+ public static partial class Consent //ATT
48
+ {
49
+ public static class ATT
50
+ {
51
+ public static bool IsAllowed
52
+ {
53
+ get
54
+ {
55
+ if (checkedATT) return allowedATT;
56
+ LogWarning("[Consent] ATT has not completed yet");
57
+ return false;
58
+ }
59
+ }
60
+
61
+ public static void Request(Action<bool> onComplete)
62
+ {
63
+ if (checkedATT)
64
+ {
65
+ Log("[Consent] ATT has already completed");
66
+ onComplete?.Invoke(allowedATT);
67
+ return;
68
+ }
69
+ if (ConsentHook.ATTRequest == null)
70
+ {
71
+ LogWarning("[Consent] ConsentHook.ATTRequest is not implemented");
72
+ onComplete?.Invoke(false);
73
+ return;
74
+ }
75
+
76
+ ConsentHook.ATTRequest(isAllowed =>
77
+ {
78
+ data.att = isAllowed ? Status.Allowed : Status.NotAllowed;
79
+ data.SaveJsonToFile();
80
+ onComplete?.Invoke(allowedATT);
81
+ });
82
+ }
83
+ }
84
+
85
+ }
86
+
87
+ public static partial class Consent //CMP
88
+ {
89
+ public static class CMP
90
+ {
91
+ /// <summary>
92
+ /// Determines if a consent popup should be shown to the user and displays it if required.
93
+ /// The consent popup will be shown only once in the lifecycle of the app if this function is used.
94
+ /// </summary>
95
+ /// <remarks>
96
+ /// The consent popup is required in the European Economic Area (EEA) and
97
+ /// other countries that have implemented the General Data Protection Regulation (GDPR).
98
+ /// </remarks>
99
+ /// <param name="onComplete">Callback invoked with a boolean indicating the
100
+ /// ConsentInformation.CanRequestAds() result
101
+ /// </param>
102
+ /// <param name="onError">Callback invoked with an error message if the consent
103
+ /// form could not be loaded or shown.</param>
104
+ public static void ShowConsentFormIfRequired(Action<bool> onComplete, Action<string> onError)
105
+ {
106
+ if (ConsentHook.ShowConsentFormIfRequired == null)
107
+ {
108
+ LogWarning("[Consent] ConsentHook.ShowConsentFormIfRequired is not implemented");
109
+ onError?.Invoke("ShowPrivacyForm is not implemented");
110
+ return;
111
+ }
112
+ if (data.consentAlreadyShown)
113
+ {
114
+ Log("[Consent] Consent form has already been shown");
115
+ onComplete?.Invoke(data.canShowAds);
116
+ return;
117
+ }
118
+ ConsentHook.ShowConsentFormIfRequired(canShowAd =>
119
+ {
120
+ data.canShowAds = canShowAd;
121
+ data.consentAlreadyShown = true;
122
+ data.SaveJsonToFile();
123
+ onComplete?.Invoke(canShowAd);
124
+ }, onError);
125
+ }
126
+
127
+ /// <summary>
128
+ /// Forces the consent popup to be shown to the user, regardless of previous
129
+ /// consent status.
130
+ /// </summary>
131
+ /// <param name="onComplete">Callback invoked with a boolean indicating the
132
+ /// ConsentInformation.CanRequestAds() result
133
+ /// </param>
134
+ /// <param name="onError">Callback invoked with an error message if the consent
135
+ /// form could not be loaded or shown.</param>
136
+ public static void ShowPrivacyForm(Action<bool> onComplete, Action<string> onError)
137
+ {
138
+ if (ConsentHook.CheckPrivacyOptionsRequired == null)
139
+ {
140
+ LogWarning("[Consent] ConsentHook.ShowPrivacyForm is not implemented");
141
+ onError?.Invoke("ShowPrivacyForm is not implemented");
142
+ return;
143
+ }
144
+ ConsentHook.ShowPrivacyForm(onComplete, onError);
145
+ }
146
+
147
+ /// <summary>
148
+ /// Determines whether privacy options are required for the current user.
149
+ /// Updates the consent information before returning the result.
150
+ /// </summary>
151
+ /// <param name="onComplete">Callback invoked with `true` if privacy options are required, otherwise `false`.</param>
152
+ public static void CheckPrivacyOptionsRequired(Action<bool> onComplete)
153
+ {
154
+ if (ConsentHook.CheckPrivacyOptionsRequired == null)
155
+ {
156
+ LogWarning("[Consent] ConsentHook.CheckPrivacyOptionsRequired is not implemented");
157
+ onComplete?.Invoke(false);
158
+ return;
159
+ }
160
+ ConsentHook.CheckPrivacyOptionsRequired(onComplete);
161
+ }
162
+
163
+ [Obsolete("Use ShowPrivacyForm instead")]
164
+ public static void ForceShowPopup(Action<bool> onComplete)
165
+ {
166
+ ShowPrivacyForm(onComplete, s => onComplete?.Invoke(false));
167
+ }
168
+ }
169
+ }
170
+
171
+ public static partial class Consent //Internal
172
+ {
173
+ private static readonly Lazy<ConsentData> _data = new Lazy<ConsentData>(() => new ConsentData().LoadJsonFromFile());
174
+ private static ConsentData data => _data.Value;
175
+ private static Action _onConsentComplete;
176
+
177
+ internal static bool checkedATT => data.att >= Status.Allowed;
178
+ internal static bool allowedATT => data.att == Status.Allowed;
179
+
180
+ internal enum Status
181
+ {
182
+ None,
183
+ NotRequired,
184
+ Allowed,
185
+ NotAllowed
186
+ }
187
+
188
+ internal static bool InitModule()
189
+ {
190
+ if (_config.autoGetConsent)
191
+ {
192
+ RequestAllConsents(null);
193
+ }
194
+ return true;
195
+ }
196
+ }
197
+ }
198
+
199
+ [Serializable]
200
+ public class ConsentData : IJsonFile
201
+ {
202
+ [SerializeField] internal AmaGDK.Consent.Status att;
203
+ [SerializeField] internal bool consentAlreadyShown;
204
+ [SerializeField] internal bool canShowAds;
205
+ }
206
+
207
+ public static class ConsentHook
208
+ {
209
+ public static Action<Action<bool>, Action<string>> ShowConsentFormIfRequired;
210
+ public static Action<Action<bool>, Action<string>> ShowPrivacyForm;
211
+ public static Action<Action<bool>> CheckPrivacyOptionsRequired;
212
+ public static Action<Action<bool>> ATTRequest;
213
+ }
214
+ }
215
+
216
+ namespace Amanotes.Core.Internal
217
+ {
218
+ public partial class ConfigAsset
219
+ {
220
+ [SerializeField]
221
+ [Tooltip("Auto pop-up ATT and CMP form")]
222
+ public bool autoGetConsent = true;
223
+ }
224
+ }
@@ -0,0 +1,25 @@
1
+ using System;
2
+ using UnityEngine;
3
+ using UnityEngine.UI;
4
+ namespace Amanotes.Core
5
+ {
6
+ public class GDKPrivacyButton: MonoBehaviour
7
+ {
8
+ public Button button;
9
+ private void Start()
10
+ {
11
+ gameObject.SetActive(false);
12
+ UpdateUI();
13
+ }
14
+
15
+ public void OnButtonClick()
16
+ {
17
+ AmaGDK.Consent.CMP.ShowPrivacyForm(canShowAd => UpdateUI(), GDKDebug.LogWarning);
18
+ }
19
+
20
+ private void UpdateUI()
21
+ {
22
+ AmaGDK.Consent.CMP.CheckPrivacyOptionsRequired(required => button.interactable = required);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 23184a9779a949419e702ce599a0dcc5
3
+ timeCreated: 1733448516
@@ -0,0 +1,148 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!1 &4256389965931995120
4
+ GameObject:
5
+ m_ObjectHideFlags: 0
6
+ m_CorrespondingSourceObject: {fileID: 0}
7
+ m_PrefabInstance: {fileID: 0}
8
+ m_PrefabAsset: {fileID: 0}
9
+ serializedVersion: 6
10
+ m_Component:
11
+ - component: {fileID: 1151037748665809425}
12
+ - component: {fileID: 981792811258053838}
13
+ - component: {fileID: 6086753863169534924}
14
+ - component: {fileID: 3785844084317390329}
15
+ - component: {fileID: 2957037893780307854}
16
+ m_Layer: 0
17
+ m_Name: GDKPrivacyButton
18
+ m_TagString: Untagged
19
+ m_Icon: {fileID: 0}
20
+ m_NavMeshLayer: 0
21
+ m_StaticEditorFlags: 0
22
+ m_IsActive: 1
23
+ --- !u!224 &1151037748665809425
24
+ RectTransform:
25
+ m_ObjectHideFlags: 0
26
+ m_CorrespondingSourceObject: {fileID: 0}
27
+ m_PrefabInstance: {fileID: 0}
28
+ m_PrefabAsset: {fileID: 0}
29
+ m_GameObject: {fileID: 4256389965931995120}
30
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
31
+ m_LocalPosition: {x: 0, y: 0, z: 0}
32
+ m_LocalScale: {x: 1, y: 1, z: 1}
33
+ m_Children: []
34
+ m_Father: {fileID: 0}
35
+ m_RootOrder: 0
36
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
37
+ m_AnchorMin: {x: 0.5, y: 0.5}
38
+ m_AnchorMax: {x: 0.5, y: 0.5}
39
+ m_AnchoredPosition: {x: 0, y: 0}
40
+ m_SizeDelta: {x: 100, y: 100}
41
+ m_Pivot: {x: 0.5, y: 0.5}
42
+ --- !u!114 &981792811258053838
43
+ MonoBehaviour:
44
+ m_ObjectHideFlags: 0
45
+ m_CorrespondingSourceObject: {fileID: 0}
46
+ m_PrefabInstance: {fileID: 0}
47
+ m_PrefabAsset: {fileID: 0}
48
+ m_GameObject: {fileID: 4256389965931995120}
49
+ m_Enabled: 1
50
+ m_EditorHideFlags: 0
51
+ m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
52
+ m_Name:
53
+ m_EditorClassIdentifier:
54
+ m_Navigation:
55
+ m_Mode: 3
56
+ m_WrapAround: 0
57
+ m_SelectOnUp: {fileID: 0}
58
+ m_SelectOnDown: {fileID: 0}
59
+ m_SelectOnLeft: {fileID: 0}
60
+ m_SelectOnRight: {fileID: 0}
61
+ m_Transition: 1
62
+ m_Colors:
63
+ m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
64
+ m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
65
+ m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
66
+ m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
67
+ m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
68
+ m_ColorMultiplier: 1
69
+ m_FadeDuration: 0.1
70
+ m_SpriteState:
71
+ m_HighlightedSprite: {fileID: 0}
72
+ m_PressedSprite: {fileID: 0}
73
+ m_SelectedSprite: {fileID: 0}
74
+ m_DisabledSprite: {fileID: 0}
75
+ m_AnimationTriggers:
76
+ m_NormalTrigger: Normal
77
+ m_HighlightedTrigger: Highlighted
78
+ m_PressedTrigger: Pressed
79
+ m_SelectedTrigger: Selected
80
+ m_DisabledTrigger: Disabled
81
+ m_Interactable: 1
82
+ m_TargetGraphic: {fileID: 2957037893780307854}
83
+ m_OnClick:
84
+ m_PersistentCalls:
85
+ m_Calls:
86
+ - m_Target: {fileID: 6086753863169534924}
87
+ m_TargetAssemblyTypeName: Amanotes.Core.GDKPrivacyButton, AmaGDK
88
+ m_MethodName: OnButtonClick
89
+ m_Mode: 1
90
+ m_Arguments:
91
+ m_ObjectArgument: {fileID: 0}
92
+ m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
93
+ m_IntArgument: 0
94
+ m_FloatArgument: 0
95
+ m_StringArgument:
96
+ m_BoolArgument: 0
97
+ m_CallState: 2
98
+ --- !u!114 &6086753863169534924
99
+ MonoBehaviour:
100
+ m_ObjectHideFlags: 0
101
+ m_CorrespondingSourceObject: {fileID: 0}
102
+ m_PrefabInstance: {fileID: 0}
103
+ m_PrefabAsset: {fileID: 0}
104
+ m_GameObject: {fileID: 4256389965931995120}
105
+ m_Enabled: 1
106
+ m_EditorHideFlags: 0
107
+ m_Script: {fileID: 11500000, guid: 23184a9779a949419e702ce599a0dcc5, type: 3}
108
+ m_Name:
109
+ m_EditorClassIdentifier:
110
+ button: {fileID: 981792811258053838}
111
+ --- !u!222 &3785844084317390329
112
+ CanvasRenderer:
113
+ m_ObjectHideFlags: 0
114
+ m_CorrespondingSourceObject: {fileID: 0}
115
+ m_PrefabInstance: {fileID: 0}
116
+ m_PrefabAsset: {fileID: 0}
117
+ m_GameObject: {fileID: 4256389965931995120}
118
+ m_CullTransparentMesh: 1
119
+ --- !u!114 &2957037893780307854
120
+ MonoBehaviour:
121
+ m_ObjectHideFlags: 0
122
+ m_CorrespondingSourceObject: {fileID: 0}
123
+ m_PrefabInstance: {fileID: 0}
124
+ m_PrefabAsset: {fileID: 0}
125
+ m_GameObject: {fileID: 4256389965931995120}
126
+ m_Enabled: 1
127
+ m_EditorHideFlags: 0
128
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
129
+ m_Name:
130
+ m_EditorClassIdentifier:
131
+ m_Material: {fileID: 0}
132
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
133
+ m_RaycastTarget: 1
134
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
135
+ m_Maskable: 1
136
+ m_OnCullStateChanged:
137
+ m_PersistentCalls:
138
+ m_Calls: []
139
+ m_Sprite: {fileID: 0}
140
+ m_Type: 0
141
+ m_PreserveAspect: 0
142
+ m_FillCenter: 1
143
+ m_FillMethod: 4
144
+ m_FillAmount: 1
145
+ m_FillClockwise: 1
146
+ m_FillOrigin: 0
147
+ m_UseSpriteMesh: 0
148
+ m_PixelsPerUnitMultiplier: 1
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: a0f053cea7e1d4184afef07fdb572024
3
+ PrefabImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: fd1abbc2a7bd48d9b0f429852b96daa9
3
+ timeCreated: 1733448490
@@ -0,0 +1,118 @@
1
+ using Amanotes.Core.Internal;
2
+ using System;
3
+
4
+ namespace Amanotes.Core
5
+ {
6
+ internal abstract class GDKTaskTrackerBase
7
+ {
8
+ protected enum GDKTaskState
9
+ {
10
+ None,
11
+ Running,
12
+ Completed,
13
+ }
14
+
15
+ protected GDKTaskState state;
16
+ public bool HasCompleted => state == GDKTaskState.Completed;
17
+ public bool HasStarted => state >= GDKTaskState.Running;
18
+
19
+ public void MarkStarted()
20
+ {
21
+ if (HasStarted)
22
+ {
23
+ GDKDebug.LogWarning("[GDKTaskTracker] Task already started");
24
+ return;
25
+ }
26
+
27
+ state = GDKTaskState.Running;
28
+ }
29
+
30
+ public virtual void Reset()
31
+ {
32
+ if (state == GDKTaskState.Running)
33
+ {
34
+ GDKDebug.LogWarning("[GDKTaskTracker] Task stop abruptly because of Reset()");
35
+ }
36
+ state = GDKTaskState.None;
37
+ }
38
+
39
+ protected bool ValidateMarkComplete()
40
+ {
41
+ if (HasCompleted)
42
+ {
43
+ GDKDebug.LogWarning("[GDKTaskTracker] Task already completed");
44
+ return false;
45
+ }
46
+
47
+ if (!HasStarted)
48
+ {
49
+ GDKDebug.LogWarning("[GDKTaskTracker] Task not yet started or been reset?");
50
+ }
51
+
52
+ state = GDKTaskState.Completed;
53
+ return true;
54
+ }
55
+ }
56
+
57
+
58
+ internal class GDKTaskTracker : GDKTaskTrackerBase
59
+ {
60
+ private Action callback;
61
+ public void RegisterOnCompleteCallback(Action onComplete)
62
+ {
63
+ if (HasCompleted)
64
+ {
65
+ onComplete?.Invoke();
66
+ }
67
+ else
68
+ {
69
+ callback -= onComplete;
70
+ callback += onComplete;
71
+ }
72
+ }
73
+
74
+ public void MarkCompleted()
75
+ {
76
+ if (!ValidateMarkComplete()) return;
77
+ GDKUtils.SafeInvokeAndClear(ref callback);
78
+ }
79
+
80
+ public override void Reset()
81
+ {
82
+ base.Reset();
83
+ callback = null;
84
+ }
85
+ }
86
+
87
+ internal class GDKTaskTracker<T> : GDKTaskTrackerBase
88
+ {
89
+ public T Result { get; private set; }
90
+ private Action<T> callback;
91
+
92
+ public void RegisterOnCompleteCallback(Action<T> onComplete)
93
+ {
94
+ if (HasCompleted)
95
+ {
96
+ onComplete?.Invoke(Result);
97
+ }
98
+ else
99
+ {
100
+ callback -= onComplete;
101
+ callback += onComplete;
102
+ }
103
+ }
104
+
105
+ public void MarkCompleted(T result)
106
+ {
107
+ if (!ValidateMarkComplete()) return;
108
+ Result = result;
109
+ GDKUtils.SafeInvokeAndClear(ref callback, Result);
110
+ }
111
+
112
+ public override void Reset()
113
+ {
114
+ base.Reset();
115
+ callback = null;
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 5c024a021cd0415bb5aace8887625c3d
3
+ timeCreated: 1733366401
@@ -14,6 +14,14 @@ namespace Amanotes.Core.Internal
14
14
  SafeInvoke(temp);
15
15
  }
16
16
 
17
+ public static void SafeInvokeAndClear<T>(ref Action<T> action, T data)
18
+ {
19
+ if (action == null) return;
20
+ Action<T> temp = action;
21
+ action = null;
22
+ SafeInvoke(temp, data);
23
+ }
24
+
17
25
  public static void SafeInvoke(Action action)
18
26
  {
19
27
  if (action == null) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.81-alpha.5",
3
+ "version": "0.2.81-alpha.6",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2019.4",
@@ -1,256 +0,0 @@
1
- using System;
2
- using Amanotes.Core.Internal;
3
- using UnityEngine;
4
- using static Amanotes.Core.GDKDebug;
5
-
6
- namespace Amanotes.Core
7
- {
8
- public partial class AmaGDK //Consent
9
- {
10
- public static partial class Consent //Public
11
- {
12
- private static bool _onGoingRequestAllConsents;
13
- public static void RequestAllConsents(Action onComplete)
14
- {
15
- OnAllConsentComplete(onComplete);
16
-
17
- if (_onGoingRequestAllConsents)
18
- {
19
- LogWarning($"[Consent] RequestAllConsents is called multiple times.");
20
- return;
21
- }
22
-
23
- _onGoingRequestAllConsents = true;
24
- #if UNITY_IOS
25
- ATT.Request(ConsiderCMP);
26
- #else
27
- CMP.Request(EndConsent);
28
- #endif
29
- }
30
-
31
- public static void OnAllConsentComplete(Action onComplete)
32
- {
33
- if (allConsentChecked)
34
- {
35
- onComplete?.Invoke();
36
- return;
37
- }
38
-
39
- _onConsentComplete -= onComplete;
40
- _onConsentComplete += onComplete;
41
- }
42
- }
43
-
44
- public static partial class Consent //ATT
45
- {
46
- public static class ATT
47
- {
48
- public static bool IsAllowed
49
- {
50
- get
51
- {
52
- if (checkedATT) return allowedATT;
53
- LogWarning("[Consent] ATT has not completed yet");
54
- return false;
55
- }
56
- }
57
-
58
- public static void Request(Action<bool> onComplete)
59
- {
60
- if (checkedATT)
61
- {
62
- onComplete?.Invoke(allowedATT);
63
- return;
64
- }
65
-
66
- ConsentHook.ATTRequest(isAllowed =>
67
- {
68
- data.att = isAllowed ? Status.Allowed : Status.NotAllowed;
69
- data.SaveJsonToFile();
70
- onComplete?.Invoke(allowedATT);
71
- });
72
- }
73
- }
74
-
75
- }
76
-
77
- public static partial class Consent //CMP
78
- {
79
- public static class CMP
80
- {
81
- public static bool IsRequired
82
- {
83
- get
84
- {
85
- if (checkedCMP) return data.cmp >= Status.Allowed;
86
-
87
- if (!ConsentHook.IsRequiredCMP.HasValue)
88
- {
89
- LogWarningOnce("[Consent] CMP is not available or not ready");
90
- return false;
91
- }
92
-
93
- return ConsentHook.IsRequiredCMP.Value;
94
- }
95
- }
96
-
97
- public static void Request(Action<bool> onComplete)
98
- {
99
- if (checkedCMP)
100
- {
101
- onComplete?.Invoke(checkedCMP);
102
- return;
103
- }
104
-
105
- ConsentHook.TryToShowCMP(successful =>
106
- {
107
- if (successful)
108
- {
109
- data.cmp = !IsRequired ? Status.NotRequired : Status.Allowed;
110
- data.SaveJsonToFile();
111
- }
112
- onComplete?.Invoke(checkedCMP);
113
- });
114
- }
115
-
116
- public static void ForceShowPopUp(Action onComplete)
117
- {
118
- OnAllConsentComplete(onComplete);
119
- ConsentHook.ForceShowCMP(EndConsent);
120
- }
121
- }
122
- }
123
-
124
- public static partial class Consent //Internal
125
- {
126
- private static readonly Lazy<ConsentData> _data = new Lazy<ConsentData>(() => new ConsentData().LoadJsonFromFile());
127
- private static ConsentData data => _data.Value;
128
- private static Action _onConsentComplete;
129
-
130
- internal static bool checkedATT => data.att >= Status.Allowed;
131
- internal static bool allowedATT => data.att == Status.Allowed;
132
- internal static bool checkedCMP => data.cmp >= Status.NotRequired;
133
- internal static bool allConsentChecked => checkedATT && checkedCMP;
134
-
135
- internal enum Status
136
- {
137
- None,
138
- NotRequired,
139
- Allowed,
140
- NotAllowed
141
- }
142
-
143
- internal static bool InitModule()
144
- {
145
- if (allConsentChecked) return true;
146
- if (!_config.autoGetConsent) return true;
147
- RequestAllConsents(null);
148
- return true;
149
- }
150
-
151
- private static void ConsiderCMP(bool needToShowCMP)
152
- {
153
- if (checkedCMP)
154
- {
155
- EndConsent(true);
156
- return;
157
- }
158
-
159
- if (needToShowCMP)
160
- {
161
- ConsentHook.TryToShowCMP(EndConsent);
162
- }
163
- else
164
- {
165
- ConsentHook.SetNotRequiredCMP(EndConsent);
166
- }
167
- }
168
-
169
- private static void EndConsent(bool isConsentSuccess)
170
- {
171
- var tmpAction = _onConsentComplete;
172
- _onConsentComplete = null;
173
- tmpAction?.Invoke();
174
- Log("[Consent] End consent checking");
175
- }
176
- }
177
- }
178
-
179
- [Serializable]
180
- public class ConsentData : IJsonFile
181
- {
182
- [SerializeField] internal AmaGDK.Consent.Status att;
183
- [SerializeField] internal AmaGDK.Consent.Status cmp;
184
- }
185
-
186
- public static class ConsentHook
187
- {
188
- public static bool? IsRequiredCMP;
189
-
190
- private static Action<Action<bool>> _tryToShowCMP;
191
- public static Action<Action<bool>> TryToShowCMP
192
- {
193
- get
194
- {
195
- if (_tryToShowCMP != null) return _tryToShowCMP;
196
-
197
- LogWarning("[Consent] ConsentHook.TryToShowCMP is null");
198
- _tryToShowCMP = callback => callback(false);
199
- return _tryToShowCMP;
200
- }
201
- set => _tryToShowCMP = value;
202
- }
203
-
204
- private static Action<Action<bool>> _forceShowCMP;
205
- public static Action<Action<bool>> ForceShowCMP
206
- {
207
- get
208
- {
209
- if (_forceShowCMP != null) return _forceShowCMP;
210
-
211
- LogWarning("[Consent] ConsentHook.ForceShowCMP is null");
212
- _forceShowCMP = callback => callback(false);
213
- return _forceShowCMP;
214
- }
215
- set => _forceShowCMP = value;
216
- }
217
-
218
- private static Action<Action<bool>> _setNotRequiredCMP;
219
- public static Action<Action<bool>> SetNotRequiredCMP
220
- {
221
- get
222
- {
223
- if (_setNotRequiredCMP != null) return _setNotRequiredCMP;
224
-
225
- LogWarning("[Consent] ConsentHook.SetNotRequiredCMP is null");
226
- _setNotRequiredCMP = callback => callback(false);
227
- return _setNotRequiredCMP;
228
- }
229
- set => _setNotRequiredCMP = value;
230
- }
231
-
232
- private static Action<Action<bool>> _attRequest;
233
- public static Action<Action<bool>> ATTRequest
234
- {
235
- get
236
- {
237
- if (_attRequest != null) return _attRequest;
238
-
239
- LogWarning("[Consent] ConsentHook.ATTRequest is null");
240
- _attRequest = callback => callback(false);
241
- return _attRequest;
242
- }
243
- set => _attRequest = value;
244
- }
245
- }
246
- }
247
-
248
- namespace Amanotes.Core.Internal
249
- {
250
- public partial class ConfigAsset
251
- {
252
- [SerializeField]
253
- [Tooltip("Auto pop-up ATT and CMP form")]
254
- public bool autoGetConsent = true;
255
- }
256
- }