Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e4b3fae4bf | |||
| a24aef7f0a | |||
| 3bf7355017 | |||
| 702c267f90 | |||
| 6a128ef899 | |||
| 2ae6a90117 | |||
| 1b334edaf7 | |||
| 0a920a0c8d |
100
bin/net6.0-windows/EVE-O-Preview.deps.json
Normal file
100
bin/net6.0-windows/EVE-O-Preview.deps.json
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v6.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"EVE-O-Preview/1.0.0": {
|
||||
"dependencies": {
|
||||
"LightInject": "7.0.1",
|
||||
"MediatR": "9.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.NET.ILLink.Analyzers": "7.0.100-1.23211.1",
|
||||
"Microsoft.NET.ILLink.Tasks": "7.0.100-1.23211.1",
|
||||
"Newtonsoft.Json": "13.0.3"
|
||||
},
|
||||
"runtime": {
|
||||
"EVE-O-Preview.dll": {}
|
||||
}
|
||||
},
|
||||
"LightInject/7.0.1": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/LightInject.dll": {
|
||||
"assemblyVersion": "7.0.1.0",
|
||||
"fileVersion": "7.0.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MediatR/9.0.0": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.1/MediatR.dll": {
|
||||
"assemblyVersion": "9.0.0.0",
|
||||
"fileVersion": "9.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {},
|
||||
"Microsoft.NET.ILLink.Analyzers/7.0.100-1.23211.1": {},
|
||||
"Microsoft.NET.ILLink.Tasks/7.0.100-1.23211.1": {},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"runtime": {
|
||||
"lib/net6.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "13.0.0.0",
|
||||
"fileVersion": "13.0.3.27908"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"EVE-O-Preview/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"LightInject/7.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-aw4ayG2Pe68i+85ws8zYk7MPCKjEd4DeBoTqVvmjA2cfpYYNnw+v0E5T3PKdriKaxdKF+eUzlnxWWZnYK/gx4w==",
|
||||
"path": "lightinject/7.0.1",
|
||||
"hashPath": "lightinject.7.0.1.nupkg.sha512"
|
||||
},
|
||||
"MediatR/9.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8b3UYNxegHVYcJMG2zH8wn+YqxLvXG+eMfj0cMCq/jTW72p6O3PCKMkrIv0mqyxdW7bA4gblsocw7n+/9Akg5g==",
|
||||
"path": "mediatr/9.0.0",
|
||||
"hashPath": "mediatr.9.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
||||
"path": "microsoft.csharp/4.7.0",
|
||||
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NET.ILLink.Analyzers/7.0.100-1.23211.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==",
|
||||
"path": "microsoft.net.illink.analyzers/7.0.100-1.23211.1",
|
||||
"hashPath": "microsoft.net.illink.analyzers.7.0.100-1.23211.1.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NET.ILLink.Tasks/7.0.100-1.23211.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==",
|
||||
"path": "microsoft.net.illink.tasks/7.0.100-1.23211.1",
|
||||
"hashPath": "microsoft.net.illink.tasks.7.0.100-1.23211.1.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
|
||||
"path": "newtonsoft.json/13.0.3",
|
||||
"hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
128
bin/net6.0-windows/EVE-O-Preview.json
Normal file
128
bin/net6.0-windows/EVE-O-Preview.json
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"ConfigVersion": 1,
|
||||
"CycleGroup1ForwardHotkeys": [
|
||||
"F14",
|
||||
"Control+F14"
|
||||
],
|
||||
"CycleGroup1BackwardHotkeys": [
|
||||
"F13",
|
||||
"Control+F13"
|
||||
],
|
||||
"CycleGroup1ClientsOrder": {
|
||||
"EVE - Example DPS Toon 1": 1,
|
||||
"EVE - Example DPS Toon 2": 2,
|
||||
"EVE - Example DPS Toon 3": 3
|
||||
},
|
||||
"CycleGroup2ForwardHotkeys": [
|
||||
"F16",
|
||||
"Control+F16"
|
||||
],
|
||||
"CycleGroup2BackwardHotkeys": [
|
||||
"F15",
|
||||
"Control+F15"
|
||||
],
|
||||
"CycleGroup2ClientsOrder": {
|
||||
"EVE - Example Logi Toon 1": 1,
|
||||
"EVE - Example Scout Toon 2": 2,
|
||||
"EVE - Example Tackle Toon 3": 3
|
||||
},
|
||||
"CycleGroup3ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup3BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup3ClientsOrder": {
|
||||
"EVE - cycle group 3": 1
|
||||
},
|
||||
"CycleGroup4ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup4BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup4ClientsOrder": {
|
||||
"EVE - cycle group 4": 1
|
||||
},
|
||||
"CycleGroup5ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup5BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup5ClientsOrder": {
|
||||
"EVE - cycle group 5": 1
|
||||
},
|
||||
"PerClientActiveClientHighlightColor": {
|
||||
"EVE - Example Toon 1": "Red",
|
||||
"EVE - Example Toon 2": "Green"
|
||||
},
|
||||
"PerClientThumbnailSize": {
|
||||
"EVE - Example Toon 1": "200, 200",
|
||||
"EVE - Example Toon 2": "200, 200"
|
||||
},
|
||||
"PerClientThumbnailRegion": {},
|
||||
"PerClientZoomAnchor": {
|
||||
"EVE - Example Toon 1": 1,
|
||||
"EVE - Example Toon 2": 7
|
||||
},
|
||||
"MinimizeToTray": false,
|
||||
"ThumbnailRefreshPeriod": 500,
|
||||
"ThumbnailResizeTimeoutPeriod": 500,
|
||||
"WineCompatibilityMode": false,
|
||||
"ThumbnailsOpacity": 0.5,
|
||||
"EnableClientLayoutTracking": false,
|
||||
"HideActiveClientThumbnail": false,
|
||||
"HideLoginClientThumbnail": false,
|
||||
"MinimizeInactiveClients": false,
|
||||
"WindowsAnimationStyle": 1,
|
||||
"ShowThumbnailsAlwaysOnTop": true,
|
||||
"EnablePerClientThumbnailLayouts": false,
|
||||
"HideThumbnailsOnLostFocus": false,
|
||||
"HideThumbnailsDelay": 2,
|
||||
"ThumbnailSize": "408, 177",
|
||||
"ThumbnailMaximumSize": "960, 540",
|
||||
"ThumbnailMinimumSize": "192, 108",
|
||||
"EnableThumbnailSnap": true,
|
||||
"ThumbnailSnapRange": 20,
|
||||
"EnableThumbnailZoom": false,
|
||||
"ThumbnailZoomFactor": 2,
|
||||
"ThumbnailZoomAnchor": 0,
|
||||
"OverlayLabelAnchor": 0,
|
||||
"ShowThumbnailOverlays": true,
|
||||
"ShowThumbnailFrames": false,
|
||||
"LockThumbnailLocation": false,
|
||||
"ThumbnailSnapToGrid": true,
|
||||
"ThumbnailSnapToGridSizeX": 102,
|
||||
"ThumbnailSnapToGridSizeY": 44,
|
||||
"EnableActiveClientHighlight": false,
|
||||
"ActiveClientHighlightColor": "GreenYellow",
|
||||
"OverlayLabelColor": "Orange",
|
||||
"OverlayLabelSize": 10,
|
||||
"EnableThumbnailRegionSnipping": true,
|
||||
"DefaultThumbnailRegion": "1187, 1252, 398, 174",
|
||||
"CurrentProfile": "Default",
|
||||
"AvailableProfiles": [
|
||||
"Default"
|
||||
],
|
||||
"IconName": "IconOriginal",
|
||||
"ActiveClientHighlightThickness": 3,
|
||||
"LoginThumbnailLocation": "5, 5",
|
||||
"ToggleTrackingHotkey": "Alt+F16",
|
||||
"ToggleSingleProcessHotkey": "Control+F16",
|
||||
"ToggleAllThumbnailsHotkey": "Alt+F12",
|
||||
"ThumbnailsManuallyHidden": false,
|
||||
"PerClientLayout": {},
|
||||
"FlatLayout": {
|
||||
"EVE - Sn v1 cosunoo (2)": "1938, 1100",
|
||||
"EVE - Primorium (1)": "1530, 1100",
|
||||
"EVE - PhatPhuckDave (3)": "1122, 1100"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
"DisableThumbnail": {},
|
||||
"PriorityClients": [],
|
||||
"ExecutablesToPreview": [
|
||||
"exefile"
|
||||
]
|
||||
}
|
||||
18
bin/net6.0-windows/EVE-O-Preview.runtimeconfig.json
Normal file
18
bin/net6.0-windows/EVE-O-Preview.runtimeconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net6.0",
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "6.0.0"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.WindowsDesktop.App",
|
||||
"version": "6.0.0"
|
||||
}
|
||||
],
|
||||
"configProperties": {
|
||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
|
||||
}
|
||||
}
|
||||
}
|
||||
10
bin/net8.0-windows8.0/EVE-O-Preview-Master.json
Normal file
10
bin/net8.0-windows8.0/EVE-O-Preview-Master.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ActiveProfile": "capacitor",
|
||||
"Profiles": [
|
||||
"Default",
|
||||
"capacitor",
|
||||
"drones",
|
||||
"target-1row",
|
||||
"target-3row"
|
||||
]
|
||||
}
|
||||
@@ -80,11 +80,11 @@
|
||||
"EnablePerClientThumbnailLayouts": false,
|
||||
"HideThumbnailsOnLostFocus": false,
|
||||
"HideThumbnailsDelay": 2,
|
||||
"ThumbnailSize": "451, 238",
|
||||
"ThumbnailSize": "512, 288",
|
||||
"ThumbnailMaximumSize": "960, 540",
|
||||
"ThumbnailMinimumSize": "192, 108",
|
||||
"EnableThumbnailSnap": true,
|
||||
"ThumbnailSnapRange": 150,
|
||||
"ThumbnailSnapRange": 0,
|
||||
"EnableThumbnailZoom": false,
|
||||
"ThumbnailZoomFactor": 2,
|
||||
"ThumbnailZoomAnchor": 0,
|
||||
@@ -93,13 +93,13 @@
|
||||
"ShowThumbnailFrames": false,
|
||||
"LockThumbnailLocation": false,
|
||||
"ThumbnailSnapToGrid": true,
|
||||
"ThumbnailSnapToGridSizeX": 112,
|
||||
"ThumbnailSnapToGridSizeY": 59,
|
||||
"ThumbnailSnapToGridSizeX": 64,
|
||||
"ThumbnailSnapToGridSizeY": 36,
|
||||
"EnableActiveClientHighlight": true,
|
||||
"ActiveClientHighlightColor": "GreenYellow",
|
||||
"OverlayLabelColor": "Orange",
|
||||
"OverlayLabelSize": 10,
|
||||
"EnableThumbnailRegionSnipping": true,
|
||||
"EnableThumbnailRegionSnipping": false,
|
||||
"DefaultThumbnailRegion": "1664, 188, 451, 238",
|
||||
"CurrentProfile": "Default",
|
||||
"AvailableProfiles": [
|
||||
@@ -110,20 +110,21 @@
|
||||
"LoginThumbnailLocation": "5, 5",
|
||||
"ToggleTrackingHotkey": "Alt+F16",
|
||||
"ToggleSingleProcessHotkey": "Control+F16",
|
||||
"ToggleAllThumbnailsHotkey": "Shift+Alt+Oem3",
|
||||
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
|
||||
"ThumbnailsManuallyHidden": false,
|
||||
"PerClientLayout": {},
|
||||
"FlatLayout": {
|
||||
"EVE - Sn v1 cosunoo (2)": "1995, 1058",
|
||||
"EVE - Primorium (1)": "240, 645",
|
||||
"EVE - PhatPhuckDave (3)": "224, -2",
|
||||
"EVE - Primorium (3)": "146, 285",
|
||||
"EVE - PhatPhuckDave (2)": "146, 57",
|
||||
"EVE - Sn v1 cosunoo (1)": "154, 472",
|
||||
"EVE - Sn v1 cosunoo (3)": "292, 517",
|
||||
"EVE - Primorium (2)": "224, 236",
|
||||
"EVE - PhatPhuckDave (1)": "292, 57",
|
||||
"EVE - Secundamen (1)": "224, 474"
|
||||
"EVE - Quartio": "-896, 1620",
|
||||
"EVE - Tertiale": "-640, 1332",
|
||||
"EVE - PhatPhuckDave": "-1152, 1044",
|
||||
"EVE - Primorium": "-640, 1044",
|
||||
"EVE - Secundamen": "-1152, 1332",
|
||||
"EVE - Quartomo": "-512, 1152",
|
||||
"EVE - Tertiashi": "-512, 864",
|
||||
"EVE - Secundaru": "-512, 576",
|
||||
"EVE - Primosaki": "-512, 288",
|
||||
"EVE - PhuckingWeebDave": "-512, 0",
|
||||
"EVE": "0, 0"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
|
||||
@@ -118,7 +118,12 @@
|
||||
"EVE - Tertiale": "0, 1155",
|
||||
"EVE - Secundamen": "0, 1015",
|
||||
"EVE - Primorium": "0, 875",
|
||||
"EVE - PhatPhuckDave": "0, 735"
|
||||
"EVE - PhatPhuckDave": "0, 735",
|
||||
"EVE - Quartomo": "0, 1295",
|
||||
"EVE - Tertiashi": "0, 1155",
|
||||
"EVE - Secundaru": "0, 1015",
|
||||
"EVE - Primosaki": "0, 875",
|
||||
"EVE - PhuckingWeebDave": "0, 735"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
@@ -127,4 +132,4 @@
|
||||
"ExecutablesToPreview": [
|
||||
"exefile"
|
||||
]
|
||||
}
|
||||
}
|
||||
130
bin/net8.0-windows8.0/Profiles/drones.json
Normal file
130
bin/net8.0-windows8.0/Profiles/drones.json
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"ConfigVersion": 1,
|
||||
"CycleGroup1ForwardHotkeys": [
|
||||
"F14",
|
||||
"Control+F14"
|
||||
],
|
||||
"CycleGroup1BackwardHotkeys": [
|
||||
"F13",
|
||||
"Control+F13"
|
||||
],
|
||||
"CycleGroup1ClientsOrder": {
|
||||
"EVE - Example DPS Toon 1": 1,
|
||||
"EVE - Example DPS Toon 2": 2,
|
||||
"EVE - Example DPS Toon 3": 3
|
||||
},
|
||||
"CycleGroup2ForwardHotkeys": [
|
||||
"F16",
|
||||
"Control+F16"
|
||||
],
|
||||
"CycleGroup2BackwardHotkeys": [
|
||||
"F15",
|
||||
"Control+F15"
|
||||
],
|
||||
"CycleGroup2ClientsOrder": {
|
||||
"EVE - Example Logi Toon 1": 1,
|
||||
"EVE - Example Scout Toon 2": 2,
|
||||
"EVE - Example Tackle Toon 3": 3
|
||||
},
|
||||
"CycleGroup3ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup3BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup3ClientsOrder": {
|
||||
"EVE - cycle group 3": 1
|
||||
},
|
||||
"CycleGroup4ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup4BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup4ClientsOrder": {
|
||||
"EVE - cycle group 4": 1
|
||||
},
|
||||
"CycleGroup5ForwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup5BackwardHotkeys": [
|
||||
""
|
||||
],
|
||||
"CycleGroup5ClientsOrder": {
|
||||
"EVE - cycle group 5": 1
|
||||
},
|
||||
"PerClientActiveClientHighlightColor": {
|
||||
"EVE - Example Toon 1": "Red",
|
||||
"EVE - Example Toon 2": "Green"
|
||||
},
|
||||
"PerClientThumbnailSize": {
|
||||
"EVE - Example Toon 1": "200, 200",
|
||||
"EVE - Example Toon 2": "200, 200"
|
||||
},
|
||||
"PerClientThumbnailRegion": {},
|
||||
"PerClientZoomAnchor": {
|
||||
"EVE - Example Toon 1": 1,
|
||||
"EVE - Example Toon 2": 7
|
||||
},
|
||||
"MinimizeToTray": true,
|
||||
"ThumbnailRefreshPeriod": 500,
|
||||
"ThumbnailResizeTimeoutPeriod": 500,
|
||||
"WineCompatibilityMode": false,
|
||||
"ThumbnailsOpacity": 1.0,
|
||||
"EnableClientLayoutTracking": false,
|
||||
"HideActiveClientThumbnail": false,
|
||||
"HideLoginClientThumbnail": false,
|
||||
"MinimizeInactiveClients": false,
|
||||
"WindowsAnimationStyle": 1,
|
||||
"ShowThumbnailsAlwaysOnTop": true,
|
||||
"EnablePerClientThumbnailLayouts": false,
|
||||
"HideThumbnailsOnLostFocus": false,
|
||||
"HideThumbnailsDelay": 2,
|
||||
"ThumbnailSize": "351, 148",
|
||||
"ThumbnailMaximumSize": "960, 540",
|
||||
"ThumbnailMinimumSize": "192, 108",
|
||||
"EnableThumbnailSnap": true,
|
||||
"ThumbnailSnapRange": 0,
|
||||
"EnableThumbnailZoom": false,
|
||||
"ThumbnailZoomFactor": 2,
|
||||
"ThumbnailZoomAnchor": 0,
|
||||
"OverlayLabelAnchor": 0,
|
||||
"ShowThumbnailOverlays": true,
|
||||
"ShowThumbnailFrames": false,
|
||||
"LockThumbnailLocation": false,
|
||||
"ThumbnailSnapToGrid": true,
|
||||
"ThumbnailSnapToGridSizeX": 87,
|
||||
"ThumbnailSnapToGridSizeY": 37,
|
||||
"EnableActiveClientHighlight": true,
|
||||
"ActiveClientHighlightColor": "GreenYellow",
|
||||
"OverlayLabelColor": "Orange",
|
||||
"OverlayLabelSize": 10,
|
||||
"EnableThumbnailRegionSnipping": true,
|
||||
"DefaultThumbnailRegion": "1764, 988, 351, 148",
|
||||
"CurrentProfile": "Default",
|
||||
"AvailableProfiles": [
|
||||
"Default"
|
||||
],
|
||||
"IconName": "IconOriginal",
|
||||
"ActiveClientHighlightThickness": 3,
|
||||
"LoginThumbnailLocation": "5, 5",
|
||||
"ToggleTrackingHotkey": "Alt+F16",
|
||||
"ToggleSingleProcessHotkey": "Control+F16",
|
||||
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
|
||||
"ThumbnailsManuallyHidden": false,
|
||||
"PerClientLayout": {},
|
||||
"FlatLayout": {
|
||||
"EVE - Quartio": "-348, 814",
|
||||
"EVE - Tertiale": "-348, 666",
|
||||
"EVE - Secundamen": "-348, 518",
|
||||
"EVE - Primorium": "-348, 370",
|
||||
"EVE - PhatPhuckDave": "-348, 222"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
"DisableThumbnail": {},
|
||||
"PriorityClients": [],
|
||||
"ExecutablesToPreview": [
|
||||
"exefile"
|
||||
]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"CurrentProfile": "capacitor",
|
||||
"ProfileReadOnly": true
|
||||
}
|
||||
@@ -84,7 +84,7 @@
|
||||
"ThumbnailMaximumSize": "960, 540",
|
||||
"ThumbnailMinimumSize": "192, 108",
|
||||
"EnableThumbnailSnap": true,
|
||||
"ThumbnailSnapRange": 150,
|
||||
"ThumbnailSnapRange": 0,
|
||||
"EnableThumbnailZoom": false,
|
||||
"ThumbnailZoomFactor": 2,
|
||||
"ThumbnailZoomAnchor": 0,
|
||||
@@ -110,15 +110,15 @@
|
||||
"LoginThumbnailLocation": "5, 5",
|
||||
"ToggleTrackingHotkey": "Alt+F16",
|
||||
"ToggleSingleProcessHotkey": "Control+F16",
|
||||
"ToggleAllThumbnailsHotkey": "Shift+Alt+Oem3",
|
||||
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
|
||||
"ThumbnailsManuallyHidden": false,
|
||||
"PerClientLayout": {},
|
||||
"FlatLayout": {
|
||||
"EVE - Quartio": "0, 1239",
|
||||
"EVE - Tertiale": "0, 1003",
|
||||
"EVE - Secundamen": "0, 767",
|
||||
"EVE - Primorium": "448, 1121",
|
||||
"EVE - PhatPhuckDave": "448, 885"
|
||||
"EVE - Quartio": "0, 1295",
|
||||
"EVE - Tertiale": "0, 1147",
|
||||
"EVE - Secundamen": "0, 999",
|
||||
"EVE - Primorium": "0, 851",
|
||||
"EVE - PhatPhuckDave": "0, 703"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
@@ -127,4 +127,4 @@
|
||||
"ExecutablesToPreview": [
|
||||
"exefile"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -110,15 +110,15 @@
|
||||
"LoginThumbnailLocation": "5, 5",
|
||||
"ToggleTrackingHotkey": "Alt+F16",
|
||||
"ToggleSingleProcessHotkey": "Control+F16",
|
||||
"ToggleAllThumbnailsHotkey": "Shift+Alt+Oem3",
|
||||
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
|
||||
"ThumbnailsManuallyHidden": true,
|
||||
"PerClientLayout": {},
|
||||
"FlatLayout": {
|
||||
"EVE - Quartio": "-1229, 1067",
|
||||
"EVE - Tertiale": "-1680, 1067",
|
||||
"EVE - Secundamen": "-2131, 1067",
|
||||
"EVE - Primorium": "-2576, 679",
|
||||
"EVE - PhatPhuckDave": "-2576, 291"
|
||||
"EVE - Quartio": "-1120, 1067",
|
||||
"EVE - Tertiale": "-1568, 1067",
|
||||
"EVE - Secundamen": "-2016, 1067",
|
||||
"EVE - Primorium": "-2464, 679",
|
||||
"EVE - PhatPhuckDave": "-2464, 291"
|
||||
},
|
||||
"ClientLayout": {},
|
||||
"ClientHotkey": {},
|
||||
@@ -127,4 +127,4 @@
|
||||
"ExecutablesToPreview": [
|
||||
"exefile"
|
||||
]
|
||||
}
|
||||
}
|
||||
43
src/Eve-O-Mock/bin/Release/net6.0-windows/ExeFile.deps.json
Normal file
43
src/Eve-O-Mock/bin/Release/net6.0-windows/ExeFile.deps.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v6.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"ExeFile/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"System.Data.DataSetExtensions": "4.5.0"
|
||||
},
|
||||
"runtime": {
|
||||
"ExeFile.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {},
|
||||
"System.Data.DataSetExtensions/4.5.0": {}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"ExeFile/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
||||
"path": "microsoft.csharp/4.7.0",
|
||||
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
|
||||
},
|
||||
"System.Data.DataSetExtensions/4.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-221clPs1445HkTBZPL+K9sDBdJRB8UN8rgjO3ztB0CQ26z//fmJXtlsr6whGatscsKGBrhJl5bwJuKSA8mwFOw==",
|
||||
"path": "system.data.datasetextensions/4.5.0",
|
||||
"hashPath": "system.data.datasetextensions.4.5.0.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
</configuration>
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net6.0",
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "6.0.0"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.WindowsDesktop.App",
|
||||
"version": "6.0.0"
|
||||
}
|
||||
],
|
||||
"configProperties": {
|
||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,203 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EveOPreview.Configuration.Implementation {
|
||||
class ConfigurationStorage : IConfigurationStorage {
|
||||
private const string CONFIGURATION_FILE_NAME = "EVE-O-Preview.json";
|
||||
private const string PROFILES_DIRECTORY = "Profiles";
|
||||
private const string MASTER_CONFIG_FILE = "master.json";
|
||||
private const string PROFILES_FOLDER_NAME = "Profiles";
|
||||
private const string PROFILE_CONFIG_FILE_EXTENSION = ".json";
|
||||
|
||||
private readonly IAppConfig _appConfig;
|
||||
private readonly IThumbnailConfiguration _thumbnailConfiguration;
|
||||
private readonly string _baseDirectory;
|
||||
private string _currentProfile;
|
||||
|
||||
public ConfigurationStorage(IAppConfig appConfig, IThumbnailConfiguration thumbnailConfiguration) {
|
||||
this._appConfig = appConfig;
|
||||
this._thumbnailConfiguration = thumbnailConfiguration;
|
||||
this._baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
this._currentProfile = "Default";
|
||||
}
|
||||
|
||||
public string CurrentProfile {
|
||||
get => this._currentProfile;
|
||||
set {
|
||||
if (this._currentProfile != value) {
|
||||
this._currentProfile = value ?? "Default";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Load() {
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
string filename = this.GetConfigFileName();
|
||||
|
||||
// First, load the master configuration which contains ProfileReadOnly and CurrentProfile
|
||||
string currentProfile = "Default";
|
||||
bool profileReadOnly = false;
|
||||
|
||||
if (File.Exists(masterConfigPath)) {
|
||||
string masterRawData = File.ReadAllText(masterConfigPath);
|
||||
var masterConfig = JsonConvert.DeserializeObject<dynamic>(masterRawData);
|
||||
if (masterConfig.CurrentProfile != null) {
|
||||
currentProfile = masterConfig.CurrentProfile.ToString();
|
||||
}
|
||||
if (masterConfig.ProfileReadOnly != null) {
|
||||
profileReadOnly = (bool)masterConfig.ProfileReadOnly;
|
||||
}
|
||||
if (!File.Exists(filename)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._thumbnailConfiguration.CurrentProfile = currentProfile;
|
||||
this._thumbnailConfiguration.ProfileReadOnly = profileReadOnly;
|
||||
string rawData = File.ReadAllText(filename);
|
||||
|
||||
// Scan the profiles directory for available profiles AFTER loading master config
|
||||
List<string> scannedProfiles = this.ScanAvailableProfiles();
|
||||
JsonSerializerSettings jsonSerializerSettings =
|
||||
new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||
|
||||
// Replace AvailableProfiles with scanned profiles (they are the source of truth)
|
||||
this._thumbnailConfiguration.AvailableProfiles.Clear();
|
||||
foreach (string profile in scannedProfiles) {
|
||||
this._thumbnailConfiguration.AvailableProfiles.Add(profile);
|
||||
}
|
||||
// StageHotkeyArraysToAvoidDuplicates(rawData);
|
||||
|
||||
// Ensure CurrentProfile is in the list
|
||||
if (!string.IsNullOrEmpty(this._thumbnailConfiguration.CurrentProfile) &&
|
||||
!this._thumbnailConfiguration.AvailableProfiles.Contains(this._thumbnailConfiguration.CurrentProfile)) {
|
||||
this._thumbnailConfiguration.AvailableProfiles.Add(this._thumbnailConfiguration.CurrentProfile);
|
||||
}
|
||||
|
||||
// Then, load the profile-specific configuration
|
||||
// IMPORTANT: Reset the configuration to clean state before loading
|
||||
// to avoid merging with existing default values
|
||||
string profileConfigPath = this.GetProfileConfigPath(currentProfile);
|
||||
|
||||
if (File.Exists(profileConfigPath)) {
|
||||
string profileRawData = File.ReadAllText(profileConfigPath);
|
||||
JsonSerializerSettings jsonSerializerSettings =
|
||||
new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||
JsonConvert.PopulateObject(profileRawData, this._thumbnailConfiguration, jsonSerializerSettings);
|
||||
} else {
|
||||
// Try to load from legacy config file for backwards compatibility
|
||||
string legacyConfigPath = this.GetConfigFileName();
|
||||
if (File.Exists(legacyConfigPath)) {
|
||||
string legacyRawData = File.ReadAllText(legacyConfigPath);
|
||||
JsonSerializerSettings jsonSerializerSettings =
|
||||
new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||
JsonConvert.PopulateObject(legacyRawData, this._thumbnailConfiguration, jsonSerializerSettings);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the values we just set (they might have been overwritten by profile load)
|
||||
this._thumbnailConfiguration.CurrentProfile = currentProfile;
|
||||
this._thumbnailConfiguration.ProfileReadOnly = profileReadOnly;
|
||||
// Re-scan profiles after loading in case the profile overwrote AvailableProfiles
|
||||
this._thumbnailConfiguration.AvailableProfiles.Clear();
|
||||
foreach (string profile in scannedProfiles) {
|
||||
this._thumbnailConfiguration.AvailableProfiles.Add(profile);
|
||||
}
|
||||
JsonConvert.PopulateObject(rawData, this._thumbnailConfiguration, jsonSerializerSettings);
|
||||
|
||||
// Validate data after loading it
|
||||
this._thumbnailConfiguration.ApplyRestrictions();
|
||||
}
|
||||
|
||||
public void Save() {
|
||||
// Save master configuration (contains ProfileReadOnly and CurrentProfile)
|
||||
this.SaveMasterConfig();
|
||||
|
||||
// If profile is read-only, don't save to the profile file
|
||||
if (!this._thumbnailConfiguration.ProfileReadOnly) {
|
||||
this.SaveProfileConfig();
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveMasterConfig() {
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
string directory = Path.GetDirectoryName(masterConfigPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) {
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Create a minimal master config with only ProfileReadOnly and CurrentProfile
|
||||
// AvailableProfiles is determined by scanning the folder, not saved here
|
||||
var masterConfig = new {
|
||||
CurrentProfile = this._thumbnailConfiguration.CurrentProfile ?? "Default",
|
||||
ProfileReadOnly = this._thumbnailConfiguration.ProfileReadOnly
|
||||
};
|
||||
|
||||
string rawData = JsonConvert.SerializeObject(masterConfig, Formatting.Indented);
|
||||
|
||||
try {
|
||||
File.WriteAllText(masterConfigPath, rawData);
|
||||
} catch (IOException) {
|
||||
// Ignore error if for some reason the updated config cannot be written down
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveProfileConfig() {
|
||||
string profileConfigPath = this.GetProfileConfigPath();
|
||||
string directory = Path.GetDirectoryName(profileConfigPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) {
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Serialize the full configuration to the profile file
|
||||
string rawData = JsonConvert.SerializeObject(this._thumbnailConfiguration, Formatting.Indented);
|
||||
string filename = this.GetConfigFileName();
|
||||
|
||||
try {
|
||||
File.WriteAllText(profileConfigPath, rawData);
|
||||
// Ensure the directory exists before saving
|
||||
string directory = Path.GetDirectoryName(filename);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) {
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
File.WriteAllText(filename, rawData);
|
||||
} catch (IOException) {
|
||||
// Ignore error if for some reason the updated config cannot be written down
|
||||
}
|
||||
}
|
||||
|
||||
private string GetMasterConfigPath() {
|
||||
return Path.Combine(PROFILES_DIRECTORY, MASTER_CONFIG_FILE);
|
||||
}
|
||||
|
||||
private string GetProfileConfigPath() {
|
||||
return this.GetProfileConfigPath(this._thumbnailConfiguration.CurrentProfile ?? "Default");
|
||||
}
|
||||
|
||||
private string GetProfileConfigPath(string profileName) {
|
||||
string sanitizedProfileName = this.SanitizeFileName(profileName);
|
||||
return Path.Combine(PROFILES_DIRECTORY, $"{sanitizedProfileName}.json");
|
||||
}
|
||||
|
||||
private string GetConfigFileName() {
|
||||
return string.IsNullOrEmpty(this._appConfig.ConfigFileName) ? ConfigurationStorage.CONFIGURATION_FILE_NAME
|
||||
: this._appConfig.ConfigFileName;
|
||||
}
|
||||
|
||||
private string SanitizeFileName(string fileName) {
|
||||
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||
foreach (char c in invalidChars) {
|
||||
fileName = fileName.Replace(c, '_');
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
private List<string> ScanAvailableProfiles() {
|
||||
List<string> profiles = new List<string>();
|
||||
|
||||
if (!Directory.Exists(PROFILES_DIRECTORY)) {
|
||||
profiles.Add("Default");
|
||||
return profiles;
|
||||
// If a custom config file is specified via command line, use it
|
||||
if (!string.IsNullOrEmpty(this._appConfig.ConfigFileName)) {
|
||||
return this._appConfig.ConfigFileName;
|
||||
}
|
||||
|
||||
try {
|
||||
foreach (string filePath in Directory.GetFiles(PROFILES_DIRECTORY, "*.json")) {
|
||||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||
|
||||
// Skip the master config file
|
||||
if (fileName.Equals(MASTER_CONFIG_FILE.Replace(".json", ""), StringComparison.OrdinalIgnoreCase)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the profile name
|
||||
if (!string.IsNullOrEmpty(fileName) && !profiles.Contains(fileName)) {
|
||||
profiles.Add(fileName);
|
||||
}
|
||||
}
|
||||
} catch (IOException) {
|
||||
// If there's an error scanning the directory, just return what we have
|
||||
// If using the Default profile or no profile is set, use the main config file
|
||||
if (string.IsNullOrEmpty(this._currentProfile) || this._currentProfile == "Default") {
|
||||
return Path.Combine(this._baseDirectory, CONFIGURATION_FILE_NAME);
|
||||
}
|
||||
|
||||
// Ensure Default is always in the list
|
||||
if (!profiles.Contains("Default")) {
|
||||
profiles.Add("Default");
|
||||
}
|
||||
|
||||
return profiles;
|
||||
// For named profiles, use the profile-specific config file in the Profiles folder
|
||||
string profilesFolder = Path.Combine(this._baseDirectory, PROFILES_FOLDER_NAME);
|
||||
return Path.Combine(profilesFolder, this._currentProfile + PROFILE_CONFIG_FILE_EXTENSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
285
src/Eve-O-Preview/Configuration/Implementation/ProfileManager.cs
Normal file
285
src/Eve-O-Preview/Configuration/Implementation/ProfileManager.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EveOPreview.Configuration.Implementation {
|
||||
class ProfileManager : IProfileManager {
|
||||
private const string PROFILES_FOLDER_NAME = "Profiles";
|
||||
private const string MASTER_CONFIG_FILE_NAME = "EVE-O-Preview-Master.json";
|
||||
private const string PROFILE_CONFIG_FILE_EXTENSION = ".json";
|
||||
private const string PROFILE_LOCK_MUTEX_PREFIX = "EVE-O-Preview_ProfileLock_";
|
||||
|
||||
private readonly IAppConfig _appConfig;
|
||||
private readonly IConfigurationStorage _configurationStorage;
|
||||
private readonly string _baseDirectory;
|
||||
private readonly Dictionary<string, Mutex> _acquiredLocks;
|
||||
private Mutex _currentProfileLock;
|
||||
|
||||
public ProfileManager(IAppConfig appConfig, IConfigurationStorage configurationStorage) {
|
||||
this._appConfig = appConfig;
|
||||
this._configurationStorage = configurationStorage;
|
||||
|
||||
// Get the base directory (where the main config file is located)
|
||||
// We'll use the application base directory
|
||||
this._baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
// Ensure Profiles folder exists
|
||||
this.EnsureProfilesFolderExists();
|
||||
|
||||
// Ensure master config exists
|
||||
this.EnsureMasterConfigExists();
|
||||
|
||||
this._acquiredLocks = new Dictionary<string, Mutex>();
|
||||
this._currentProfileLock = null;
|
||||
}
|
||||
|
||||
public System.Collections.Generic.List<string> GetAvailableProfiles() {
|
||||
string profilesPath = this.GetProfilesFolderPath();
|
||||
var profiles = new System.Collections.Generic.List<string> { "Default" };
|
||||
|
||||
if (Directory.Exists(profilesPath)) {
|
||||
var profileFiles = Directory.GetFiles(profilesPath, "*" + PROFILE_CONFIG_FILE_EXTENSION);
|
||||
foreach (var file in profileFiles) {
|
||||
string profileName = Path.GetFileNameWithoutExtension(file);
|
||||
if (!string.IsNullOrEmpty(profileName) && !profiles.Contains(profileName)) {
|
||||
profiles.Add(profileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public string GetActiveProfile() {
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
|
||||
if (!File.Exists(masterConfigPath)) {
|
||||
return "Default";
|
||||
}
|
||||
|
||||
try {
|
||||
string rawData = File.ReadAllText(masterConfigPath);
|
||||
var masterConfig = JsonConvert.DeserializeObject<MasterConfig>(rawData);
|
||||
return masterConfig?.ActiveProfile ?? "Default";
|
||||
} catch {
|
||||
return "Default";
|
||||
}
|
||||
}
|
||||
|
||||
public void SwitchProfile(string profileName) {
|
||||
if (string.IsNullOrEmpty(profileName)) {
|
||||
profileName = "Default";
|
||||
}
|
||||
|
||||
// Check if the profile is locked by another instance
|
||||
if (this.IsProfileLocked(profileName)) {
|
||||
MessageBox.Show(
|
||||
$"Cannot switch to profile '{profileName}' because it is already in use by another instance.",
|
||||
"Profile In Use",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current instance ID
|
||||
int instanceId = global::EveOPreview.Program.InstanceId;
|
||||
|
||||
// Get the current profile for this instance
|
||||
var profiles = this.GetProfilesList();
|
||||
string currentProfile = instanceId >= 0 && instanceId < profiles.Count
|
||||
? profiles[instanceId]
|
||||
: "Default";
|
||||
|
||||
// Save current configuration first
|
||||
this._configurationStorage.Save();
|
||||
|
||||
// Release current profile lock
|
||||
this.ReleaseProfileLock(currentProfile);
|
||||
|
||||
// Acquire new profile lock
|
||||
this.AcquireProfileLock(profileName);
|
||||
|
||||
// Update the Profiles array for this instance
|
||||
this.UpdateProfileForInstance(instanceId, profileName);
|
||||
|
||||
// Restart the application
|
||||
this.RestartApplication();
|
||||
}
|
||||
|
||||
public string GetProfileConfigPath(string profileName) {
|
||||
if (string.IsNullOrEmpty(profileName) || profileName == "Default") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Path.Combine(this.GetProfilesFolderPath(), profileName + PROFILE_CONFIG_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
private string GetProfilesFolderPath() {
|
||||
return Path.Combine(this._baseDirectory, PROFILES_FOLDER_NAME);
|
||||
}
|
||||
|
||||
private string GetMasterConfigPath() {
|
||||
return Path.Combine(this._baseDirectory, MASTER_CONFIG_FILE_NAME);
|
||||
}
|
||||
|
||||
private void EnsureProfilesFolderExists() {
|
||||
string profilesPath = this.GetProfilesFolderPath();
|
||||
if (!Directory.Exists(profilesPath)) {
|
||||
Directory.CreateDirectory(profilesPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureMasterConfigExists() {
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
|
||||
if (!File.Exists(masterConfigPath)) {
|
||||
var availableProfiles = this.GetAvailableProfiles();
|
||||
var defaultConfig = new MasterConfig {
|
||||
ActiveProfile = "Default",
|
||||
Profiles = availableProfiles
|
||||
};
|
||||
string rawData = JsonConvert.SerializeObject(defaultConfig, Formatting.Indented);
|
||||
File.WriteAllText(masterConfigPath, rawData);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveActiveProfile(string profileName) {
|
||||
// Read existing config to preserve Profiles array
|
||||
var existingConfig = this.LoadMasterConfig();
|
||||
if (existingConfig == null) {
|
||||
existingConfig = new MasterConfig { Profiles = this.GetAvailableProfiles() };
|
||||
}
|
||||
|
||||
existingConfig.ActiveProfile = profileName;
|
||||
string rawData = JsonConvert.SerializeObject(existingConfig, Formatting.Indented);
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
|
||||
try {
|
||||
File.WriteAllText(masterConfigPath, rawData);
|
||||
} catch (IOException) {
|
||||
// Ignore error if config cannot be written
|
||||
}
|
||||
}
|
||||
|
||||
private MasterConfig LoadMasterConfig() {
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
|
||||
if (!File.Exists(masterConfigPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
string rawData = File.ReadAllText(masterConfigPath);
|
||||
return JsonConvert.DeserializeObject<MasterConfig>(rawData);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void RestartApplication() {
|
||||
// Call the static method in Program which properly handles the mutex
|
||||
Program.RestartApplication();
|
||||
}
|
||||
|
||||
public List<string> GetProfilesList() {
|
||||
var masterConfig = this.LoadMasterConfig();
|
||||
if (masterConfig?.Profiles != null && masterConfig.Profiles.Count > 0) {
|
||||
return masterConfig.Profiles;
|
||||
}
|
||||
return this.GetAvailableProfiles();
|
||||
}
|
||||
|
||||
public string GetProfileForInstance(int instanceId) {
|
||||
var profiles = this.GetProfilesList();
|
||||
if (instanceId >= 0 && instanceId < profiles.Count) {
|
||||
return profiles[instanceId];
|
||||
}
|
||||
return "Default";
|
||||
}
|
||||
|
||||
public bool IsProfileLocked(string profileName) {
|
||||
if (string.IsNullOrEmpty(profileName) || profileName == "Default") {
|
||||
return false;
|
||||
}
|
||||
|
||||
string mutexName = PROFILE_LOCK_MUTEX_PREFIX + profileName;
|
||||
try {
|
||||
Mutex.OpenExisting(mutexName);
|
||||
return true;
|
||||
} catch (UnauthorizedAccessException) {
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AcquireProfileLock(string profileName) {
|
||||
if (string.IsNullOrEmpty(profileName) || profileName == "Default") {
|
||||
return true;
|
||||
}
|
||||
|
||||
string mutexName = PROFILE_LOCK_MUTEX_PREFIX + profileName;
|
||||
try {
|
||||
var mutex = new Mutex(true, mutexName);
|
||||
this._currentProfileLock = mutex;
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseProfileLock(string profileName) {
|
||||
if (this._currentProfileLock != null) {
|
||||
this._currentProfileLock.ReleaseMutex();
|
||||
this._currentProfileLock.Dispose();
|
||||
this._currentProfileLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateProfileForInstance(int instanceId, string profileName) {
|
||||
var masterConfig = this.LoadMasterConfig();
|
||||
if (masterConfig == null) {
|
||||
masterConfig = new MasterConfig { Profiles = this.GetAvailableProfiles() };
|
||||
}
|
||||
|
||||
// Ensure the Profiles array is large enough
|
||||
if (masterConfig.Profiles == null) {
|
||||
masterConfig.Profiles = this.GetAvailableProfiles();
|
||||
}
|
||||
|
||||
// Expand the array if necessary
|
||||
while (masterConfig.Profiles.Count <= instanceId) {
|
||||
masterConfig.Profiles.Add("Default");
|
||||
}
|
||||
|
||||
// Update the profile for this instance
|
||||
masterConfig.Profiles[instanceId] = profileName;
|
||||
|
||||
// Also update ActiveProfile for backward compatibility
|
||||
masterConfig.ActiveProfile = profileName;
|
||||
|
||||
// Save the updated config
|
||||
string rawData = JsonConvert.SerializeObject(masterConfig, Formatting.Indented);
|
||||
string masterConfigPath = this.GetMasterConfigPath();
|
||||
|
||||
try {
|
||||
File.WriteAllText(masterConfigPath, rawData);
|
||||
} catch (IOException) {
|
||||
// Ignore error if config cannot be written
|
||||
}
|
||||
}
|
||||
|
||||
private class MasterConfig {
|
||||
public string ActiveProfile { get; set; }
|
||||
public List<string> Profiles { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,6 @@ namespace EveOPreview.Configuration.Implementation {
|
||||
|
||||
this.CurrentProfile = "Default";
|
||||
this.AvailableProfiles = new List<string> { "Default" };
|
||||
this.ProfileReadOnly = false;
|
||||
|
||||
this.IconName = "";
|
||||
|
||||
@@ -305,10 +304,7 @@ namespace EveOPreview.Configuration.Implementation {
|
||||
public Rectangle DefaultThumbnailRegion { get; set; }
|
||||
|
||||
public string CurrentProfile { get; set; }
|
||||
[JsonIgnore]
|
||||
public List<string> AvailableProfiles { get; set; }
|
||||
[JsonProperty("ProfileReadOnly")]
|
||||
public bool ProfileReadOnly { get; set; }
|
||||
[JsonProperty("IconName")]
|
||||
public string IconName {
|
||||
get; set;
|
||||
|
||||
50
src/Eve-O-Preview/Configuration/Interface/IProfileManager.cs
Normal file
50
src/Eve-O-Preview/Configuration/Interface/IProfileManager.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EveOPreview.Configuration {
|
||||
public interface IProfileManager {
|
||||
/// <summary>
|
||||
/// Gets the list of available profile names from the Profiles folder
|
||||
/// </summary>
|
||||
List<string> GetAvailableProfiles();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currently active profile name from the master config
|
||||
/// </summary>
|
||||
string GetActiveProfile();
|
||||
|
||||
/// <summary>
|
||||
/// Switches to the specified profile, saves current config, updates master config, and restarts the application
|
||||
/// </summary>
|
||||
void SwitchProfile(string profileName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to a profile's config file
|
||||
/// </summary>
|
||||
string GetProfileConfigPath(string profileName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of profiles from the master config array
|
||||
/// </summary>
|
||||
List<string> GetProfilesList();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile name for the specified instance ID
|
||||
/// </summary>
|
||||
string GetProfileForInstance(int instanceId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a profile is currently locked by another instance
|
||||
/// </summary>
|
||||
bool IsProfileLocked(string profileName);
|
||||
|
||||
/// <summary>
|
||||
/// Acquires a lock on the specified profile for the current instance
|
||||
/// </summary>
|
||||
bool AcquireProfileLock(string profileName);
|
||||
|
||||
/// <summary>
|
||||
/// Releases the lock on the specified profile
|
||||
/// </summary>
|
||||
void ReleaseProfileLock(string profileName);
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,6 @@ namespace EveOPreview.Configuration {
|
||||
|
||||
string CurrentProfile { get; set; }
|
||||
List<string> AvailableProfiles { get; set; }
|
||||
bool ProfileReadOnly { get; set; }
|
||||
|
||||
string IconName { get; set; }
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace EveOPreview.Presenters {
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IThumbnailConfiguration _configuration;
|
||||
private readonly IConfigurationStorage _configurationStorage;
|
||||
private readonly IProfileManager _profileManager;
|
||||
private readonly IDictionary<string, IThumbnailDescription> _descriptionsCache;
|
||||
private bool _suppressSizeNotifications;
|
||||
|
||||
@@ -25,11 +26,13 @@ namespace EveOPreview.Presenters {
|
||||
#endregion
|
||||
|
||||
public MainFormPresenter(IApplicationController controller, IMainFormView view, IMediator mediator,
|
||||
IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage)
|
||||
IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage,
|
||||
IProfileManager profileManager)
|
||||
: base(controller, view) {
|
||||
this._mediator = mediator;
|
||||
this._configuration = configuration;
|
||||
this._configurationStorage = configurationStorage;
|
||||
this._profileManager = profileManager;
|
||||
|
||||
this._descriptionsCache = new Dictionary<string, IThumbnailDescription>();
|
||||
|
||||
@@ -44,6 +47,7 @@ namespace EveOPreview.Presenters {
|
||||
this.View.ThumbnailStateChanged = this.UpdateThumbnailState;
|
||||
this.View.DocumentationLinkActivated = this.OpenDocumentationLink;
|
||||
this.View.ApplicationExitRequested = this.ExitApplication;
|
||||
this.View.ProfileSwitchRequested = this.SwitchProfile;
|
||||
|
||||
this.View.IconName = this._configuration.IconName;
|
||||
}
|
||||
@@ -57,10 +61,23 @@ namespace EveOPreview.Presenters {
|
||||
this.View.Minimize();
|
||||
}
|
||||
|
||||
// Initialize the tray profile menu
|
||||
this.UpdateTrayProfileMenu();
|
||||
|
||||
this._mediator.Send(new StartService());
|
||||
this._suppressSizeNotifications = false;
|
||||
}
|
||||
|
||||
private void UpdateTrayProfileMenu() {
|
||||
var profiles = this._profileManager.GetAvailableProfiles();
|
||||
var currentProfile = this._profileManager.GetActiveProfile();
|
||||
this.View.UpdateTrayProfileMenu(profiles, currentProfile);
|
||||
}
|
||||
|
||||
private void SwitchProfile(string profileName) {
|
||||
this._profileManager.SwitchProfile(profileName);
|
||||
}
|
||||
|
||||
private void Minimize() {
|
||||
if (!this._configuration.MinimizeToTray) {
|
||||
return;
|
||||
@@ -132,7 +149,6 @@ namespace EveOPreview.Presenters {
|
||||
|
||||
this.View.AvailableProfiles = this._configuration.AvailableProfiles;
|
||||
this.View.CurrentProfile = this._configuration.CurrentProfile;
|
||||
this.View.ProfileReadOnly = this._configuration.ProfileReadOnly;
|
||||
|
||||
this.View.ToggleTrackingHotkey = this._configuration.ToggleTrackingHotkey;
|
||||
this.View.ToggleSingleProcessHotkey = this._configuration.ToggleSingleProcessHotkey;
|
||||
@@ -185,7 +201,6 @@ namespace EveOPreview.Presenters {
|
||||
|
||||
this._configuration.AvailableProfiles = this.View.AvailableProfiles;
|
||||
this._configuration.CurrentProfile = this.View.CurrentProfile;
|
||||
this._configuration.ProfileReadOnly = this.View.ProfileReadOnly;
|
||||
|
||||
this._configuration.ToggleTrackingHotkey = this.View.ToggleTrackingHotkey;
|
||||
this._configuration.ToggleSingleProcessHotkey = this.View.ToggleSingleProcessHotkey;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using EveOPreview.Configuration;
|
||||
using EveOPreview.Configuration.Implementation;
|
||||
using EveOPreview.Presenters;
|
||||
using EveOPreview.Services;
|
||||
using EveOPreview.View;
|
||||
@@ -9,17 +11,27 @@ using MediatR;
|
||||
|
||||
namespace EveOPreview {
|
||||
static class Program {
|
||||
private static string MUTEX_NAME = "EVE-O-Preview Single Instance Mutex";
|
||||
private const string MUTEX_PREFIX = "EVE-O-Preview_Instance_";
|
||||
private const string INSTANCE_ID_ARG = "--instance-id=";
|
||||
|
||||
private static Mutex _singleInstanceMutex;
|
||||
private static int _instanceId = 0;
|
||||
|
||||
/// <summary>The main entry point for the application.</summary>
|
||||
[STAThread]
|
||||
static void Main() {
|
||||
static void Main(string[] args) {
|
||||
// Parse instance ID from command line arguments, or auto-detect next available
|
||||
Program._instanceId = ParseInstanceId(args);
|
||||
|
||||
// If no instance ID was provided, find the next available one
|
||||
if (Program._instanceId == 0 && !HasInstanceIdArgument(args)) {
|
||||
Program._instanceId = FindNextAvailableInstanceId();
|
||||
}
|
||||
|
||||
// The very usual Mutex-based single-instance screening
|
||||
// 'token' variable is used to store reference to the instance Mutex
|
||||
// during the app lifetime
|
||||
Program._singleInstanceMutex = Program.GetInstanceToken();
|
||||
Program._singleInstanceMutex = Program.GetInstanceToken(Program._instanceId);
|
||||
|
||||
// If it was not possible to acquire the app token then another app instance is already running
|
||||
// Nothing to do here
|
||||
@@ -36,20 +48,57 @@ namespace EveOPreview {
|
||||
controller.Run<MainFormPresenter>();
|
||||
}
|
||||
|
||||
private static Mutex GetInstanceToken() {
|
||||
private static bool HasInstanceIdArgument(string[] args) {
|
||||
if (args == null || args.Length == 0) {
|
||||
return false;
|
||||
}
|
||||
return args.Any(a => a.StartsWith(INSTANCE_ID_ARG));
|
||||
}
|
||||
|
||||
private static int ParseInstanceId(string[] args) {
|
||||
if (args == null || args.Length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var arg = args.FirstOrDefault(a => a.StartsWith(INSTANCE_ID_ARG));
|
||||
if (arg != null && int.TryParse(arg.Substring(INSTANCE_ID_ARG.Length), out int id)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int FindNextAvailableInstanceId() {
|
||||
// Try instance IDs starting from 0, find the first one that's not in use
|
||||
for (int id = 0; id < 10; id++) {
|
||||
string mutexName = MUTEX_PREFIX + id;
|
||||
try {
|
||||
Mutex.OpenExisting(mutexName);
|
||||
// This instance ID is taken, try next
|
||||
} catch {
|
||||
// This instance ID is available
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return 0; // Fallback to 0 if all are taken
|
||||
}
|
||||
|
||||
private static Mutex GetInstanceToken(int instanceId) {
|
||||
string mutexName = MUTEX_PREFIX + instanceId;
|
||||
|
||||
// The code might look overcomplicated here for a single Mutex operation
|
||||
// Yet we had already experienced a Windows-level issue
|
||||
// where .NET finalizer thread was literally paralyzed by
|
||||
// a failed Mutex operation. That did lead to weird OutOfMemory
|
||||
// exceptions later
|
||||
try {
|
||||
Mutex.OpenExisting(Program.MUTEX_NAME);
|
||||
Mutex.OpenExisting(mutexName);
|
||||
// if that didn't fail then another instance is already running
|
||||
return null;
|
||||
} catch (UnauthorizedAccessException) {
|
||||
return null;
|
||||
} catch (Exception) {
|
||||
Mutex token = new Mutex(true, Program.MUTEX_NAME, out var result);
|
||||
Mutex token = new Mutex(true, mutexName, out var result);
|
||||
return result ? token : null;
|
||||
}
|
||||
}
|
||||
@@ -78,9 +127,13 @@ namespace EveOPreview {
|
||||
container.Register(typeof(IRequestHandler<, >), typeof(Program).Assembly);
|
||||
|
||||
// Configuration services
|
||||
container.Register<IConfigurationStorage>();
|
||||
container.Register<IAppConfig>();
|
||||
container.Register<IThumbnailConfiguration>();
|
||||
container.Register<IConfigurationStorage>();
|
||||
container.Register<IProfileManager>();
|
||||
|
||||
// Initialize profile system
|
||||
Program.InitializeProfileSystem(container);
|
||||
|
||||
// Application services
|
||||
container.Register<IThumbnailManager>();
|
||||
@@ -98,5 +151,58 @@ namespace EveOPreview {
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
private static void InitializeProfileSystem(IIocContainer container) {
|
||||
var profileManager = container.Resolve<IProfileManager>();
|
||||
var configurationStorage = container.Resolve<IConfigurationStorage>();
|
||||
var thumbnailConfiguration = container.Resolve<IThumbnailConfiguration>();
|
||||
|
||||
// Get the active profile for this instance based on instance ID
|
||||
string activeProfile = profileManager.GetProfileForInstance(Program._instanceId);
|
||||
|
||||
// Acquire the profile lock for this instance
|
||||
profileManager.AcquireProfileLock(activeProfile);
|
||||
|
||||
// Set the current profile in the configuration storage
|
||||
if (configurationStorage is ConfigurationStorage configStorage) {
|
||||
configStorage.CurrentProfile = activeProfile;
|
||||
}
|
||||
|
||||
// Update the thumbnail configuration with the active profile
|
||||
thumbnailConfiguration.CurrentProfile = activeProfile;
|
||||
thumbnailConfiguration.AvailableProfiles = profileManager.GetAvailableProfiles();
|
||||
}
|
||||
|
||||
public static void RestartApplication() {
|
||||
// Get the current executable path
|
||||
string executablePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
|
||||
if (string.IsNullOrEmpty(executablePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Release the mutex first so the new instance can start
|
||||
Program._singleInstanceMutex?.Dispose();
|
||||
Program._singleInstanceMutex = null;
|
||||
|
||||
// Small delay to ensure the mutex is fully released
|
||||
System.Threading.Thread.Sleep(100);
|
||||
|
||||
// Start a new instance of the application with the same instance ID
|
||||
try {
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo {
|
||||
FileName = executablePath,
|
||||
Arguments = INSTANCE_ID_ARG + Program._instanceId,
|
||||
UseShellExecute = true
|
||||
});
|
||||
} catch (Exception) {
|
||||
// If starting the new process fails, we're in a bad state
|
||||
// Just exit anyway
|
||||
}
|
||||
|
||||
// Exit the current application immediately
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
public static int InstanceId => Program._instanceId;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Threading;
|
||||
@@ -54,6 +55,11 @@ namespace EveOPreview.Services {
|
||||
private HotkeyHandler _toggleTrackingHotkey;
|
||||
private HotkeyHandler _toggleSingleProcessHotkey;
|
||||
private HotkeyHandler _toggleAllThumbnailsHotkey;
|
||||
private EventWaitHandle _toggleEvent;
|
||||
private Thread _toggleEventThread;
|
||||
private SynchronizationContext _syncContext;
|
||||
private const string TOGGLE_EVENT_NAME = "EVE-O-Preview_ToggleEvent";
|
||||
private bool _isToggleInitiator;
|
||||
#endregion
|
||||
|
||||
public ThumbnailManager(IMediator mediator, IThumbnailConfiguration configuration,
|
||||
@@ -76,6 +82,9 @@ namespace EveOPreview.Services {
|
||||
|
||||
this._thumbnailViews = new Dictionary<IntPtr, IThumbnailView>();
|
||||
|
||||
// Capture the current synchronization context (UI thread)
|
||||
this._syncContext = SynchronizationContext.Current;
|
||||
|
||||
// DispatcherTimer setup
|
||||
this._thumbnailUpdateTimer = new DispatcherTimer();
|
||||
this._thumbnailUpdateTimer.Tick += ThumbnailUpdateTimerTick;
|
||||
@@ -176,15 +185,34 @@ namespace EveOPreview.Services {
|
||||
var toggleAllThumbnailsKey = this._configuration.StringToKey(this._configuration.ToggleAllThumbnailsHotkey);
|
||||
this._toggleAllThumbnailsHotkey = new HotkeyHandler(mainHandle, toggleAllThumbnailsKey);
|
||||
this._toggleAllThumbnailsHotkey.Pressed += (object s, HandledEventArgs e) => {
|
||||
// Mark this instance as the initiator so we don't process our own event
|
||||
this._isToggleInitiator = true;
|
||||
|
||||
this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden;
|
||||
this._hideThumbnailsDelay = 0;
|
||||
this.RefreshThumbnails();
|
||||
|
||||
// Signal all other instances to toggle as well
|
||||
this._toggleEvent?.Set();
|
||||
|
||||
// Reset the event after a short delay so other instances can process it
|
||||
// Then clear the initiator flag
|
||||
System.Threading.Timer resetTimer = null;
|
||||
resetTimer = new System.Threading.Timer(_ => {
|
||||
this._toggleEvent?.Reset();
|
||||
this._isToggleInitiator = false;
|
||||
resetTimer?.Dispose();
|
||||
}, null, 50, System.Threading.Timeout.Infinite);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"Toggled all thumbnails: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}");
|
||||
e.Handled = true;
|
||||
};
|
||||
registered = this._toggleAllThumbnailsHotkey.Register();
|
||||
System.Diagnostics.Debug.WriteLine($"Toggle all thumbnails hotkey registration result: {registered}");
|
||||
|
||||
// Initialize the toggle event for multi-instance synchronization
|
||||
this.InitializeToggleEvent();
|
||||
}
|
||||
|
||||
public void ReRegisterHotkeys() {
|
||||
@@ -257,9 +285,25 @@ namespace EveOPreview.Services {
|
||||
var toggleAllThumbnailsKey = this._configuration.StringToKey(this._configuration.ToggleAllThumbnailsHotkey);
|
||||
this._toggleAllThumbnailsHotkey = new HotkeyHandler(mainHandle, toggleAllThumbnailsKey);
|
||||
this._toggleAllThumbnailsHotkey.Pressed += (object s, HandledEventArgs e) => {
|
||||
// Mark this instance as the initiator so we don't process our own event
|
||||
this._isToggleInitiator = true;
|
||||
|
||||
this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden;
|
||||
this._hideThumbnailsDelay = 0;
|
||||
this.RefreshThumbnails();
|
||||
|
||||
// Signal all other instances to toggle as well
|
||||
this._toggleEvent?.Set();
|
||||
|
||||
// Reset the event after a short delay so other instances can process it
|
||||
// Then clear the initiator flag
|
||||
System.Threading.Timer resetTimer = null;
|
||||
resetTimer = new System.Threading.Timer(_ => {
|
||||
this._toggleEvent?.Reset();
|
||||
this._isToggleInitiator = false;
|
||||
resetTimer?.Dispose();
|
||||
}, null, 50, System.Threading.Timeout.Infinite);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"Toggled all thumbnails: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}");
|
||||
e.Handled = true;
|
||||
@@ -267,6 +311,62 @@ namespace EveOPreview.Services {
|
||||
this._toggleAllThumbnailsHotkey.Register();
|
||||
}
|
||||
|
||||
private void InitializeToggleEvent() {
|
||||
bool created;
|
||||
try {
|
||||
// Create or open the named event - use ManualReset to wake all instances
|
||||
this._toggleEvent = new EventWaitHandle(false, EventResetMode.ManualReset, TOGGLE_EVENT_NAME, out created);
|
||||
if (!created) {
|
||||
// Event already exists, use it
|
||||
this._toggleEvent = EventWaitHandle.OpenExisting(TOGGLE_EVENT_NAME);
|
||||
}
|
||||
} catch {
|
||||
// Fallback: create a new one
|
||||
this._toggleEvent = new EventWaitHandle(false, EventResetMode.ManualReset, TOGGLE_EVENT_NAME);
|
||||
}
|
||||
|
||||
// Start a thread to listen for toggle events from other instances
|
||||
this._toggleEventThread = new Thread(this.ToggleEventListener) {
|
||||
IsBackground = true,
|
||||
Name = "ToggleEventListener"
|
||||
};
|
||||
this._toggleEventThread.Start();
|
||||
}
|
||||
|
||||
private void ToggleEventListener() {
|
||||
while (true) {
|
||||
try {
|
||||
// Wait for the toggle event
|
||||
this._toggleEvent?.WaitOne();
|
||||
|
||||
// Reset the event so we can wait again
|
||||
this._toggleEvent?.Reset();
|
||||
|
||||
// Skip processing if we initiated this toggle
|
||||
// Check inside the UI thread callback to avoid race conditions
|
||||
this._syncContext?.Post(_ => {
|
||||
// Double-check the flag on the UI thread after a small delay
|
||||
// to ensure the initiator's flag is still set
|
||||
System.Threading.Thread.Sleep(10);
|
||||
if (this._isToggleInitiator) {
|
||||
return; // Skip - we initiated this toggle
|
||||
}
|
||||
|
||||
this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden;
|
||||
this._hideThumbnailsDelay = 0;
|
||||
this.RefreshThumbnails();
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"Received toggle event: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}");
|
||||
}, null);
|
||||
} catch (ThreadAbortException) {
|
||||
// Thread is being aborted, exit gracefully
|
||||
break;
|
||||
} catch {
|
||||
// Ignore other errors and continue listening
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IThumbnailView GetClientByTitle(string title) {
|
||||
return _thumbnailViews.FirstOrDefault(x => x.Value.Title == title).Value;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,10 @@ namespace EveOPreview.View {
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
components = new System.ComponentModel.Container();
|
||||
RestoreWindowMenuItem = new ToolStripMenuItem();
|
||||
ExitMenuItem = new ToolStripMenuItem();
|
||||
TitleMenuItem = new ToolStripMenuItem();
|
||||
SeparatorMenuItem = new ToolStripSeparator();
|
||||
ProfileSeparatorMenuItem = new ToolStripSeparator();
|
||||
ProfilesMenuItem = new ToolStripMenuItem();
|
||||
ProfileReadOnlyMenuItem = new ToolStripMenuItem();
|
||||
ToolStripMenuItem RestoreWindowMenuItem;
|
||||
ToolStripMenuItem ExitMenuItem;
|
||||
ToolStripMenuItem TitleMenuItem;
|
||||
ToolStripSeparator SeparatorMenuItem;
|
||||
TabControl ContentTabControl;
|
||||
TabPage GeneralTabPage;
|
||||
Panel GeneralSettingsPanel;
|
||||
@@ -85,7 +82,8 @@ namespace EveOPreview.View {
|
||||
PickRegionButton = new Button();
|
||||
ProfileLabel = new Label();
|
||||
ProfileComboBox = new ComboBox();
|
||||
ProfileReadOnlyCheckBox = new CheckBox();
|
||||
SaveProfileButton = new Button();
|
||||
DeleteProfileButton = new Button();
|
||||
ThumbnailSnapRangeLabel = new Label();
|
||||
ThumbnailSnapRangeNumericEdit = new NumericUpDown();
|
||||
ThumbnailSnapToGridCheckBox = new CheckBox();
|
||||
@@ -135,6 +133,10 @@ namespace EveOPreview.View {
|
||||
DocumentationLink = new LinkLabel();
|
||||
NotifyIcon = new NotifyIcon(components);
|
||||
TrayMenu = new ContextMenuStrip(components);
|
||||
RestoreWindowMenuItem = new ToolStripMenuItem();
|
||||
ExitMenuItem = new ToolStripMenuItem();
|
||||
TitleMenuItem = new ToolStripMenuItem();
|
||||
SeparatorMenuItem = new ToolStripSeparator();
|
||||
ContentTabControl = new TabControl();
|
||||
GeneralTabPage = new TabPage();
|
||||
GeneralSettingsPanel = new Panel();
|
||||
@@ -214,26 +216,6 @@ namespace EveOPreview.View {
|
||||
SeparatorMenuItem.Name = "SeparatorMenuItem";
|
||||
SeparatorMenuItem.Size = new Size(150, 6);
|
||||
//
|
||||
// ProfileSeparatorMenuItem
|
||||
//
|
||||
ProfileSeparatorMenuItem.Name = "ProfileSeparatorMenuItem";
|
||||
ProfileSeparatorMenuItem.Size = new Size(150, 6);
|
||||
//
|
||||
// ProfilesMenuItem
|
||||
//
|
||||
ProfilesMenuItem.DropDownItems.Clear();
|
||||
ProfilesMenuItem.Name = "ProfilesMenuItem";
|
||||
ProfilesMenuItem.Size = new Size(153, 22);
|
||||
ProfilesMenuItem.Text = "Profiles";
|
||||
//
|
||||
// ProfileReadOnlyMenuItem
|
||||
//
|
||||
ProfileReadOnlyMenuItem.CheckOnClick = true;
|
||||
ProfileReadOnlyMenuItem.Name = "ProfileReadOnlyMenuItem";
|
||||
ProfileReadOnlyMenuItem.Size = new Size(153, 22);
|
||||
ProfileReadOnlyMenuItem.Text = "Read Only";
|
||||
ProfileReadOnlyMenuItem.Click += ProfileReadOnlyMenuItem_Click;
|
||||
//
|
||||
// ContentTabControl
|
||||
//
|
||||
ContentTabControl.Alignment = TabAlignment.Left;
|
||||
@@ -492,7 +474,8 @@ namespace EveOPreview.View {
|
||||
ThumbnailSettingsPanel.Controls.Add(PickRegionButton);
|
||||
ThumbnailSettingsPanel.Controls.Add(ProfileLabel);
|
||||
ThumbnailSettingsPanel.Controls.Add(ProfileComboBox);
|
||||
ThumbnailSettingsPanel.Controls.Add(ProfileReadOnlyCheckBox);
|
||||
ThumbnailSettingsPanel.Controls.Add(SaveProfileButton);
|
||||
ThumbnailSettingsPanel.Controls.Add(DeleteProfileButton);
|
||||
ThumbnailSettingsPanel.Controls.Add(ThumbnailSnapRangeLabel);
|
||||
ThumbnailSettingsPanel.Controls.Add(ThumbnailSnapRangeNumericEdit);
|
||||
ThumbnailSettingsPanel.Controls.Add(ThumbnailSnapToGridCheckBox);
|
||||
@@ -653,16 +636,27 @@ namespace EveOPreview.View {
|
||||
ProfileComboBox.TabIndex = 51;
|
||||
ProfileComboBox.SelectedIndexChanged += ProfileComboBox_SelectedIndexChanged;
|
||||
//
|
||||
// ProfileReadOnlyCheckBox
|
||||
// SaveProfileButton
|
||||
//
|
||||
ProfileReadOnlyCheckBox.AutoSize = true;
|
||||
ProfileReadOnlyCheckBox.Location = new Point(310, 278);
|
||||
ProfileReadOnlyCheckBox.Margin = new Padding(4);
|
||||
ProfileReadOnlyCheckBox.Name = "ProfileReadOnlyCheckBox";
|
||||
ProfileReadOnlyCheckBox.Size = new Size(107, 19);
|
||||
ProfileReadOnlyCheckBox.TabIndex = 54;
|
||||
ProfileReadOnlyCheckBox.Text = "Read Only";
|
||||
ProfileReadOnlyCheckBox.UseVisualStyleBackColor = true;
|
||||
SaveProfileButton.Location = new Point(179, 277);
|
||||
SaveProfileButton.Margin = new Padding(4);
|
||||
SaveProfileButton.Name = "SaveProfileButton";
|
||||
SaveProfileButton.Size = new Size(56, 21);
|
||||
SaveProfileButton.TabIndex = 52;
|
||||
SaveProfileButton.Text = "Save";
|
||||
SaveProfileButton.UseVisualStyleBackColor = true;
|
||||
SaveProfileButton.Click += SaveProfileButton_Click;
|
||||
//
|
||||
// DeleteProfileButton
|
||||
//
|
||||
DeleteProfileButton.Location = new Point(243, 277);
|
||||
DeleteProfileButton.Margin = new Padding(4);
|
||||
DeleteProfileButton.Name = "DeleteProfileButton";
|
||||
DeleteProfileButton.Size = new Size(56, 21);
|
||||
DeleteProfileButton.TabIndex = 53;
|
||||
DeleteProfileButton.Text = "Delete";
|
||||
DeleteProfileButton.UseVisualStyleBackColor = true;
|
||||
DeleteProfileButton.Click += DeleteProfileButton_Click;
|
||||
//
|
||||
// ThumbnailSnapRangeLabel
|
||||
//
|
||||
@@ -1473,7 +1467,7 @@ namespace EveOPreview.View {
|
||||
//
|
||||
TrayMenu.ImageScalingSize = new Size(24, 24);
|
||||
TrayMenu.Items.AddRange(
|
||||
new ToolStripItem[] { TitleMenuItem, RestoreWindowMenuItem, SeparatorMenuItem, ProfileSeparatorMenuItem, ProfilesMenuItem, ProfileReadOnlyMenuItem, ExitMenuItem });
|
||||
new ToolStripItem[] { TitleMenuItem, RestoreWindowMenuItem, SeparatorMenuItem, ExitMenuItem });
|
||||
TrayMenu.Name = "contextMenuStrip1";
|
||||
TrayMenu.Size = new Size(154, 76);
|
||||
//
|
||||
@@ -1536,13 +1530,6 @@ namespace EveOPreview.View {
|
||||
#endregion
|
||||
private NotifyIcon NotifyIcon;
|
||||
private ContextMenuStrip TrayMenu;
|
||||
private ToolStripMenuItem TitleMenuItem;
|
||||
private ToolStripMenuItem RestoreWindowMenuItem;
|
||||
private ToolStripMenuItem ExitMenuItem;
|
||||
private ToolStripMenuItem ProfilesMenuItem;
|
||||
private ToolStripMenuItem ProfileReadOnlyMenuItem;
|
||||
private ToolStripSeparator SeparatorMenuItem;
|
||||
private ToolStripSeparator ProfileSeparatorMenuItem;
|
||||
private TabPage ZoomTabPage;
|
||||
private CheckBox EnableClientLayoutTrackingCheckBox;
|
||||
private CheckBox HideActiveClientThumbnailCheckBox;
|
||||
@@ -1591,7 +1578,8 @@ namespace EveOPreview.View {
|
||||
private Label RegionHeightLabel;
|
||||
private Button PickRegionButton;
|
||||
private ComboBox ProfileComboBox;
|
||||
private CheckBox ProfileReadOnlyCheckBox;
|
||||
private Button SaveProfileButton;
|
||||
private Button DeleteProfileButton;
|
||||
private Label ProfileLabel;
|
||||
private Label ThumbnailSnapRangeLabel;
|
||||
private NumericUpDown ThumbnailSnapRangeNumericEdit;
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace EveOPreview.View {
|
||||
private Size _minimumSize;
|
||||
private Size _maximumSize;
|
||||
private string _iconName;
|
||||
private string _lastSetProfile;
|
||||
#endregion
|
||||
|
||||
public MainForm(ApplicationContext context) {
|
||||
@@ -46,6 +45,9 @@ namespace EveOPreview.View {
|
||||
// Add mouse wheel event handlers for aspect ratio maintenance
|
||||
this.ThumbnailsWidthNumericEdit.MouseWheel += ThumbnailSizeNumeric_MouseWheel;
|
||||
this.ThumbnailsHeightNumericEdit.MouseWheel += ThumbnailSizeNumeric_MouseWheel;
|
||||
|
||||
// Set tray icon text with instance ID
|
||||
this.SetTrayIconText();
|
||||
}
|
||||
|
||||
public bool MinimizeToTray {
|
||||
@@ -303,6 +305,15 @@ namespace EveOPreview.View {
|
||||
}
|
||||
}
|
||||
|
||||
public string CurrentProfile {
|
||||
get => this.ProfileComboBox.Text;
|
||||
set {
|
||||
if (this.ProfileComboBox.Items.Contains(value)) {
|
||||
this.ProfileComboBox.SelectedItem = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> AvailableProfiles {
|
||||
get => this.ProfileComboBox.Items.Cast<string>().ToList();
|
||||
set {
|
||||
@@ -310,85 +321,36 @@ namespace EveOPreview.View {
|
||||
foreach (var profile in value) {
|
||||
this.ProfileComboBox.Items.Add(profile);
|
||||
}
|
||||
this.UpdateTrayProfilesMenu(value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ProfileReadOnly {
|
||||
get => this.ProfileReadOnlyCheckBox.Checked;
|
||||
set {
|
||||
this.ProfileReadOnlyCheckBox.Checked = value;
|
||||
this.ProfileReadOnlyMenuItem.Checked = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string CurrentProfile {
|
||||
get => this.ProfileComboBox.Text;
|
||||
set {
|
||||
this._lastSetProfile = value;
|
||||
if (this.ProfileComboBox.Items.Contains(value)) {
|
||||
this.ProfileComboBox.SelectedItem = value;
|
||||
}
|
||||
this.UpdateTrayProfilesMenuCheckedState();
|
||||
}
|
||||
}
|
||||
|
||||
private void ProfileComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if (!this._suppressEvents && this.ProfileComboBox.SelectedItem != null) {
|
||||
string newProfile = this.ProfileComboBox.SelectedItem.ToString();
|
||||
// Only restart if this is a user-initiated change (not during initial load)
|
||||
if (newProfile != this._lastSetProfile) {
|
||||
this._lastSetProfile = newProfile;
|
||||
// Save ONLY the master config, not the profile file
|
||||
// This prevents corrupting the target profile with current settings
|
||||
SaveMasterOnly();
|
||||
Application.Restart();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
if (!this._suppressEvents) {
|
||||
this.ApplicationSettingsChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveMasterOnly() {
|
||||
// Set to read-only temporarily so Save() only saves master config
|
||||
bool originalReadOnly = this.ProfileReadOnlyCheckBox.Checked;
|
||||
this.ProfileReadOnlyCheckBox.Checked = true;
|
||||
this.ApplicationSettingsChanged?.Invoke();
|
||||
this.ProfileReadOnlyCheckBox.Checked = originalReadOnly;
|
||||
}
|
||||
|
||||
private void UpdateTrayProfilesMenu(List<string> profiles) {
|
||||
this._suppressEvents = true;
|
||||
this.ProfilesMenuItem.DropDownItems.Clear();
|
||||
|
||||
foreach (string profile in profiles) {
|
||||
var menuItem = new ToolStripMenuItem(profile);
|
||||
if (profile == this.CurrentProfile) {
|
||||
menuItem.Checked = true;
|
||||
}
|
||||
menuItem.Click += (sender, e) => {
|
||||
if (!this._suppressEvents) {
|
||||
this.CurrentProfile = profile;
|
||||
// Save ONLY the master config, not the profile file
|
||||
bool originalReadOnly = this.ProfileReadOnlyCheckBox.Checked;
|
||||
this.ProfileReadOnlyCheckBox.Checked = true;
|
||||
private void SaveProfileButton_Click(object sender, EventArgs e) {
|
||||
using (var inputDialog = new InputDialog("Save Profile", "Enter profile name:")) {
|
||||
if (inputDialog.ShowDialog() == DialogResult.OK) {
|
||||
string profileName = inputDialog.InputText;
|
||||
if (!string.IsNullOrWhiteSpace(profileName)) {
|
||||
this.ProfileComboBox.Items.Add(profileName);
|
||||
this.ProfileComboBox.SelectedItem = profileName;
|
||||
this.ApplicationSettingsChanged?.Invoke();
|
||||
this.ProfileReadOnlyCheckBox.Checked = originalReadOnly;
|
||||
Application.Restart();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
};
|
||||
this.ProfilesMenuItem.DropDownItems.Add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
this._suppressEvents = false;
|
||||
}
|
||||
|
||||
private void UpdateTrayProfilesMenuCheckedState() {
|
||||
this._suppressEvents = true;
|
||||
foreach (ToolStripMenuItem item in this.ProfilesMenuItem.DropDownItems) {
|
||||
item.Checked = (item.Text == this.CurrentProfile);
|
||||
private void DeleteProfileButton_Click(object sender, EventArgs e) {
|
||||
if (this.ProfileComboBox.SelectedItem != null) {
|
||||
string selectedProfile = this.ProfileComboBox.SelectedItem.ToString();
|
||||
if (selectedProfile != "Default") {
|
||||
this.ProfileComboBox.Items.Remove(selectedProfile);
|
||||
this.ApplicationSettingsChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
this._suppressEvents = false;
|
||||
}
|
||||
|
||||
public new void Show() {// Registers the current instance as the application's Main Form
|
||||
@@ -460,6 +422,71 @@ namespace EveOPreview.View {
|
||||
|
||||
public Action DocumentationLinkActivated { get; set; }
|
||||
|
||||
public Action<string> ProfileSwitchRequested { get; set; }
|
||||
|
||||
public void UpdateTrayProfileMenu(List<string> profiles, string currentProfile) {
|
||||
// Clear existing items from the tray menu
|
||||
this.TrayMenu.Items.Clear();
|
||||
|
||||
// Add title
|
||||
ToolStripMenuItem titleMenuItem = new ToolStripMenuItem();
|
||||
titleMenuItem.Enabled = false;
|
||||
titleMenuItem.Name = "TitleMenuItem";
|
||||
titleMenuItem.Size = new System.Drawing.Size(200, 22);
|
||||
titleMenuItem.Text = "EVE-O-Preview";
|
||||
this.TrayMenu.Items.Add(titleMenuItem);
|
||||
|
||||
// Add restore option
|
||||
ToolStripMenuItem restoreMenuItem = new ToolStripMenuItem();
|
||||
restoreMenuItem.Name = "RestoreWindowMenuItem";
|
||||
restoreMenuItem.Size = new System.Drawing.Size(200, 22);
|
||||
restoreMenuItem.Text = "Restore";
|
||||
restoreMenuItem.Click += this.RestoreMainForm_Handler;
|
||||
this.TrayMenu.Items.Add(restoreMenuItem);
|
||||
|
||||
// Add separator
|
||||
ToolStripSeparator separatorMenuItem = new ToolStripSeparator();
|
||||
separatorMenuItem.Name = "SeparatorMenuItem";
|
||||
separatorMenuItem.Size = new System.Drawing.Size(200, 6);
|
||||
this.TrayMenu.Items.Add(separatorMenuItem);
|
||||
|
||||
// Add profile submenu
|
||||
ToolStripMenuItem profileMenuItem = new ToolStripMenuItem();
|
||||
profileMenuItem.Name = "ProfileMenuItem";
|
||||
profileMenuItem.Size = new System.Drawing.Size(200, 22);
|
||||
profileMenuItem.Text = "Profiles";
|
||||
|
||||
foreach (var profile in profiles) {
|
||||
ToolStripMenuItem profileItem = new ToolStripMenuItem();
|
||||
profileItem.Name = "Profile_" + profile;
|
||||
profileItem.Size = new System.Drawing.Size(180, 22);
|
||||
profileItem.Text = profile;
|
||||
profileItem.Checked = (profile == currentProfile);
|
||||
|
||||
profileItem.Click += (sender, e) => {
|
||||
this.ProfileSwitchRequested?.Invoke(profile);
|
||||
};
|
||||
|
||||
profileMenuItem.DropDownItems.Add(profileItem);
|
||||
}
|
||||
|
||||
this.TrayMenu.Items.Add(profileMenuItem);
|
||||
|
||||
// Add final separator
|
||||
ToolStripSeparator finalSeparatorMenuItem = new ToolStripSeparator();
|
||||
finalSeparatorMenuItem.Name = "FinalSeparatorMenuItem";
|
||||
finalSeparatorMenuItem.Size = new System.Drawing.Size(200, 6);
|
||||
this.TrayMenu.Items.Add(finalSeparatorMenuItem);
|
||||
|
||||
// Add exit option
|
||||
ToolStripMenuItem exitMenuItem = new ToolStripMenuItem();
|
||||
exitMenuItem.Name = "ExitMenuItem";
|
||||
exitMenuItem.Size = new System.Drawing.Size(200, 22);
|
||||
exitMenuItem.Text = "Exit";
|
||||
exitMenuItem.Click += this.ExitMenuItemClick_Handler;
|
||||
this.TrayMenu.Items.Add(exitMenuItem);
|
||||
}
|
||||
|
||||
#region UI events
|
||||
private void ContentTabControl_DrawItem(object sender, DrawItemEventArgs e) {
|
||||
TabControl control = (TabControl)sender;
|
||||
@@ -673,12 +700,6 @@ namespace EveOPreview.View {
|
||||
private void ExitMenuItemClick_Handler(object sender, EventArgs e) {
|
||||
this.ApplicationExitRequested?.Invoke();
|
||||
}
|
||||
|
||||
private void ProfileReadOnlyMenuItem_Click(object sender, EventArgs e) {
|
||||
if (!this._suppressEvents) {
|
||||
this.ApplicationSettingsChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void InitZoomAnchorMap() {
|
||||
@@ -717,6 +738,12 @@ namespace EveOPreview.View {
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTrayIconText() {
|
||||
// Get the instance ID from Program
|
||||
int instanceId = EveOPreview.Program.InstanceId;
|
||||
this.NotifyIcon.Text = $"EVE-O-Preview [{instanceId}]";
|
||||
}
|
||||
|
||||
private void AnimationStyleCombo_SelectedIndexChanged(object sender, EventArgs e) {}
|
||||
|
||||
private void GeneralSettingsPanel_Paint(object sender, PaintEventArgs e) {}
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace EveOPreview.View {
|
||||
|
||||
string CurrentProfile { get; set; }
|
||||
List<string> AvailableProfiles { get; set; }
|
||||
bool ProfileReadOnly { get; set; }
|
||||
|
||||
string ToggleTrackingHotkey { get; set; }
|
||||
string ToggleSingleProcessHotkey { get; set; }
|
||||
@@ -64,6 +63,9 @@ namespace EveOPreview.View {
|
||||
void RemoveThumbnails(IList<IThumbnailDescription> thumbnails);
|
||||
void RefreshZoomSettings();
|
||||
|
||||
void UpdateTrayProfileMenu(List<string> profiles, string currentProfile);
|
||||
Action<string> ProfileSwitchRequested { get; set; }
|
||||
|
||||
Action ApplicationExitRequested { get; set; }
|
||||
Action FormActivated { get; set; }
|
||||
Action FormMinimized { get; set; }
|
||||
|
||||
91
src/bin/net8.0-windows8.0/EVE-O-Preview.deps.json
Normal file
91
src/bin/net8.0-windows8.0/EVE-O-Preview.deps.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v8.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v8.0": {
|
||||
"EVE-O-Preview/1.0.0": {
|
||||
"dependencies": {
|
||||
"LightInject": "7.0.1",
|
||||
"MediatR": "9.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.NET.ILLink.Tasks": "8.0.8",
|
||||
"Newtonsoft.Json": "13.0.3"
|
||||
},
|
||||
"runtime": {
|
||||
"EVE-O-Preview.dll": {}
|
||||
}
|
||||
},
|
||||
"LightInject/7.0.1": {
|
||||
"runtime": {
|
||||
"lib/net8.0/LightInject.dll": {
|
||||
"assemblyVersion": "7.0.1.0",
|
||||
"fileVersion": "7.0.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MediatR/9.0.0": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.1/MediatR.dll": {
|
||||
"assemblyVersion": "9.0.0.0",
|
||||
"fileVersion": "9.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {},
|
||||
"Microsoft.NET.ILLink.Tasks/8.0.8": {},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"runtime": {
|
||||
"lib/net6.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "13.0.0.0",
|
||||
"fileVersion": "13.0.3.27908"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"EVE-O-Preview/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"LightInject/7.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-aw4ayG2Pe68i+85ws8zYk7MPCKjEd4DeBoTqVvmjA2cfpYYNnw+v0E5T3PKdriKaxdKF+eUzlnxWWZnYK/gx4w==",
|
||||
"path": "lightinject/7.0.1",
|
||||
"hashPath": "lightinject.7.0.1.nupkg.sha512"
|
||||
},
|
||||
"MediatR/9.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8b3UYNxegHVYcJMG2zH8wn+YqxLvXG+eMfj0cMCq/jTW72p6O3PCKMkrIv0mqyxdW7bA4gblsocw7n+/9Akg5g==",
|
||||
"path": "mediatr/9.0.0",
|
||||
"hashPath": "mediatr.9.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.CSharp/4.7.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
||||
"path": "microsoft.csharp/4.7.0",
|
||||
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NET.ILLink.Tasks/8.0.8": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-P8wR6MUWwYXIjPJuBaZgo5zlI/GWI6QEAo6NyVIbPefa9CCkohYu7dP2rD/mrqnjEqfRHyl+h9VZrDoGpELqYg==",
|
||||
"path": "microsoft.net.illink.tasks/8.0.8",
|
||||
"hashPath": "microsoft.net.illink.tasks.8.0.8.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
|
||||
"path": "newtonsoft.json/13.0.3",
|
||||
"hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/bin/net8.0-windows8.0/EVE-O-Preview.runtimeconfig.json
Normal file
18
src/bin/net8.0-windows8.0/EVE-O-Preview.runtimeconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net8.0",
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "8.0.0"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.WindowsDesktop.App",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
],
|
||||
"configProperties": {
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user