Skip to content

Commit

Permalink
Animate tray icon while opening database.
Browse files Browse the repository at this point in the history
  • Loading branch information
Aldaviva committed Oct 28, 2020
1 parent b8fe00a commit 9df27f9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 23 deletions.
11 changes: 11 additions & 0 deletions KeePassTrayIconLockState/DatabaseOpenState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace KeePassTrayIconLockState {

internal enum DatabaseOpenState {

CLOSED,
OPENING,
OPEN

}

}
7 changes: 4 additions & 3 deletions KeePassTrayIconLockState/KeePassTrayIconLockState.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@
<HintPath>..\..\..\..\..\..\Programs\Security\KeePass\KeePass.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="KoKo">
<HintPath>..\..\KoKo\KoKo\bin\Release\net45\KoKo.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Include="DatabaseOpenState.cs" />
<Compile Include="KeePassTrayIconLockStateExt.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TrayIcon.cs" />
Expand All @@ -51,9 +55,6 @@
<PackageReference Include="ILRepack.Lib.MSBuild.Task">
<Version>2.0.18.1</Version>
</PackageReference>
<PackageReference Include="KoKo">
<Version>2.0.2</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
59 changes: 39 additions & 20 deletions KeePassTrayIconLockState/KeePassTrayIconLockStateExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,57 @@
namespace KeePassTrayIconLockState {

// ReSharper disable once UnusedType.Global
public class KeePassTrayIconLockStateExt: Plugin {
public class KeePassTrayIconLockStateExt: Plugin, IDisposable {

private readonly TimeSpan startupDelay = TimeSpan.FromMilliseconds(50);
private readonly TimeSpan startupDelay = TimeSpan.FromMilliseconds(60);
private readonly IDictionary<DatabaseOpenState, Icon> iconsByFileOpenState = new Dictionary<DatabaseOpenState, Icon>();
private readonly StoredProperty<DatabaseOpenState> databaseOpenState = new StoredProperty<DatabaseOpenState>(DatabaseOpenState.CLOSED);
private readonly Property<TrayIcon> trayIcon;
private readonly StoredProperty<bool> isDatabaseOpen = new StoredProperty<bool>(false);

private IPluginHost keePassHost = null!;
private Timer? animationTimer;

public KeePassTrayIconLockStateExt() {
iconsByFileOpenState.Add(DatabaseOpenState.CLOSED, loadIcon(false));
iconsByFileOpenState.Add(DatabaseOpenState.OPENING, loadIcon(false));
iconsByFileOpenState.Add(DatabaseOpenState.OPEN, loadIcon(true));
Icon lockedIcon = loadIcon(false);
Icon unlockedIcon = loadIcon(true);

trayIcon = DerivedProperty<TrayIcon>.Create(databaseOpenState, isOpen => new TrayIcon(iconsByFileOpenState[isOpen], isOpen != DatabaseOpenState.CLOSED));
iconsByFileOpenState.Add(DatabaseOpenState.CLOSED, lockedIcon);
iconsByFileOpenState.Add(DatabaseOpenState.OPENING, lockedIcon);
iconsByFileOpenState.Add(DatabaseOpenState.OPEN, unlockedIcon);
}

public override bool Initialize(IPluginHost host) {
keePassHost = host;

keePassHost.MainWindow.FileOpened += delegate { databaseOpenState.Value = DatabaseOpenState.OPEN; };
keePassHost.MainWindow.FileClosed += delegate { databaseOpenState.Value = DatabaseOpenState.CLOSED; };
keePassHost.MainWindow.FileOpened += delegate { isDatabaseOpen.Value = true; };
keePassHost.MainWindow.FileClosed += delegate { isDatabaseOpen.Value = false; };

ToolStripItem statusBarInfo = keePassHost.MainWindow.Controls.OfType<StatusStrip>().First().Items[1];
statusBarInfo.TextChanged += (sender, args) => {
if (statusBarInfo.Text == KPRes.OpeningDatabase2) {
databaseOpenState.Value = DatabaseOpenState.OPENING;
ToolStripItem statusBarInfo = keePassHost.MainWindow.Controls.OfType<StatusStrip>().First().Items[1];
Property<string> statusBarText = new NativeReadableProperty<string>(statusBarInfo, nameof(ToolStripItem.Text), nameof(ToolStripItem.TextChanged));

Property<DatabaseOpenState> databaseOpenState = DerivedProperty<DatabaseOpenState>.Create(isDatabaseOpen, statusBarText, (isOpen, statusText) => {
if (statusText == KPRes.OpeningDatabase2) {
return DatabaseOpenState.OPENING;
} else {
return isOpen ? DatabaseOpenState.OPEN : DatabaseOpenState.CLOSED;
}
};
});

Property<TrayIcon> trayIcon = DerivedProperty<TrayIcon>.Create(databaseOpenState, isOpen => new TrayIcon(iconsByFileOpenState[isOpen], isOpen != DatabaseOpenState.CLOSED));

trayIcon.PropertyChanged += (sender, args) => renderTrayIcon(args.NewValue);

animationTimer = new Timer { Enabled = false, Interval = 600 };
bool animationShowClosedIcon = false;
animationTimer.Tick += delegate {
keePassHost.MainWindow.MainNotifyIcon.Icon = iconsByFileOpenState[animationShowClosedIcon ? DatabaseOpenState.CLOSED : DatabaseOpenState.OPEN];
animationShowClosedIcon ^= true;
};

databaseOpenState.PropertyChanged += (sender, args) => {
animationShowClosedIcon = false;
animationTimer.Enabled = args.NewValue == DatabaseOpenState.OPENING;
};

Task.Delay(startupDelay)
.ContinueWith(_ => renderTrayIcon(trayIcon.Value)); // Give KeePass time to stop setting its own icon

Expand All @@ -65,12 +84,12 @@ private void renderTrayIcon(TrayIcon icon) {

public override Image SmallIcon => iconsByFileOpenState[DatabaseOpenState.CLOSED].ToBitmap();

private enum DatabaseOpenState {

CLOSED,
OPENING,
OPEN
public override void Terminate() {
Dispose();
}

public void Dispose() {
animationTimer?.Dispose();
}

}
Expand Down

0 comments on commit 9df27f9

Please sign in to comment.