Skip to content

Notification on outdated Rider package #2244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 24, 2022
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class UnityPluginInstaller
private readonly UnityVersion myUnityVersion;
private readonly UnitySolutionTracker myUnitySolutionTracker;
private readonly UnityRefresher myRefresher;
private readonly RiderNotificationPopupHost myNotificationPopupHost;
private readonly UserNotifications myUserNotifications;
private readonly IHostProductInfo myHostProductInfo;
private readonly IContextBoundSettingsStoreLive myBoundSettingsStore;
private readonly ProcessingQueue myQueue;
Expand All @@ -57,7 +57,7 @@ public UnityPluginInstaller(
UnitySolutionTracker unitySolutionTracker,
UnityRefresher refresher,
IHostProductInfo hostProductInfo,
RiderNotificationPopupHost notificationPopupHost = null)
UserNotifications userNotifications)
{
myPluginInstallations = new JetHashSet<VirtualFileSystemPath>();

Expand All @@ -72,7 +72,7 @@ public UnityPluginInstaller(
myUnitySolutionTracker = unitySolutionTracker;
myRefresher = refresher;
myHostProductInfo = hostProductInfo;
myNotificationPopupHost = notificationPopupHost;
myUserNotifications = userNotifications;

myBoundSettingsStore = settingsStore.BoundSettingsStore;
myQueue = new ProcessingQueue(myShellLocks, myLifetime);
Expand Down Expand Up @@ -362,8 +362,7 @@ internal void ShowOutOfSyncNotification(Lifetime lifetime)
var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) => s.InstallUnity3DRiderPlugin);
var isEnabled = myBoundSettingsStore.GetValueProperty<bool>(lifetime, entry, null).Value;
if (isEnabled) return;
var notification = RiderNotification.Create(
NotificationSeverity.WARNING, "Unity editor plugin update required",
myUserNotifications.CreateNotification(notificationLifetime.Lifetime, NotificationSeverity.WARNING, "Unity editor plugin update required",
"The Unity editor plugin is out of date and automatic plugin updates are disabled. Advanced Unity integration features are unavailable until the plugin is updated.",
additionalCommands: new[]
{
Expand All @@ -377,17 +376,13 @@ internal void ShowOutOfSyncNotification(Lifetime lifetime)
notificationLifetime.Terminate();
});
})
}
);
myNotificationPopupHost.ShowNotification(notificationLifetime.Lifetime, notification);
});
}
else
{
var notification = RiderNotification.Create(
NotificationSeverity.WARNING, "Advanced Unity integration is unavailable",
$"Make sure Rider {myHostProductInfo.VersionMarketingString} is set as the External Editor in Unity preferences."
);
myNotificationPopupHost.ShowNotification(notificationLifetime.Lifetime, notification);
myUserNotifications.CreateNotification(notificationLifetime.Lifetime, NotificationSeverity.WARNING,
"Advanced Unity integration is unavailable",
$"Make sure Rider {myHostProductInfo.VersionMarketingString} is set as the External Editor in Unity preferences.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using JetBrains.Application.Notifications;
using JetBrains.Application.Settings;
using JetBrains.Application.Threading;
using JetBrains.Collections.Viewable;
using JetBrains.DataFlow;
using JetBrains.Lifetimes;
using JetBrains.ProjectModel;
using JetBrains.ProjectModel.DataContext;
using JetBrains.ReSharper.Plugins.Unity.Core.Application.Settings;
using JetBrains.ReSharper.Plugins.Unity.Core.ProjectModel;
using JetBrains.ReSharper.Plugins.Unity.Rider.Protocol;
using JetBrains.ReSharper.Plugins.Unity.UnityEditorIntegration;
using JetBrains.ReSharper.Plugins.Unity.UnityEditorIntegration.Packages;
using JetBrains.ReSharper.Psi.Util;
using JetBrains.Util;

namespace JetBrains.ReSharper.Plugins.Unity.Rider.UnityEditorIntegration
{
[SolutionComponent]
public class RiderPackageUpdateAvailabilityChecker
{
private readonly ILogger myLogger;
private readonly ISolution mySolution;
private readonly IShellLocks myShellLocks;
private readonly PackageManager myPackageManager;
private readonly UnityVersion myUnityVersion;
private readonly ISettingsStore mySettingsStore;
private readonly BackendUnityHost myBackendUnityHost;
private readonly UserNotifications myUserNotifications;
private readonly JetHashSet<VirtualFileSystemPath> myNotificationShown;
private readonly IContextBoundSettingsStoreLive myBoundSettingsStore;
private string packageId = "com.unity.ide.rider";
private Version leastRiderPackageVersion = new Version(3, 0, 9);

public RiderPackageUpdateAvailabilityChecker(
Lifetime lifetime,
ILogger logger,
ISolution solution,
IShellLocks shellLocks,
PackageManager packageManager,
UnitySolutionTracker unitySolutionTracker,
UnityVersion unityVersion,
IApplicationWideContextBoundSettingStore applicationWideContextBoundSettingStore,
ISettingsStore settingsStore,
BackendUnityHost backendUnityHost,
UserNotifications userNotifications
)
{
myLogger = logger;
mySolution = solution;
myShellLocks = shellLocks;
myPackageManager = packageManager;
myUnityVersion = unityVersion;
mySettingsStore = settingsStore;
myBackendUnityHost = backendUnityHost;
myUserNotifications = userNotifications;
myNotificationShown = new JetHashSet<VirtualFileSystemPath>();
myBoundSettingsStore = applicationWideContextBoundSettingStore.BoundSettingsStore;
unitySolutionTracker.IsUnityGeneratedProject.WhenTrue(lifetime, lt =>
{
ShowNotificationIfNeeded(lt, leastRiderPackageVersion);
BindToInstallationSettingChange(lt, leastRiderPackageVersion);
BindToProtocol(lt);
});
}

private void BindToProtocol(Lifetime lt)
{
myBackendUnityHost.BackendUnityModel.ViewNotNull(lt, (l, model) =>
{
model.RiderPackagePotentialUpdateVersion.Advise(l, result =>
{
if (!string.IsNullOrEmpty(result) && Version.TryParse(result, out var resultVersion))
{
ShowNotificationIfNeeded(l, resultVersion);
}
});
});
}

private void BindToInstallationSettingChange(Lifetime lifetime, Version version)
{
var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) =>
s.AllowRiderUpdateNotifications);
myBoundSettingsStore.GetValueProperty<bool>(lifetime, entry, null).Change.Advise_NoAcknowledgement(lifetime,
args =>
{
if (!args.GetNewOrNull()) return;
ShowNotificationIfNeeded(lifetime, version);
});
}

private void ShowNotificationIfNeeded(Lifetime lifetime, Version expectedVersion)
{
if (!myBoundSettingsStore.GetValue((UnitySettings s) => s.AllowRiderUpdateNotifications))
return;

myPackageManager.IsInitialUpdateFinished.WhenTrue(lifetime, lt =>
{
myUnityVersion.ActualVersionForSolution.AdviseNotNull(lt, version =>
{
if (myNotificationShown.Contains(mySolution.SolutionFilePath)) return;

// Version before 2019.2 doesn't have Rider package
// 2019.2.0 - 2019.2.5 : version 1.2.1 is the last one
// 2019.2.6 - present : see: leastRiderPackageVersion
if (version < new Version(2019, 2, 6)) return;

var package = myPackageManager.GetPackageById(packageId);

if (package == null)
{
myNotificationShown.Add(mySolution.SolutionFilePath);
myLogger.Info($"{packageId} is missing.");
myShellLocks.ExecuteOrQueueEx(lt,
"RiderPackageUpdateAvailabilityChecker.ShowNotificationIfNeeded",
() =>
{
myUserNotifications.CreateNotification(lt, NotificationSeverity.WARNING,
"JetBrains Rider package in Unity is missing.",
"Make sure JetBrains Rider package is installed in Unity Package Manager.");
});
}
else if (package.Source == PackageSource.Registry &&
new Version(package.PackageDetails.Version) < expectedVersion)
{
var notificationLifetime = lt.CreateNested();
myNotificationShown.Add(mySolution.SolutionFilePath);
myLogger.Info($"{packageId} {package.PackageDetails.Version} is older then expected.");

myShellLocks.ExecuteOrQueueEx(lt,
"RiderPackageUpdateAvailabilityChecker.ShowNotificationIfNeeded",
() => myUserNotifications.CreateNotification(notificationLifetime.Lifetime,
NotificationSeverity.INFO,
"Update available - JetBrains Rider package.",
"Check for JetBrains Rider package updates in Unity Package Manager.",
additionalCommands: new[]
{
new UserNotificationCommand("Never show for this solution", () =>
{
mySettingsStore.BindToContextTransient(
ContextRange.ManuallyRestrictWritesToOneContext(
mySolution.ToDataContext()))
.SetValue((UnitySettings key) => key.AllowRiderUpdateNotifications, false);
notificationLifetime.Terminate();
})
}));
}
});
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class UnitySettings
{
[SettingsEntry(true, "If this option is enabled, the Rider Unity editor plugin will be automatically installed and updated.")]
public bool InstallUnity3DRiderPlugin;

[SettingsEntry(true, "If this option is disabled, Rider package update notifications would never be shown.")]
public bool AllowRiderUpdateNotifications;

[SettingsEntry(true, "If this option is enabled, Rider will automatically notify the Unity editor to refresh assets.")]
public bool AllowAutomaticRefreshInUnity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ private void AddGeneralSection()

AddBoolOption((UnitySettings s) => s.AllowAutomaticRefreshInUnity,
"Automatically refresh assets in Unity");

AddBoolOption((UnitySettings s) => s.AllowRiderUpdateNotifications,
"Notify when Rider package update is available");
}

private void AddCSharpSection()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ object BackendUnityModel: Root() {
call("getUnityEditorState", void, Library.UnityEditorState).documentation = "Polled from the backend to get what the editor is currently doing"

property("unityApplicationData", Library.UnityApplicationData)
property ("riderPackagePotentialUpdateVersion", string).documentation = "Version of the latest compatible update for the Rider package"
field("unityApplicationSettings", Library.UnityApplicationSettings)
field("unityProjectSettings", Library.UnityProjectSettings)

Expand Down
2 changes: 2 additions & 0 deletions unity/EditorPlugin/AfterUnity56/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ static EntryPoint()

PluginEntryPoint.OnModelInitialization += UnitTesting.Initialization.OnModelInitializationHandler;
PluginEntryPoint.OnModelInitialization += Navigation.Initialization.OnModelInitializationHandler;
PluginEntryPoint.OnModelInitialization += Packages.Initialization.OnModelInitializationHandler;
AppDomain.CurrentDomain.DomainUnload += (EventHandler) ((_, __) =>
{
PluginEntryPoint.OnModelInitialization -= UnitTesting.Initialization.OnModelInitializationHandler;
PluginEntryPoint.OnModelInitialization -= Navigation.Initialization.OnModelInitializationHandler;
PluginEntryPoint.OnModelInitialization -= Packages.Initialization.OnModelInitializationHandler;
});
}
}
Expand Down
55 changes: 55 additions & 0 deletions unity/EditorPlugin/AfterUnity56/Packages/Initialization.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#if UNITY_2019_2
using System.Linq;
using JetBrains.Diagnostics;
using JetBrains.Rd.Base;
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
#endif

namespace JetBrains.Rider.Unity.Editor.AfterUnity56.Packages
{
public static class Initialization
{
#if UNITY_2019_2
private static string packageId = "com.unity.ide.rider";
private static readonly ILog ourLogger = Log.GetLog("Packages.Initialization");
private static SearchRequest ourRequest;
#endif
public static void OnModelInitializationHandler(UnityModelAndLifetime modelAndLifetime)
{
#if UNITY_2019_2
ourRequest = Client.Search(packageId);
modelAndLifetime.Lifetime.OnTermination(() => { ourRequest = null; });
EditorApplication.update += () => Progress(modelAndLifetime);
#endif
}
#if UNITY_2019_2
static void Progress(UnityModelAndLifetime modelAndLifetime)
{
if (ourRequest == null)
{
EditorApplication.update -= () => Progress(modelAndLifetime);
return;
}

if (!ourRequest.IsCompleted) return;
if (ourRequest.Status == StatusCode.Success)
{
var latestCompatible = ourRequest.Result.FirstOrDefault()?.versions.latestCompatible;
if (latestCompatible != null)
{
ourLogger.Info("Found: " + latestCompatible);
modelAndLifetime.Model.RiderPackagePotentialUpdateVersion.Set(latestCompatible);
}
}
else if (ourRequest.Status >= StatusCode.Failure)
{
ourLogger.Error(ourRequest.Error.message);
}

EditorApplication.update -= () => Progress(modelAndLifetime);
}
#endif
}
}
7 changes: 4 additions & 3 deletions unity/EditorPlugin/EditorPluginNet46.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
<RootNamespace>JetBrains.Rider.Unity.Editor</RootNamespace>
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<DefineConstants>UNITY_2017_3;RIDER_EDITOR_PLUGIN</DefineConstants>
<DefineConstants>UNITY_2019_2;RIDER_EDITOR_PLUGIN</DefineConstants>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyOriginatorKeyFile>..\..\sign.snk</AssemblyOriginatorKeyFile>
<LangVersion>9</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Unity.Libs.Ref.2017.3.0f3" Version="2020.6.10" />
<PackageReference Include="JetBrains.Unity.Libs.Ref.2019.2.0f1" Version="2021.11.29" />
<PackageReference Include="JetBrains.Build.ILRepack" Version="0.0.3" />
<PackageReference Include="JetBrains.Toolset.RefAsm.net461.NetStandard" Version="2.0.20190130.182358" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net472" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit" Version="3.13.2" />
</ItemGroup>

<Target Name="WriteRiderDev" AfterTargets="CopyFilesToOutputDirectory">
Expand All @@ -41,7 +42,7 @@
<Compile Remove="AssetPostprocessors\SlnAssetPostprocessor.cs" />
<Compile Remove="RiderMenu.cs" />
</ItemGroup>
<Import Project="$(DotNetSdkPath)\Build\PackageReference.JetBrains.RdFramework.Props"/>
<Import Project="$(DotNetSdkPath)\Build\PackageReference.JetBrains.RdFramework.Props" />
<Import Project="ILRepack.targets" />
<Import Project="Model.targets" />
</Project>
2 changes: 1 addition & 1 deletion unity/EditorPlugin/EditorPluginUnity56.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<ItemGroup>
<Compile Remove="AfterUnity56\UnitTesting\CompiledAssembliesTracker.cs" />
</ItemGroup>
<Import Project="$(DotNetSdkPath)\Build\PackageReference.JetBrains.RdFramework.Props"/>
<Import Project="$(DotNetSdkPath)\Build\PackageReference.JetBrains.RdFramework.Props" />
<Import Project="ILRepack.targets" />
<Import Project="Model.targets" />
</Project>
2 changes: 2 additions & 0 deletions unity/EditorPlugin/PluginSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ public static bool LogEventsCollectorEnabled
/// <remarks>
/// Contains all 3 toggles: Enable/Disable; Debug On/Off; Writing Launch File On/Off
/// </remarks>
#if !UNITY_2019_2 // this is not loaded, for Rider package, so remove it to avoid compilation warning
[PreferenceItem("Rider")]
#endif
private static void RiderPreferencesItem()
{
EditorGUIUtility.labelWidth = 200f;
Expand Down