✨ Make the prefetch supports typescript and opengraph.
⚡ Use prefetch in Solarpass pfp
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Solarpass</title>
|
||||
<app-data />
|
||||
<og-data />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
7
DysonNetwork.Pass/Client/src/dy-prefetch.d.ts
vendored
Normal file
7
DysonNetwork.Pass/Client/src/dy-prefetch.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export {}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
DyPrefetch?: any
|
||||
}
|
||||
}
|
@@ -46,8 +46,8 @@ import CaptchaWidget from '@/components/CaptchaWidget.vue';
|
||||
const route = useRoute();
|
||||
|
||||
// Get provider and API key from app data
|
||||
const provider = ref((window as any).__APP_DATA__?.Provider || '');
|
||||
const apiKey = ref((window as any).__APP_DATA__?.ApiKey || '');
|
||||
const provider = ref(window.DyPrefetch?.provider || '');
|
||||
const apiKey = ref(window.DyPrefetch?.api_key || '');
|
||||
|
||||
const onCaptchaVerified = (token: string) => {
|
||||
if (window.parent !== window) {
|
||||
|
@@ -116,8 +116,8 @@ const rules: FormRules = {
|
||||
}
|
||||
|
||||
// Get captcha provider and API key from global data
|
||||
const captchaProvider = ref((window as any).__APP_DATA__?.Provider || '')
|
||||
const captchaApiKey = ref((window as any).__APP_DATA__?.ApiKey || '')
|
||||
const captchaProvider = ref(window.DyPrefetch?.provider || '')
|
||||
const captchaApiKey = ref(window.DyPrefetch?.api_key || '')
|
||||
|
||||
const onCaptchaVerified = (token: string) => {
|
||||
formModel.captchaToken = token
|
||||
|
@@ -175,11 +175,9 @@ const notFound = ref<boolean>(false)
|
||||
const user = ref<any>(null)
|
||||
|
||||
async function fetchUser() {
|
||||
// @ts-ignore
|
||||
if (window.__APP_DATA__?.Account != null) {
|
||||
if (window.DyPrefetch?.Account != null) {
|
||||
console.log('[Fetch] Use the pre-rendered account data.')
|
||||
// @ts-ignore
|
||||
user.value = window.__APP_DATA__['Account']
|
||||
user.value = window.DyPrefetch.Account
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0"/>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" Version="9.0.4"/>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="9.0.4"/>
|
||||
<PackageReference Include="OpenGraph-Net" Version="4.0.1" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0"/>
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0"/>
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0"/>
|
||||
|
52
DysonNetwork.Pass/Pages/Data/AccountPageData.cs
Normal file
52
DysonNetwork.Pass/Pages/Data/AccountPageData.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Net;
|
||||
using DysonNetwork.Pass.Wallet;
|
||||
using DysonNetwork.Shared.PageData;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using OpenGraphNet;
|
||||
|
||||
namespace DysonNetwork.Pass.Pages.Data;
|
||||
|
||||
public class AccountPageData(AppDatabase db, SubscriptionService subscriptions, IConfiguration configuration)
|
||||
: IPageDataProvider
|
||||
{
|
||||
private readonly string _siteUrl = configuration["SiteUrl"]!;
|
||||
|
||||
public bool CanHandlePath(PathString path) =>
|
||||
path.StartsWithSegments("/accounts") || path.ToString().StartsWith("/@");
|
||||
|
||||
public async Task<IDictionary<string, object?>> GetAppDataAsync(HttpContext context)
|
||||
{
|
||||
var path = context.Request.Path.Value!;
|
||||
var startIndex = path.StartsWith("/accounts/") ? "/accounts/".Length : "/@".Length;
|
||||
var endIndex = path.IndexOf('/', startIndex);
|
||||
var username = endIndex == -1 ? path[startIndex..] : path.Substring(startIndex, endIndex - startIndex);
|
||||
username = WebUtility.UrlDecode(username);
|
||||
if (username.StartsWith("@"))
|
||||
username = username[1..];
|
||||
|
||||
var account = await db.Accounts
|
||||
.Include(e => e.Badges)
|
||||
.Include(e => e.Profile)
|
||||
.Where(a => a.Name == username)
|
||||
.FirstOrDefaultAsync();
|
||||
if (account is null) return new Dictionary<string, object?>();
|
||||
|
||||
var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
|
||||
account.PerkSubscription = perk?.ToReference();
|
||||
|
||||
var og = OpenGraph.MakeGraph(
|
||||
title: account.Nick,
|
||||
type: "profile",
|
||||
image: $"{_siteUrl}/cgi/drive/files/{account.Profile.Picture?.Id}?original=true",
|
||||
url: $"{_siteUrl}/@{username}",
|
||||
description: account.Profile.Bio ?? $"@{account.Name} profile on the Solar Network",
|
||||
siteName: "Solarpass"
|
||||
);
|
||||
|
||||
return new Dictionary<string, object?>()
|
||||
{
|
||||
["Account"] = account,
|
||||
["OpenGraph"] = og
|
||||
};
|
||||
}
|
||||
}
|
@@ -34,6 +34,7 @@ builder.Services.AddAppScheduledJobs();
|
||||
|
||||
builder.Services.AddTransient<IPageDataProvider, VersionPageData>();
|
||||
builder.Services.AddTransient<IPageDataProvider, CaptchaPageData>();
|
||||
builder.Services.AddTransient<IPageDataProvider, AccountPageData>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"Debug": true,
|
||||
"BaseUrl": "http://localhost:5216",
|
||||
"SiteUrl": "https://id.solian.app",
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
|
@@ -26,6 +26,7 @@
|
||||
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.2.0" />
|
||||
<PackageReference Include="NodaTime.Serialization.Protobuf" Version="2.0.2" />
|
||||
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0" />
|
||||
<PackageReference Include="OpenGraph-Net" Version="4.0.1" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.8.41" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="Yarp.ReverseProxy" Version="2.3.0" />
|
||||
|
@@ -3,6 +3,9 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NodaTime;
|
||||
using NodaTime.Serialization.SystemTextJson;
|
||||
using OpenGraphNet;
|
||||
|
||||
namespace DysonNetwork.Shared.PageData;
|
||||
|
||||
@@ -24,6 +27,13 @@ public static class PageStartup
|
||||
/// <returns></returns>
|
||||
public static WebApplication MapPages(this WebApplication app, string defaultFile)
|
||||
{
|
||||
var jsonOpts = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
}.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
|
||||
|
||||
#pragma warning disable ASP0016
|
||||
app.MapFallback(async context =>
|
||||
{
|
||||
@@ -33,7 +43,7 @@ public static class PageStartup
|
||||
await context.Response.WriteAsync("Not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var html = await File.ReadAllTextAsync(defaultFile);
|
||||
|
||||
using var scope = app.Services.CreateScope();
|
||||
@@ -50,8 +60,15 @@ public static class PageStartup
|
||||
foreach (var (key, value) in result)
|
||||
appData[key] = value;
|
||||
|
||||
var json = JsonSerializer.Serialize(appData);
|
||||
html = html.Replace("<app-data />", $"<script>window.__APP_DATA__ = {json};</script>");
|
||||
OpenGraph? og = null;
|
||||
if (appData.TryGetValue("OpenGraph", out var openGraph) && openGraph is OpenGraph gog)
|
||||
og = gog;
|
||||
|
||||
var json = JsonSerializer.Serialize(appData, jsonOpts);
|
||||
html = html.Replace("<app-data />", $"<script>window.DyPrefetch = {json};</script>");
|
||||
|
||||
if (og is not null)
|
||||
html = html.Replace("<og-data />", og.ToString());
|
||||
|
||||
context.Response.ContentType = "text/html";
|
||||
await context.Response.WriteAsync(html);
|
||||
|
Reference in New Issue
Block a user