Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions Contentstack.Core/ContentstackClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,88 @@
private string currentContenttypeUid = null;
private string currentEntryUid = null;
public List<IContentstackPlugin> Plugins { get; set; } = new List<IContentstackPlugin>();

private static LivePreviewConfig CloneLivePreviewConfig(LivePreviewConfig source)
{
if (source == null) return null;

return new LivePreviewConfig
{
Enable = source.Enable,
Host = source.Host,
ManagementToken = source.ManagementToken,
PreviewToken = source.PreviewToken,
ReleaseId = source.ReleaseId,
PreviewTimestamp = source.PreviewTimestamp,

// internal state (same assembly)
LivePreview = source.LivePreview,
ContentTypeUID = source.ContentTypeUID,
EntryUID = source.EntryUID,
PreviewResponse = source.PreviewResponse
};
}

private static ContentstackOptions CloneOptions(ContentstackOptions source)
{
if (source == null) return null;

return new ContentstackOptions
{
ApiKey = source.ApiKey,
AccessToken = source.AccessToken,

Check warning on line 93 in Contentstack.Core/ContentstackClient.cs

View workflow job for this annotation

GitHub Actions / unit-test

'ContentstackOptions.AccessToken' is obsolete: 'We have deprecated AccessToken and we will stop supporting it in the near future. We strongly recommend using DeliveryToken.'

Check warning on line 93 in Contentstack.Core/ContentstackClient.cs

View workflow job for this annotation

GitHub Actions / unit-test

'ContentstackOptions.AccessToken' is obsolete: 'We have deprecated AccessToken and we will stop supporting it in the near future. We strongly recommend using DeliveryToken.'

Check warning on line 93 in Contentstack.Core/ContentstackClient.cs

View workflow job for this annotation

GitHub Actions / unit-test

'ContentstackOptions.AccessToken' is obsolete: 'We have deprecated AccessToken and we will stop supporting it in the near future. We strongly recommend using DeliveryToken.'

Check warning on line 93 in Contentstack.Core/ContentstackClient.cs

View workflow job for this annotation

GitHub Actions / unit-test

'ContentstackOptions.AccessToken' is obsolete: 'We have deprecated AccessToken and we will stop supporting it in the near future. We strongly recommend using DeliveryToken.'
DeliveryToken = source.DeliveryToken,
Environment = source.Environment,
Host = source.Host,
Proxy = source.Proxy,
Region = source.Region,
Version = source.Version,
Branch = source.Branch,
Timeout = source.Timeout,
EarlyAccessHeader = source.EarlyAccessHeader,
LivePreview = CloneLivePreviewConfig(source.LivePreview)
};
}

/// <summary>
/// Clears any in-memory Live Preview context (hash, release, timestamp, content type, entry).
/// Useful when switching back to the Delivery API after using Live Preview / Timeline preview.
/// </summary>
public void ResetLivePreview()
{
if (this.LivePreviewConfig == null) return;

this.LivePreviewConfig.LivePreview = null;
this.LivePreviewConfig.ReleaseId = null;
this.LivePreviewConfig.PreviewTimestamp = null;
this.LivePreviewConfig.ContentTypeUID = null;
this.LivePreviewConfig.EntryUID = null;
this.LivePreviewConfig.PreviewResponse = null;
}

/// <summary>
/// Creates a new client instance with the same configuration but isolated in-memory state.
/// Use this to safely perform Timeline comparisons (left/right) without shared Live Preview context.
/// </summary>
public ContentstackClient Fork()
{
var forked = new ContentstackClient(CloneOptions(_options));

// Preserve any runtime header mutations (e.g., custom headers added via SetHeader).
if (this._LocalHeaders != null)
{
foreach (var kvp in this._LocalHeaders)
{
forked.SetHeader(kvp.Key, kvp.Value?.ToString());
}
}

// Carry over current content type / entry hints (used when live preview query omits them)
forked.currentContenttypeUid = this.currentContenttypeUid;
forked.currentEntryUid = this.currentEntryUid;

return forked;
}
/// <summary>
/// Initializes a instance of the <see cref="ContentstackClient"/> class.
/// </summary>
Expand Down
41 changes: 28 additions & 13 deletions Contentstack.Core/Models/Entry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,39 +1401,54 @@ public async Task<T> Fetch<T>()

//Dictionary<string, object> urlQueries = new Dictionary<string, object>();

var livePreviewConfig = this.ContentTypeInstance?.StackInstance?.LivePreviewConfig;
if (headers != null && headers.Count() > 0)
{
foreach (var header in headers)
{
if (this.ContentTypeInstance.StackInstance.LivePreviewConfig.Enable == true
&& this.ContentTypeInstance.StackInstance.LivePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId
&& header.Key == "access_token" && !string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview))
if (this.ContentTypeInstance != null
&& livePreviewConfig != null
&& livePreviewConfig.Enable
&& livePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId
&& header.Key == "access_token"
&& !string.IsNullOrEmpty(livePreviewConfig.LivePreview))
{
continue;
}
headerAll.Add(header.Key, (String)header.Value);
}
}
bool isLivePreview = false;
if (this.ContentTypeInstance.StackInstance.LivePreviewConfig.Enable == true && this.ContentTypeInstance.StackInstance.LivePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId)
var hasLivePreviewContext =
this.ContentTypeInstance != null
&& livePreviewConfig != null
&& livePreviewConfig.Enable
&& livePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId
&& (
!string.IsNullOrEmpty(livePreviewConfig.LivePreview)
|| !string.IsNullOrEmpty(livePreviewConfig.ReleaseId)
|| !string.IsNullOrEmpty(livePreviewConfig.PreviewTimestamp)
);

if (hasLivePreviewContext)
{
mainJson.Add("live_preview", string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview)? "init" : this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview);
mainJson.Add("live_preview", string.IsNullOrEmpty(livePreviewConfig.LivePreview)? "init" : livePreviewConfig.LivePreview);

if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.ManagementToken)) {
headerAll["authorization"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.ManagementToken;
} else if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewToken)) {
headerAll["preview_token"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewToken;
if (!string.IsNullOrEmpty(livePreviewConfig.ManagementToken)) {
headerAll["authorization"] = livePreviewConfig.ManagementToken;
} else if (!string.IsNullOrEmpty(livePreviewConfig.PreviewToken)) {
headerAll["preview_token"] = livePreviewConfig.PreviewToken;
} else {
throw new LivePreviewException();
}

if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.ReleaseId))
if (!string.IsNullOrEmpty(livePreviewConfig.ReleaseId))
{
headerAll["release_id"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.ReleaseId;
headerAll["release_id"] = livePreviewConfig.ReleaseId;
}
if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewTimestamp))
if (!string.IsNullOrEmpty(livePreviewConfig.PreviewTimestamp))
{
headerAll["preview_timestamp"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewTimestamp;
headerAll["preview_timestamp"] = livePreviewConfig.PreviewTimestamp;
}

isLivePreview = true;
Expand Down
44 changes: 28 additions & 16 deletions Contentstack.Core/Models/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1874,26 +1874,37 @@ private async Task<JObject> Exec()
Dictionary<string, object> mainJson = new Dictionary<string, object>();

bool isLivePreview = false;
if (this.ContentTypeInstance!=null && this.ContentTypeInstance.StackInstance.LivePreviewConfig.Enable == true
&& this.ContentTypeInstance.StackInstance?.LivePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId)
{
mainJson.Add("live_preview", string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview) ? "init" : this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview);

if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.ManagementToken)) {
headerAll["authorization"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.ManagementToken;
} else if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewToken)) {
headerAll["preview_token"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewToken;
var livePreviewConfig = this.ContentTypeInstance?.StackInstance?.LivePreviewConfig;
var hasLivePreviewContext =
this.ContentTypeInstance != null
&& livePreviewConfig != null
&& livePreviewConfig.Enable
&& livePreviewConfig.ContentTypeUID == this.ContentTypeInstance.ContentTypeId
&& (
!string.IsNullOrEmpty(livePreviewConfig.LivePreview)
|| !string.IsNullOrEmpty(livePreviewConfig.ReleaseId)
|| !string.IsNullOrEmpty(livePreviewConfig.PreviewTimestamp)
);

if (hasLivePreviewContext)
{
mainJson.Add("live_preview", string.IsNullOrEmpty(livePreviewConfig.LivePreview) ? "init" : livePreviewConfig.LivePreview);

if (!string.IsNullOrEmpty(livePreviewConfig.ManagementToken)) {
headerAll["authorization"] = livePreviewConfig.ManagementToken;
} else if (!string.IsNullOrEmpty(livePreviewConfig.PreviewToken)) {
headerAll["preview_token"] = livePreviewConfig.PreviewToken;
} else {
throw new LivePreviewException();
}

if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.ReleaseId))
if (!string.IsNullOrEmpty(livePreviewConfig.ReleaseId))
{
headerAll["release_id"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.ReleaseId;
headerAll["release_id"] = livePreviewConfig.ReleaseId;
}
if (!string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewTimestamp))
if (!string.IsNullOrEmpty(livePreviewConfig.PreviewTimestamp))
{
headerAll["preview_timestamp"] = this.ContentTypeInstance.StackInstance.LivePreviewConfig.PreviewTimestamp;
headerAll["preview_timestamp"] = livePreviewConfig.PreviewTimestamp;
}

isLivePreview = true;
Expand All @@ -1903,10 +1914,11 @@ private async Task<JObject> Exec()
{
foreach (var header in headers)
{
if (this.ContentTypeInstance!=null && this.ContentTypeInstance?.StackInstance.LivePreviewConfig.Enable == true
&& this.ContentTypeInstance?.StackInstance.LivePreviewConfig.ContentTypeUID == this.ContentTypeInstance?.ContentTypeId
if (this.ContentTypeInstance!=null && livePreviewConfig != null
&& livePreviewConfig.Enable
&& livePreviewConfig.ContentTypeUID == this.ContentTypeInstance?.ContentTypeId
&& header.Key == "access_token"
&& !string.IsNullOrEmpty(this.ContentTypeInstance.StackInstance.LivePreviewConfig.LivePreview))
&& !string.IsNullOrEmpty(livePreviewConfig.LivePreview))
{
continue;
}
Expand Down
Loading