summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/SMAPI.Web/Controllers/IndexController.cs93
-rw-r--r--src/SMAPI.Web/Controllers/LogParserController.cs11
-rw-r--r--src/SMAPI.Web/Framework/Clients/GitHub/GitAsset.cs20
-rw-r--r--src/SMAPI.Web/Framework/Clients/GitHub/GitRelease.cs6
-rw-r--r--src/SMAPI.Web/Framework/ConfigModels/ContextConfig.cs15
-rw-r--r--src/SMAPI.Web/Framework/ConfigModels/LogParserConfig.cs12
-rw-r--r--src/SMAPI.Web/Properties/launchSettings.json2
-rw-r--r--src/SMAPI.Web/StardewModdingAPI.Web.csproj1
-rw-r--r--src/SMAPI.Web/Startup.cs3
-rw-r--r--src/SMAPI.Web/ViewModels/IndexModel.cs41
-rw-r--r--src/SMAPI.Web/Views/Index/Index.cshtml62
-rw-r--r--src/SMAPI.Web/Views/Shared/_Layout.cshtml10
-rw-r--r--src/SMAPI.Web/appsettings.Development.json7
-rw-r--r--src/SMAPI.Web/appsettings.json7
-rw-r--r--src/SMAPI.Web/wwwroot/Content/css/index.css58
15 files changed, 318 insertions, 30 deletions
diff --git a/src/SMAPI.Web/Controllers/IndexController.cs b/src/SMAPI.Web/Controllers/IndexController.cs
new file mode 100644
index 00000000..5d45118f
--- /dev/null
+++ b/src/SMAPI.Web/Controllers/IndexController.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Caching.Memory;
+using StardewModdingAPI.Web.Framework.Clients.GitHub;
+using StardewModdingAPI.Web.ViewModels;
+
+namespace StardewModdingAPI.Web.Controllers
+{
+ /// <summary>Provides an info/download page about SMAPI.</summary>
+ [Route("")]
+ [Route("install")]
+ internal class IndexController : Controller
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>The cache in which to store release data.</summary>
+ private readonly IMemoryCache Cache;
+
+ /// <summary>The GitHub API client.</summary>
+ private readonly IGitHubClient GitHub;
+
+ /// <summary>The cache time for release info.</summary>
+ private readonly TimeSpan CacheTime = TimeSpan.FromMinutes(5);
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="cache">The cache in which to store release data.</param>
+ /// <param name="github">The GitHub API client.</param>
+ public IndexController(IMemoryCache cache, IGitHubClient github)
+ {
+ this.Cache = cache;
+ this.GitHub = github;
+ }
+
+ /// <summary>Display the index page.</summary>
+ [HttpGet]
+ public async Task<ViewResult> Index()
+ {
+ // fetch latest SMAPI release
+ GitRelease release = await this.Cache.GetOrCreateAsync("latest-smapi-release", async entry =>
+ {
+ entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);
+ return await this.GitHub.GetLatestReleaseAsync("Pathoschild/SMAPI");
+ });
+ string downloadUrl = this.GetMainDownloadUrl(release);
+ string devDownloadUrl = this.GetDevDownloadUrl(release);
+
+ // render view
+ var model = new IndexModel(release.Name, release.Body, downloadUrl, devDownloadUrl);
+ return this.View(model);
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Get the main download URL for a SMAPI release.</summary>
+ /// <param name="release">The SMAPI release.</param>
+ private string GetMainDownloadUrl(GitRelease release)
+ {
+ // get main download URL
+ foreach (GitAsset asset in release.Assets ?? new GitAsset[0])
+ {
+ if (Regex.IsMatch(asset.FileName, @"SMAPI-[\d\.]+-installer.zip"))
+ return asset.DownloadUrl;
+ }
+
+ // fallback just in case
+ return "https://github.com/pathoschild/SMAPI/releases";
+ }
+
+ /// <summary>Get the for-developers download URL for a SMAPI release.</summary>
+ /// <param name="release">The SMAPI release.</param>
+ private string GetDevDownloadUrl(GitRelease release)
+ {
+ // get dev download URL
+ foreach (GitAsset asset in release.Assets ?? new GitAsset[0])
+ {
+ if (Regex.IsMatch(asset.FileName, @"SMAPI-[\d\.]+-installer-for-developers.zip"))
+ return asset.DownloadUrl;
+ }
+
+ // fallback just in case
+ return "https://github.com/pathoschild/SMAPI/releases";
+ }
+ }
+}
diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs
index b9227a2f..04a11a82 100644
--- a/src/SMAPI.Web/Controllers/LogParserController.cs
+++ b/src/SMAPI.Web/Controllers/LogParserController.cs
@@ -19,7 +19,7 @@ namespace StardewModdingAPI.Web.Controllers
** Properties
*********/
/// <summary>The log parser config settings.</summary>
- private readonly LogParserConfig Config;
+ private readonly ContextConfig Config;
/// <summary>The underlying Pastebin client.</summary>
private readonly IPastebinClient Pastebin;
@@ -36,11 +36,11 @@ namespace StardewModdingAPI.Web.Controllers
** Constructor
***/
/// <summary>Construct an instance.</summary>
- /// <param name="configProvider">The log parser config settings.</param>
+ /// <param name="contextProvider">The context config settings.</param>
/// <param name="pastebin">The Pastebin API client.</param>
- public LogParserController(IOptions<LogParserConfig> configProvider, IPastebinClient pastebin)
+ public LogParserController(IOptions<ContextConfig> contextProvider, IPastebinClient pastebin)
{
- this.Config = configProvider.Value;
+ this.Config = contextProvider.Value;
this.Pastebin = pastebin;
}
@@ -50,12 +50,11 @@ namespace StardewModdingAPI.Web.Controllers
/// <summary>Render the log parser UI.</summary>
/// <param name="id">The paste ID.</param>
[HttpGet]
- [Route("")]
[Route("log")]
[Route("log/{id}")]
public ViewResult Index(string id = null)
{
- return this.View("Index", new LogParserModel(this.Config.SectionUrl, id));
+ return this.View("Index", new LogParserModel(this.Config.LogParserUrl, id));
}
/***
diff --git a/src/SMAPI.Web/Framework/Clients/GitHub/GitAsset.cs b/src/SMAPI.Web/Framework/Clients/GitHub/GitAsset.cs
new file mode 100644
index 00000000..73ce4025
--- /dev/null
+++ b/src/SMAPI.Web/Framework/Clients/GitHub/GitAsset.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+
+namespace StardewModdingAPI.Web.Framework.Clients.GitHub
+{
+ /// <summary>A GitHub download attached to a release.</summary>
+ internal class GitAsset
+ {
+ /// <summary>The file name.</summary>
+ [JsonProperty("name")]
+ public string FileName { get; set; }
+
+ /// <summary>The file content type.</summary>
+ [JsonProperty("content_type")]
+ public string ContentType { get; set; }
+
+ /// <summary>The download URL.</summary>
+ [JsonProperty("browser_download_url")]
+ public string DownloadUrl { get; set; }
+ }
+}
diff --git a/src/SMAPI.Web/Framework/Clients/GitHub/GitRelease.cs b/src/SMAPI.Web/Framework/Clients/GitHub/GitRelease.cs
index 0a47f3b4..b944088d 100644
--- a/src/SMAPI.Web/Framework/Clients/GitHub/GitRelease.cs
+++ b/src/SMAPI.Web/Framework/Clients/GitHub/GitRelease.cs
@@ -15,5 +15,11 @@ namespace StardewModdingAPI.Web.Framework.Clients.GitHub
/// <summary>The semantic version string.</summary>
[JsonProperty("tag_name")]
public string Tag { get; set; }
+
+ /// <summary>The Markdown description for the release.</summary>
+ public string Body { get; set; }
+
+ /// <summary>The attached files.</summary>
+ public GitAsset[] Assets { get; set; }
}
}
diff --git a/src/SMAPI.Web/Framework/ConfigModels/ContextConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/ContextConfig.cs
new file mode 100644
index 00000000..117462f4
--- /dev/null
+++ b/src/SMAPI.Web/Framework/ConfigModels/ContextConfig.cs
@@ -0,0 +1,15 @@
+namespace StardewModdingAPI.Web.Framework.ConfigModels
+{
+ /// <summary>The config settings for the app context.</summary>
+ public class ContextConfig // must be public to pass into views
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The root URL for the app.</summary>
+ public string RootUrl { get; set; }
+
+ /// <summary>The root URL for the log parser.</summary>
+ public string LogParserUrl { get; set; }
+ }
+}
diff --git a/src/SMAPI.Web/Framework/ConfigModels/LogParserConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/LogParserConfig.cs
deleted file mode 100644
index 198274b2..00000000
--- a/src/SMAPI.Web/Framework/ConfigModels/LogParserConfig.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace StardewModdingAPI.Web.Framework.ConfigModels
-{
- /// <summary>The config settings for the log parser.</summary>
- internal class LogParserConfig
- {
- /*********
- ** Accessors
- *********/
- /// <summary>The root URL for the log parser controller.</summary>
- public string SectionUrl { get; set; }
- }
-}
diff --git a/src/SMAPI.Web/Properties/launchSettings.json b/src/SMAPI.Web/Properties/launchSettings.json
index e485e4e3..88179044 100644
--- a/src/SMAPI.Web/Properties/launchSettings.json
+++ b/src/SMAPI.Web/Properties/launchSettings.json
@@ -11,7 +11,7 @@
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
- "launchUrl": "log",
+ "launchUrl": "",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/src/SMAPI.Web/StardewModdingAPI.Web.csproj b/src/SMAPI.Web/StardewModdingAPI.Web.csproj
index b5b0ff07..19198503 100644
--- a/src/SMAPI.Web/StardewModdingAPI.Web.csproj
+++ b/src/SMAPI.Web/StardewModdingAPI.Web.csproj
@@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.6.0" />
+ <PackageReference Include="Markdig" Version="0.14.8" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.0.0" />
diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs
index 307c4ae9..e5e759e7 100644
--- a/src/SMAPI.Web/Startup.cs
+++ b/src/SMAPI.Web/Startup.cs
@@ -48,7 +48,7 @@ namespace StardewModdingAPI.Web
// init configuration
services
.Configure<ModUpdateCheckConfig>(this.Configuration.GetSection("ModUpdateCheck"))
- .Configure<LogParserConfig>(this.Configuration.GetSection("LogParser"))
+ .Configure<ContextConfig>(this.Configuration.GetSection("Context"))
.Configure<RouteOptions>(options => options.ConstraintMap.Add("semanticVersion", typeof(VersionConstraint)))
.AddMemoryCache()
.AddMvc()
@@ -134,7 +134,6 @@ namespace StardewModdingAPI.Web
// shortcut redirects
.Add(new RedirectToUrlRule("^/docs$", "https://stardewvalleywiki.com/Modding:Index"))
- .Add(new RedirectToUrlRule("^/install$", "https://stardewvalleywiki.com/Modding:Installing_SMAPI"))
)
.UseStaticFiles() // wwwroot folder
.UseMvc();
diff --git a/src/SMAPI.Web/ViewModels/IndexModel.cs b/src/SMAPI.Web/ViewModels/IndexModel.cs
new file mode 100644
index 00000000..6d3da91e
--- /dev/null
+++ b/src/SMAPI.Web/ViewModels/IndexModel.cs
@@ -0,0 +1,41 @@
+namespace StardewModdingAPI.Web.ViewModels
+{
+ /// <summary>The view model for the index page.</summary>
+ public class IndexModel
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The latest SMAPI version.</summary>
+ public string LatestVersion { get; set; }
+
+ /// <summary>The Markdown description for the release.</summary>
+ public string Description { get; set; }
+
+ /// <summary>The main download URL.</summary>
+ public string DownloadUrl { get; set; }
+
+ /// <summary>The for-developers download URL.</summary>
+ public string DevDownloadUrl { get; set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ public IndexModel() { }
+
+ /// <summary>Construct an instance.</summary>
+ /// <param name="latestVersion">The latest SMAPI version.</param>
+ /// <param name="description">The Markdown description for the release.</param>
+ /// <param name="downloadUrl">The main download URL.</param>
+ /// <param name="devDownloadUrl">The for-developers download URL.</param>
+ internal IndexModel(string latestVersion, string description, string downloadUrl, string devDownloadUrl)
+ {
+ this.LatestVersion = latestVersion;
+ this.Description = description;
+ this.DownloadUrl = downloadUrl;
+ this.DevDownloadUrl = devDownloadUrl;
+ }
+ }
+}
diff --git a/src/SMAPI.Web/Views/Index/Index.cshtml b/src/SMAPI.Web/Views/Index/Index.cshtml
new file mode 100644
index 00000000..1bae8b16
--- /dev/null
+++ b/src/SMAPI.Web/Views/Index/Index.cshtml
@@ -0,0 +1,62 @@
+@{
+ ViewData["Title"] = "SMAPI";
+}
+@model StardewModdingAPI.Web.ViewModels.IndexModel
+@section Head {
+ <link rel="stylesheet" href="~/Content/css/index.css" />
+}
+
+<p id="blurb">
+ The mod loader for Stardew Valley. It works fine with GOG and Steam achievements, it's
+ compatible with Linux/Mac/Windows, you can uninstall it anytime, and there's a friendly
+ community if you need help. It's a cool pufferchick.
+</p>
+
+<div id="call-to-action">
+ <a href="@Model.DownloadUrl" class="main-cta">Download SMAPI @Model.LatestVersion</a><br />
+ <a href="https://stardewvalleywiki.com/Modding:Installing_SMAPI" class="secondary-cta">Install guide</a><br />
+ <a href="https://stardewvalleywiki.com/Modding:Player_FAQs" class="secondary-cta">FAQs</a><br />
+ <img src="favicon.ico" />
+</div>
+
+
+<h2>Find help</h2>
+<ul>
+ <li><a href="https://stardewvalleywiki.com/Modding:SMAPI_compatibility">Mod compatibility list</a></li>
+ <li>Get help <a href="https://stardewvalleywiki.com/Modding:Community#Discord">on Discord</a> or <a href="https://community.playstarbound.com/threads/smapi-stardew-modding-api.108375/">in the forums</a></li>
+</ul>
+
+<h2>What's new in SMAPI @Model.LatestVersion?</h2>
+<div class="github-description">
+ @Html.Raw(Markdig.Markdown.ToHtml(Model.Description))
+</div>
+
+<p>See the <a href="https://github.com/Pathoschild/SMAPI/blob/develop/docs/release-notes.md#release-notes">release notes</a> and <a href="https://stardewvalleywiki.com/Modding:SMAPI_compatibility">mod compatibility list</a> for more info.</p>
+
+<h2>Support SMAPI ♥</h2>
+<ul id="support-links">
+ <li><a href="https://www.paypal.me/pathoschild">Donate once</a></li>
+ <li>
+ <a href="https://www.patreon.com/pathoschild">Donate $1+/month</a><br />
+ <small>You'll have access to all private posts about behind-the-scenes info, upcoming features, and early previews of SMAPI updates. You can optionally provide early feedback on SMAPI features to influence development.</small>
+ </li>
+ <li><a href="https://github.com/Pathoschild/SMAPI">Contribute to the code</a></li>
+</ul>
+
+<p>
+ Special thanks to
+ acerbicon,
+ <a href="https://www.nexusmods.com/stardewvalley/users/31393530">ChefRude</a>,
+ jwdred,
+ <a href="http://community.playstarbound.com/members/karmylla.637910/">Karmylla</a>,
+ OfficialPiAddict,
+ Robby LaFarge,
+ and a few anonymous users for supporting SMAPI; you're awesome! 🏅
+</p>
+
+<h2>For mod creators</h2>
+<ul>
+ <li><a href="@Model.DevDownloadUrl">SMAPI 2.2 for developers</a> (includes <a href="https://docs.microsoft.com/en-us/visualstudio/ide/using-intellisense">intellisense</a> and full console output)</li>
+ <li><a href="https://stardewvalleywiki.com/Modding:Index">Modding documentation</a></li>
+ <li>Need help? Come <a href="https://stardewvalleywiki.com/Modding:Community#Discord">chat on Discord</a>.</li>
+</ul>
diff --git a/src/SMAPI.Web/Views/Shared/_Layout.cshtml b/src/SMAPI.Web/Views/Shared/_Layout.cshtml
index 547a8178..ac98c71b 100644
--- a/src/SMAPI.Web/Views/Shared/_Layout.cshtml
+++ b/src/SMAPI.Web/Views/Shared/_Layout.cshtml
@@ -1,3 +1,7 @@
+@using Microsoft.Extensions.Options
+@using StardewModdingAPI.Web.Framework.ConfigModels
+@inject IOptions<ContextConfig> ContextConfig
+
<!DOCTYPE html>
<html>
<head>
@@ -10,9 +14,9 @@
<div id="sidebar">
<h4>SMAPI</h4>
<ul>
- <li><a href="https://stardewvalleywiki.com/Modding:Index">FAQs & guides</a></li>
- <li><a href="https://github.com/pathoschild/SMAPI/releases">Download SMAPI</a></li>
- <li><a href="https://discord.gg/stardewvalley">Get help on Discord</a></li>
+ <li><a href="@ContextConfig.Value.RootUrl">About SMAPI</a></li>
+ <li><a href="@ContextConfig.Value.LogParserUrl">Log parser</a></li>
+ <li><a href="https://stardewvalleywiki.com/Modding:Index">Docs</a></li>
</ul>
</div>
<div id="content-column">
diff --git a/src/SMAPI.Web/appsettings.Development.json b/src/SMAPI.Web/appsettings.Development.json
index 45fc30f3..495af120 100644
--- a/src/SMAPI.Web/appsettings.Development.json
+++ b/src/SMAPI.Web/appsettings.Development.json
@@ -16,14 +16,15 @@
"Microsoft": "Information"
}
},
+ "Context": {
+ "RootUrl": "http://localhost:59482/",
+ "LogParserUrl": "http://localhost:59482/log/"
+ },
"ApiClients": {
"GitHubUsername": null,
"GitHubPassword": null,
"PastebinUserKey": null,
"PastebinDevKey": null
- },
- "LogParser": {
- "SectionUrl": "http://localhost:59482/log/"
}
}
diff --git a/src/SMAPI.Web/appsettings.json b/src/SMAPI.Web/appsettings.json
index 69b3b4f8..9758f4a7 100644
--- a/src/SMAPI.Web/appsettings.json
+++ b/src/SMAPI.Web/appsettings.json
@@ -13,6 +13,10 @@
"Default": "Warning"
}
},
+ "Context": {
+ "RootUrl": null, // see top note
+ "LogParserUrl": null // see top note
+ },
"ApiClients": {
"UserAgent": "SMAPI/{0} (+https://github.com/Pathoschild/SMAPI)",
@@ -41,8 +45,5 @@
"ChucklefishKey": "Chucklefish",
"GitHubKey": "GitHub",
"NexusKey": "Nexus"
- },
- "LogParser": {
- "SectionUrl": null // see top note
}
}
diff --git a/src/SMAPI.Web/wwwroot/Content/css/index.css b/src/SMAPI.Web/wwwroot/Content/css/index.css
new file mode 100644
index 00000000..06cd6fb4
--- /dev/null
+++ b/src/SMAPI.Web/wwwroot/Content/css/index.css
@@ -0,0 +1,58 @@
+/*********
+** Intro
+*********/
+h1 {
+ text-align: center;
+ font-size: 6em;
+ color: #000;
+}
+
+#blurb {
+ margin: auto;
+ width: 30em;
+ text-align: center;
+}
+
+#call-to-action {
+ margin: 3em 0;
+ text-align: center;
+}
+
+#call-to-action a {
+ box-shadow: #caefab 0 1px 0 0 inset;
+ background: linear-gradient(#77d42a 5%, #5cb811 100%) #77d42a;
+ border-radius: 6px;
+ border: 1px solid #268a16;
+ display: inline-block;
+ cursor: pointer;
+ color: #306108;
+ font-weight: bold;
+ margin-bottom: 1em;
+ padding: 6px 24px;
+ text-decoration: none;
+ text-shadow: #aade7c 0 1px 0;
+}
+
+#call-to-action a.secondary-cta {
+ background: #768d87;
+ border: 1px solid #566963;
+ color: #ffffff;
+ text-shadow: #2b665e 0 1px 0;
+}
+
+/*********
+** Subsections
+*********/
+.github-description {
+ border-left: 0.25em solid #dfe2e5;
+ padding-left: 1em;
+}
+
+.github-description .noinclude {
+ display: none;
+}
+
+#support-links li small {
+ display: block;
+ width: 50em;
+}