fixes, improvements. firebase

This commit is contained in:
Savya Bikram Shah
2026-06-01 13:15:40 +05:45
parent 384176fdcc
commit 6f79bcd018
180 changed files with 25324 additions and 9393 deletions

View File

@@ -151,7 +151,7 @@ namespace Darkmatter.Features.Artbook
{
if (!entry.HasValue || entry.Value.Thumbnail == null) return;
var ct = _cts?.Token ?? CancellationToken.None;
await _gallery.SaveImageAsync(entry.Value.Thumbnail, entry.Value.Id, ct);
await _gallery.SaveImageAsync(entry.Value.Thumbnail, entry.Value.Name, ct);
}
private void HandleLeftEditClicked() => OpenForEdit(GetLeftEntry());

View File

@@ -1,8 +1,9 @@
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Features.Capture;
using Darkmatter.Core.Contracts.Features.DrawingCatalog;
using Darkmatter.Core.Contracts.Features.GameplayFlow;
using Darkmatter.Core.Contracts.Features.Progression;
using Darkmatter.Core.Contracts.Services.Capture;
using Darkmatter.Core.Contracts.Services.Gallery;
using Darkmatter.Core.Data.Signals.Features.Capture;
@@ -18,19 +19,25 @@ namespace Darkmatter.Features.Capture
private readonly IGameplaySceneRefs _refs;
private readonly IEventBus _bus;
private readonly CaptureConfig _config;
private readonly IProgressionSystem _progression;
private readonly IDrawingTemplateCatalog _catalog;
public CaptureSystem(
ICaptureService captureService,
IGalleryService galleryService,
IGameplaySceneRefs refs,
IEventBus bus,
CaptureConfig config)
CaptureConfig config,
IProgressionSystem progression,
IDrawingTemplateCatalog catalog)
{
_captureService = captureService;
_galleryService = galleryService;
_refs = refs;
_bus = bus;
_config = config;
_progression = progression;
_catalog = catalog;
}
public async UniTask<byte[]> CapturePngAsync(bool saveToGallery = false, CancellationToken ct = default)
@@ -44,9 +51,9 @@ namespace Darkmatter.Features.Capture
{
if (tex.LoadImage(png))
{
var fileName = await BuildFileNameAsync();
_bus.Publish(new GallerySaveStartedSignal());
await _galleryService.SaveImageAsync(tex,
$"colorbook_{DateTime.UtcNow:yyyyMMdd_HHmmss}.png", ct);
await _galleryService.SaveImageAsync(tex, fileName, ct);
success = true;
}
}
@@ -57,5 +64,20 @@ namespace Darkmatter.Features.Capture
}
return png;
}
private async UniTask<string> BuildFileNameAsync()
{
var id = _progression.LastOpenedTemplateId;
if (string.IsNullOrEmpty(id)) return null;
try
{
var template = await _catalog.LoadAsync(id);
return template?.DisplayName;
}
catch
{
return null;
}
}
}
}

View File

@@ -2,12 +2,9 @@ using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Darkmatter.Core;
using Darkmatter.Core.Contracts.Features.DrawingCatalog;
using Darkmatter.Core.Contracts.Features.Progression;
using Darkmatter.Core.Data.Signals.Features.Drawing;
using Darkmatter.Libs.Observer;
using ZLinq;
namespace Darkmatter.Features.DrawingCatalog.Systems;
@@ -15,7 +12,6 @@ public sealed class DrawingCatalogController : IDrawingCatalogController
{
private readonly IDrawingTemplateCatalog _catalog;
private readonly IEventBus _bus;
private readonly IProgressionSystem _progression;
private readonly List<string> _visible = new();
public IReadOnlyList<string> VisibleIds => _visible;
@@ -23,11 +19,9 @@ public sealed class DrawingCatalogController : IDrawingCatalogController
public DrawingCatalogController(
IDrawingTemplateCatalog catalog,
IProgressionSystem progression,
IEventBus bus)
{
_catalog = catalog;
_progression = progression;
_bus = bus;
}
@@ -45,13 +39,8 @@ public sealed class DrawingCatalogController : IDrawingCatalogController
private void Refresh()
{
_visible.Clear();
var all = _catalog.AllTemplateIds;
foreach (var id in all)
if (!_progression.CompletedTemplateIds.AsValueEnumerable().Contains(id))
_visible.Add(id);
foreach (var id in all)
if (_progression.CompletedTemplateIds.AsValueEnumerable().Contains(id))
_visible.Add(id);
_visible.AddRange(_catalog.AllTemplateIds);
_visible.Sort(StringComparer.OrdinalIgnoreCase);
ListChanged?.Invoke();
}
}

View File

@@ -0,0 +1,19 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Darkmatter.Libs.UnityUtils.Editor
{
public static class OpenEditorGalleryMenu
{
private const string MenuPath = "Tools/Colorbook/Open Editor Gallery";
[MenuItem(MenuPath)]
private static void Open()
{
var dir = Path.Combine(Application.persistentDataPath, "Colorbook-Gallery");
Directory.CreateDirectory(dir);
EditorUtility.RevealInFinder(dir);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 55aad6d59cbf04999877c8c4b2f55836

View File

@@ -21,6 +21,8 @@ namespace Darkmatter.Services.Ads
[SerializeField] private bool autoReload = true;
[Tooltip("Seconds between auto-reload retries on failure.")]
[SerializeField, Min(1f)] private float reloadDelaySeconds = 5f;
[Tooltip("Max reload attempts before giving up.")]
[SerializeField, Min(1)] private int reloadMaxAttempts = 6;
public bool IsInitialized => _initialized;
public event Action<AdFormat, AdLoadState> LoadStateChanged;
@@ -495,8 +497,14 @@ namespace Darkmatter.Services.Ads
{
try
{
await UniTask.Delay(TimeSpan.FromSeconds(reloadDelaySeconds), cancellationToken: cancellationToken);
await LoadAsync(format, cancellationToken);
for (int attempt = 0; attempt < reloadMaxAttempts; attempt++)
{
await UniTask.Delay(TimeSpan.FromSeconds(reloadDelaySeconds), cancellationToken: cancellationToken);
if (cancellationToken.IsCancellationRequested) return;
if (IsReady(format)) return;
if (await LoadAsync(format, cancellationToken)) return;
}
Debug.LogWarning($"[AdMobAdService] {format} reload gave up after {reloadMaxAttempts} attempts.");
}
catch (OperationCanceledException) { }
}

View File

@@ -9,9 +9,7 @@ namespace Darkmatter.Services.Analytics
{
public void Register(IContainerBuilder builder)
{
#if FIREBASE_ANALYTICS_PRESENT
builder.RegisterEntryPoint<FirebaseAnalyticsSystem>();
#endif
}
}
}

View File

@@ -1,4 +1,3 @@
#if FIREBASE_ANALYTICS
using System.Threading;
using Cysharp.Threading.Tasks;
using Firebase.Crashlytics;
@@ -10,7 +9,6 @@ namespace Darkmatter.Services.Analytics
{
public async UniTask StartAsync(CancellationToken cancellation = new CancellationToken())
{
#if !UNITY_EDITOR
await Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
var dependencyStatus = task.Result;
@@ -39,8 +37,6 @@ namespace Darkmatter.Services.Analytics
// Firebase Unity SDK is not safe to use here.
}
}, cancellation);
#endif
}
}
}
#endif
}

View File

@@ -0,0 +1,16 @@
using System;
using UnityEngine;
namespace Darkmatter.Services.Gallery
{
[Serializable]
public struct GalleryConfig
{
public Texture2D Background { get; }
public GalleryConfig(Texture2D background)
{
Background = background;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bf2070de4e452444fa248a03c10928a6

View File

@@ -1,4 +1,6 @@
using System;
using System.IO;
using System.Text;
using System.Threading;
using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Services.Gallery;
@@ -8,36 +10,123 @@ namespace Darkmatter.Services.Gallery
{
public class GalleryService : IGalleryService
{
private readonly GalleryConfig _config;
public GalleryService(GalleryConfig config) => _config = config;
public async UniTask SaveImageAsync(Texture2D image, string fileName, CancellationToken cancellationToken)
{
var permission = await NativeGallery.RequestPermissionAsync(NativeGallery.PermissionType.Write,
NativeGallery.MediaType.Image);
if (permission != NativeGallery.Permission.Granted)
Texture2D composited = null;
Texture2D toSave = image;
if (_config.Background != null)
{
return;
composited = CompositeOverBackground(image, _config.Background);
toSave = composited;
}
var tcs = new UniTaskCompletionSource();
var registration = cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));
var resolvedName = BuildUniqueFileName(fileName);
NativeGallery.SaveImageToGallery(image, "Colorbook",
filename: $"colorbook_{DateTime.UtcNow:yyyyMMdd_HHmmss}.png", callback: (success, path) =>
try
{
#if UNITY_EDITOR
var bytes = toSave.EncodeToPNG();
var dir = Path.Combine(Application.persistentDataPath, "Colorbook-Gallery");
Directory.CreateDirectory(dir);
var path = Path.Combine(dir, resolvedName);
await File.WriteAllBytesAsync(path, bytes, cancellationToken);
Debug.Log($"[GalleryService] (Editor) Image saved to: {path}");
#else
var permission = await NativeGallery.RequestPermissionAsync(NativeGallery.PermissionType.Write,
NativeGallery.MediaType.Image);
if (permission != NativeGallery.Permission.Granted)
{
registration.Dispose();
if (!success)
{
Debug.LogError("Failed to save image to gallery.");
}
else
{
Debug.Log($"Image saved to gallery at: {path}");
}
return;
}
tcs.TrySetResult();
});
var tcs = new UniTaskCompletionSource();
var registration = cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));
await tcs.Task;
NativeGallery.SaveImageToGallery(toSave, "Colorbook",
filename: resolvedName, callback: (success, path) =>
{
registration.Dispose();
if (!success)
{
Debug.LogError("Failed to save image to gallery.");
}
else
{
Debug.Log($"Image saved to gallery at: {path}");
}
tcs.TrySetResult();
});
await tcs.Task;
#endif
}
finally
{
if (composited != null) UnityEngine.Object.Destroy(composited);
}
}
private static string BuildUniqueFileName(string baseName)
{
var prefix = Sanitize(baseName);
if (string.IsNullOrEmpty(prefix)) prefix = "drawing";
return $"{prefix}_{DateTime.UtcNow:yyyyMMdd_HHmmssfff}.png";
}
private static string Sanitize(string s)
{
if (string.IsNullOrEmpty(s)) return null;
var name = Path.GetFileNameWithoutExtension(s).Trim();
var sb = new StringBuilder(name.Length);
foreach (var c in name)
{
if (char.IsLetterOrDigit(c)) sb.Append(c);
else if (c == ' ' || c == '-' || c == '_') sb.Append('_');
}
return sb.Length == 0 ? null : sb.ToString();
}
private static Texture2D CompositeOverBackground(Texture2D captured, Texture2D background)
{
int bgW = background.width;
int bgH = background.height;
int cW = captured.width;
int cH = captured.height;
float fit = Mathf.Min(1f, Mathf.Min((float)bgW / cW, (float)bgH / cH));
int finalW = Mathf.Max(1, Mathf.RoundToInt(cW * fit));
int finalH = Mathf.Max(1, Mathf.RoundToInt(cH * fit));
int offsetX = (bgW - finalW) / 2;
int offsetY = (bgH - finalH) / 2;
var rt = RenderTexture.GetTemporary(bgW, bgH, 0, RenderTextureFormat.ARGB32);
var prev = RenderTexture.active;
try
{
Graphics.Blit(background, rt);
RenderTexture.active = rt;
GL.PushMatrix();
GL.LoadPixelMatrix(0, bgW, bgH, 0);
Graphics.DrawTexture(new Rect(offsetX, offsetY, finalW, finalH), captured);
GL.PopMatrix();
var output = new Texture2D(bgW, bgH, TextureFormat.RGBA32, mipChain: false);
output.ReadPixels(new Rect(0, 0, bgW, bgH), 0, 0);
output.Apply();
return output;
}
finally
{
RenderTexture.active = prev;
RenderTexture.ReleaseTemporary(rt);
}
}
}
}
}

View File

@@ -7,8 +7,11 @@ namespace Darkmatter.Services.Gallery
{
public class GalleryModule : MonoBehaviour,IModule
{
[SerializeField] private Texture2D saveBackground;
public void Register(IContainerBuilder builder)
{
builder.RegisterInstance(new GalleryConfig(saveBackground));
builder.Register<IGalleryService,GalleryService>(Lifetime.Singleton);
}
}