mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-11-29 14:38:21 +01:00
Compare commits
3 Commits
extensions
...
a58a1b347a
| Author | SHA1 | Date | |
|---|---|---|---|
|
a58a1b347a
|
|||
|
37303ddf02
|
|||
|
f8417706e1
|
@@ -12,8 +12,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetImpl.CefSharp", "windo
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.WinForms.Legacy", "windows\TweetLib.WinForms.Legacy\TweetLib.WinForms.Legacy.csproj", "{B54E732A-4090-4DAA-9ABD-311368C17B68}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.WinForms.Legacy", "windows\TweetLib.WinForms.Legacy\TweetLib.WinForms.Legacy.csproj", "{B54E732A-4090-4DAA-9ABD-311368C17B68}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Api", "lib\TweetLib.Api\TweetLib.Api.csproj", "{85596C10-F76E-4619-9CC6-6C1593880F83}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Core", "lib\TweetLib.Core\TweetLib.Core.csproj", "{93BA3CB4-A812-4949-B07D-8D393FB38937}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Core", "lib\TweetLib.Core\TweetLib.Core.csproj", "{93BA3CB4-A812-4949-B07D-8D393FB38937}"
|
||||||
@@ -56,10 +54,6 @@ Global
|
|||||||
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Debug|x86.Build.0 = Debug|x86
|
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Debug|x86.Build.0 = Debug|x86
|
||||||
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Release|x86.ActiveCfg = Release|x86
|
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Release|x86.ActiveCfg = Release|x86
|
||||||
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Release|x86.Build.0 = Release|x86
|
{B54E732A-4090-4DAA-9ABD-311368C17B68}.Release|x86.Build.0 = Release|x86
|
||||||
{85596C10-F76E-4619-9CC6-6C1593880F83}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{85596C10-F76E-4619-9CC6-6C1593880F83}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{85596C10-F76E-4619-9CC6-6C1593880F83}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{85596C10-F76E-4619-9CC6-6C1593880F83}.Release|x86.Build.0 = Release|x86
|
|
||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.ActiveCfg = Debug|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.Build.0 = Debug|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.Build.0 = Debug|x86
|
||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.ActiveCfg = Release|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
namespace TweetLib.Api.Data {
|
|
||||||
public readonly struct NamespacedResource {
|
|
||||||
public Resource Namespace { get; }
|
|
||||||
public Resource Path { get; }
|
|
||||||
|
|
||||||
public NamespacedResource(Resource ns, Resource path) {
|
|
||||||
Namespace = ns;
|
|
||||||
Path = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Equals(NamespacedResource other) {
|
|
||||||
return Namespace.Equals(other.Namespace) && Path.Equals(other.Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) {
|
|
||||||
return obj is NamespacedResource other && Equals(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(NamespacedResource left, NamespacedResource right) {
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(NamespacedResource left, NamespacedResource right) {
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode() {
|
|
||||||
unchecked {
|
|
||||||
return (Namespace.GetHashCode() * 397) ^ Path.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return $"{Namespace}:{Path}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
namespace TweetLib.Api.Data.Notification {
|
|
||||||
/// <summary>
|
|
||||||
/// Allows extensions to decide which screen to use for notifications.
|
|
||||||
///
|
|
||||||
/// Every registered provider becomes available in the Options dialog and has to be explicitly selected by the user. Only one provider
|
|
||||||
/// can be active at any given time.
|
|
||||||
/// </summary>
|
|
||||||
public interface IDesktopNotificationScreenProvider {
|
|
||||||
/// <summary>
|
|
||||||
/// A unique identifier of this provider. Only needs to be unique within the scope of this plugin.
|
|
||||||
/// </summary>
|
|
||||||
Resource Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Text displayed in the user interface.
|
|
||||||
/// </summary>
|
|
||||||
string DisplayName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a screen that will be used to display the next desktop notification.
|
|
||||||
///
|
|
||||||
/// If the return value is <c>null</c> or a screen that is not present in <see cref="IScreenLayout.AllScreens" />, desktop
|
|
||||||
/// notifications will be temporarily paused and this method will be called again after an unspecified amount of time (but
|
|
||||||
/// not sooner than 1 second since the last call).
|
|
||||||
/// </summary>
|
|
||||||
IScreen? PickScreen(IScreenLayout layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace TweetLib.Api.Data.Notification {
|
|
||||||
public interface IScreen {
|
|
||||||
ScreenBounds Bounds { get; }
|
|
||||||
string Name { get; }
|
|
||||||
bool IsPrimary { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace TweetLib.Api.Data.Notification {
|
|
||||||
public interface IScreenLayout {
|
|
||||||
IScreen PrimaryScreen { get; }
|
|
||||||
IScreen TweetDuckScreen { get; }
|
|
||||||
List<IScreen> AllScreens { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
namespace TweetLib.Api.Data.Notification {
|
|
||||||
public readonly struct ScreenBounds {
|
|
||||||
public int X1 { get; }
|
|
||||||
public int Y1 { get; }
|
|
||||||
public int Width { get; }
|
|
||||||
public int Height { get; }
|
|
||||||
|
|
||||||
public int X2 => X1 + Width;
|
|
||||||
public int Y2 => Y1 + Height;
|
|
||||||
|
|
||||||
public ScreenBounds(int x1, int y1, int width, int height) {
|
|
||||||
X1 = x1;
|
|
||||||
Y1 = y1;
|
|
||||||
Width = width;
|
|
||||||
Height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace TweetLib.Api.Data {
|
|
||||||
public readonly struct Resource {
|
|
||||||
private const string ValidCharacterPattern = "^[a-z0-9_]+$";
|
|
||||||
private static readonly Regex ValidCharacterRegex = new Regex(ValidCharacterPattern, RegexOptions.Compiled);
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
public Resource(string name) {
|
|
||||||
if (!ValidCharacterRegex.IsMatch(name)) {
|
|
||||||
throw new ArgumentException("Resource name must match the regex: " + ValidCharacterPattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Equals(Resource other) {
|
|
||||||
return Name == other.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) {
|
|
||||||
return obj is Resource other && Equals(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(Resource left, Resource right) {
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(Resource left, Resource right) {
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode() {
|
|
||||||
return Name.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace TweetLib.Api {
|
|
||||||
public interface ITweetDuckApi {
|
|
||||||
T? FindService<T>() where T : class, ITweetDuckService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
namespace TweetLib.Api {
|
|
||||||
public interface ITweetDuckService {}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
using TweetLib.Api.Data.Notification;
|
|
||||||
|
|
||||||
namespace TweetLib.Api.Service {
|
|
||||||
public interface INotificationService : ITweetDuckService {
|
|
||||||
void RegisterDesktopNotificationScreenProvider(IDesktopNotificationScreenProvider provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using TweetLib.Api.Data;
|
|
||||||
|
|
||||||
namespace TweetLib.Api {
|
|
||||||
public abstract class TweetDuckExtension {
|
|
||||||
/// <summary>
|
|
||||||
/// Unique identifier of the extension.
|
|
||||||
/// </summary>
|
|
||||||
public abstract Resource Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the extension is loaded on startup, or enabled at runtime.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void Enable(ITweetDuckApi api);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<Configurations>Debug;Release</Configurations>
|
|
||||||
<Platforms>x86;x64</Platforms>
|
|
||||||
<LangVersion>10</LangVersion>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\..\Version.cs" Link="Version.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -5,8 +5,6 @@ using TweetLib.Browser.Request;
|
|||||||
using TweetLib.Core.Application;
|
using TweetLib.Core.Application;
|
||||||
using TweetLib.Core.Features;
|
using TweetLib.Core.Features;
|
||||||
using TweetLib.Core.Features.Plugins;
|
using TweetLib.Core.Features.Plugins;
|
||||||
using TweetLib.Core.Resources;
|
|
||||||
using TweetLib.Core.Systems.Api;
|
|
||||||
using TweetLib.Core.Systems.Configuration;
|
using TweetLib.Core.Systems.Configuration;
|
||||||
using TweetLib.Core.Systems.Logging;
|
using TweetLib.Core.Systems.Logging;
|
||||||
using TweetLib.Utils.Static;
|
using TweetLib.Utils.Static;
|
||||||
@@ -23,11 +21,8 @@ namespace TweetLib.Core {
|
|||||||
internal static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
|
internal static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
|
||||||
internal static readonly string GuidePath = Path.Combine(ProgramPath, "guide");
|
internal static readonly string GuidePath = Path.Combine(ProgramPath, "guide");
|
||||||
|
|
||||||
public static readonly string ExtensionPath = Path.Combine(ProgramPath, "extensions");
|
public static readonly string StoragePath = IsPortable ? Path.Combine(ProgramPath, "portable", "storage") : GetDataFolder();
|
||||||
public static readonly string StoragePath = IsPortable ? Path.Combine(ProgramPath, "portable", "storage") : GetDataFolder();
|
public static readonly string LogoPath = Path.Combine(ResourcesPath, "images/logo.png");
|
||||||
public static readonly string LogoPath = Path.Combine(ResourcesPath, "images/logo.png");
|
|
||||||
|
|
||||||
public static ApiImplementation Api { get; } = new ();
|
|
||||||
|
|
||||||
public static Logger Logger { get; } = new (Path.Combine(StoragePath, "TD_Log.txt"), Setup.IsDebugLogging);
|
public static Logger Logger { get; } = new (Path.Combine(StoragePath, "TD_Log.txt"), Setup.IsDebugLogging);
|
||||||
public static ConfigManager ConfigManager { get; } = Setup.CreateConfigManager(StoragePath);
|
public static ConfigManager ConfigManager { get; } = Setup.CreateConfigManager(StoragePath);
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using TweetLib.Api;
|
|
||||||
using TweetLib.Core.Systems.Api;
|
|
||||||
|
|
||||||
namespace TweetLib.Core.Features.Extensions {
|
|
||||||
public static class ExtensionLoader {
|
|
||||||
public static void LoadAllInFolder(string extensionFolder) {
|
|
||||||
if (!Directory.Exists(extensionFolder)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
foreach (string file in Directory.EnumerateFiles(extensionFolder, "*.dll", SearchOption.TopDirectoryOnly)) {
|
|
||||||
try {
|
|
||||||
Assembly assembly = Assembly.LoadFile(file);
|
|
||||||
foreach (Type type in assembly.GetTypes()) {
|
|
||||||
if (typeof(TweetDuckExtension).IsAssignableFrom(type) && Activator.CreateInstance(type) is TweetDuckExtension extension) {
|
|
||||||
EnableExtension(extension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
App.ErrorHandler.HandleException("Extension Error", "Could not load extension: " + Path.GetFileNameWithoutExtension(file), true, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DirectoryNotFoundException) {
|
|
||||||
// ignore
|
|
||||||
} catch (Exception e) {
|
|
||||||
App.ErrorHandler.HandleException("Extension Error", "Could not load extensions.", true, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EnableExtension(TweetDuckExtension extension) {
|
|
||||||
ApiImplementation apiImplementation = App.Api;
|
|
||||||
apiImplementation.CurrentExtension = extension;
|
|
||||||
extension.Enable(apiImplementation);
|
|
||||||
apiImplementation.CurrentExtension = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using TweetLib.Api;
|
|
||||||
|
|
||||||
namespace TweetLib.Core.Systems.Api {
|
|
||||||
public class ApiImplementation : ITweetDuckApi {
|
|
||||||
public TweetDuckExtension? CurrentExtension { get; internal set; }
|
|
||||||
|
|
||||||
private readonly Dictionary<Type, ITweetDuckService> services = new Dictionary<Type, ITweetDuckService>();
|
|
||||||
|
|
||||||
internal ApiImplementation() {}
|
|
||||||
|
|
||||||
public void RegisterService<T>(T service) where T : class, ITweetDuckService {
|
|
||||||
if (!typeof(T).IsInterface) {
|
|
||||||
throw new ArgumentException("Api service implementation must be registered with its interface type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
services.Add(typeof(T), service);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T? FindService<T>() where T : class, ITweetDuckService {
|
|
||||||
return services.TryGetValue(typeof(T), out ITweetDuckService? service) ? service as T : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ using TweetLib.Utils.Static;
|
|||||||
|
|
||||||
namespace TweetLib.Core.Systems.Configuration {
|
namespace TweetLib.Core.Systems.Configuration {
|
||||||
public abstract class ConfigManager {
|
public abstract class ConfigManager {
|
||||||
public static TypeConverterRegistry ConverterRegistry { get; } = new ();
|
protected static TypeConverterRegistry ConverterRegistry { get; } = new ();
|
||||||
|
|
||||||
static ConfigManager() {
|
static ConfigManager() {
|
||||||
ConverterRegistry.Register(typeof(WindowState), new BasicTypeConverter<WindowState> {
|
ConverterRegistry.Register(typeof(WindowState), new BasicTypeConverter<WindowState> {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\TweetLib.Api\TweetLib.Api.csproj" />
|
|
||||||
<ProjectReference Include="..\TweetLib.Browser\TweetLib.Browser.csproj" />
|
<ProjectReference Include="..\TweetLib.Browser\TweetLib.Browser.csproj" />
|
||||||
<ProjectReference Include="..\TweetLib.Utils\TweetLib.Utils.csproj" />
|
<ProjectReference Include="..\TweetLib.Utils\TweetLib.Utils.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CefSharp.Common.NETCore" Version="107.1.90" />
|
<PackageReference Include="CefSharp.Common.NETCore" Version="109.1.110" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
using TweetDuck.Application.Service;
|
|
||||||
using TweetLib.Api;
|
|
||||||
using TweetLib.Api.Data;
|
|
||||||
using TweetLib.Api.Service;
|
|
||||||
using TweetLib.Core;
|
|
||||||
|
|
||||||
namespace TweetDuck.Application {
|
|
||||||
static class ApiServices {
|
|
||||||
public static NotificationService Notifications { get; } = new NotificationService();
|
|
||||||
|
|
||||||
public static void Register() {
|
|
||||||
App.Api.RegisterService<INotificationService>(Notifications);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static NamespacedResource Namespace(Resource path) {
|
|
||||||
TweetDuckExtension currentExtension = App.Api.CurrentExtension ?? throw new InvalidOperationException("Cannot use API services outside of designated method calls.");
|
|
||||||
return new NamespacedResource(currentExtension.Id, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using TweetLib.Api.Data;
|
|
||||||
using TweetLib.Api.Data.Notification;
|
|
||||||
using TweetLib.Api.Service;
|
|
||||||
|
|
||||||
namespace TweetDuck.Application.Service {
|
|
||||||
sealed class NotificationService : INotificationService {
|
|
||||||
private readonly List<NamespacedProvider> desktopNotificationScreenProviders = new ();
|
|
||||||
|
|
||||||
public void RegisterDesktopNotificationScreenProvider(IDesktopNotificationScreenProvider provider) {
|
|
||||||
desktopNotificationScreenProviders.Add(new NamespacedProvider(ApiServices.Namespace(provider.Id), provider));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<NamespacedProvider> GetDesktopNotificationScreenProviders() {
|
|
||||||
return desktopNotificationScreenProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class NamespacedProvider : IDesktopNotificationScreenProvider {
|
|
||||||
public NamespacedResource NamespacedId { get; }
|
|
||||||
|
|
||||||
private readonly IDesktopNotificationScreenProvider provider;
|
|
||||||
|
|
||||||
public NamespacedProvider(NamespacedResource id, IDesktopNotificationScreenProvider provider) {
|
|
||||||
this.NamespacedId = id;
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource Id => provider.Id;
|
|
||||||
public string DisplayName => provider.DisplayName;
|
|
||||||
public IScreen? PickScreen(IScreenLayout layout) => provider.PickScreen(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,15 @@ namespace TweetDuck.Browser.Notification {
|
|||||||
|
|
||||||
protected virtual Point PrimaryLocation {
|
protected virtual Point PrimaryLocation {
|
||||||
get {
|
get {
|
||||||
Screen screen = Config.NotificationDisplay.PickScreen(owner);
|
Screen screen;
|
||||||
|
|
||||||
|
if (Config.NotificationDisplay > 0 && Config.NotificationDisplay <= Screen.AllScreens.Length) {
|
||||||
|
screen = Screen.AllScreens[Config.NotificationDisplay - 1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
screen = Screen.FromControl(owner);
|
||||||
|
}
|
||||||
|
|
||||||
int edgeDist = Config.NotificationEdgeDistance;
|
int edgeDist = Config.NotificationEdgeDistance;
|
||||||
|
|
||||||
switch (Config.NotificationPosition) {
|
switch (Config.NotificationPosition) {
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDuck.Application;
|
|
||||||
using TweetDuck.Application.Service;
|
|
||||||
using TweetLib.Api.Data;
|
|
||||||
using TweetLib.Api.Data.Notification;
|
|
||||||
using TweetLib.Utils.Serialization.Converters;
|
|
||||||
using TweetLib.Utils.Static;
|
|
||||||
|
|
||||||
namespace TweetDuck.Browser.Notification {
|
|
||||||
abstract class NotificationScreen {
|
|
||||||
public static List<NotificationScreen> All {
|
|
||||||
get {
|
|
||||||
var list = new List<NotificationScreen> {
|
|
||||||
SameAsTweetDuck.Instance
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int index = 1; index <= Screen.AllScreens.Length; index++) {
|
|
||||||
list.Add(new Static(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var provider in ApiServices.Notifications.GetDesktopNotificationScreenProviders()) {
|
|
||||||
list.Add(new Provided(provider.NamespacedId));
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract string DisplayName { get; }
|
|
||||||
|
|
||||||
private NotificationScreen() {}
|
|
||||||
|
|
||||||
public abstract Screen PickScreen(FormBrowser mainWindow);
|
|
||||||
|
|
||||||
protected abstract string Serialize();
|
|
||||||
|
|
||||||
public sealed class SameAsTweetDuck : NotificationScreen {
|
|
||||||
public static SameAsTweetDuck Instance { get; } = new SameAsTweetDuck();
|
|
||||||
|
|
||||||
public override string DisplayName => "(Same as TweetDuck)";
|
|
||||||
|
|
||||||
private SameAsTweetDuck() {}
|
|
||||||
|
|
||||||
public override Screen PickScreen(FormBrowser mainWindow) {
|
|
||||||
return Screen.FromControl(mainWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string Serialize() {
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) {
|
|
||||||
return obj is SameAsTweetDuck;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode() {
|
|
||||||
return 1828695039;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class Static : NotificationScreen {
|
|
||||||
public override string DisplayName {
|
|
||||||
get {
|
|
||||||
Screen? screen = Screen;
|
|
||||||
if (screen == null) {
|
|
||||||
return $"Unknown ({screenIndex})";
|
|
||||||
}
|
|
||||||
|
|
||||||
return screen.DeviceName.TrimStart('\\', '.') + $" ({screen.Bounds.Width}x{screen.Bounds.Height})";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Screen? Screen => screenIndex >= 1 && screenIndex <= Screen.AllScreens.Length ? Screen.AllScreens[screenIndex - 1] : null;
|
|
||||||
|
|
||||||
private readonly int screenIndex;
|
|
||||||
|
|
||||||
public Static(int screenIndex) {
|
|
||||||
this.screenIndex = screenIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Screen PickScreen(FormBrowser mainWindow) {
|
|
||||||
return Screen ?? SameAsTweetDuck.Instance.PickScreen(mainWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string Serialize() {
|
|
||||||
return screenIndex.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) {
|
|
||||||
return obj is Static other && screenIndex == other.screenIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode() {
|
|
||||||
return 31 * screenIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class Provided : NotificationScreen {
|
|
||||||
public override string DisplayName => Provider?.DisplayName ?? $"Unknown ({resource})";
|
|
||||||
|
|
||||||
private readonly NamespacedResource resource;
|
|
||||||
|
|
||||||
private NotificationService.NamespacedProvider? provider;
|
|
||||||
private NotificationService.NamespacedProvider? Provider => provider ??= ApiServices.Notifications.GetDesktopNotificationScreenProviders().Find(p => p.NamespacedId == resource);
|
|
||||||
|
|
||||||
public Provided(NamespacedResource resource) {
|
|
||||||
this.resource = resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Screen PickScreen(FormBrowser mainWindow) {
|
|
||||||
IScreen? pick = Provider?.PickScreen(new WindowsFormsScreenLayout(mainWindow));
|
|
||||||
return pick is WindowsFormsScreen screen ? screen.Screen : SameAsTweetDuck.Instance.PickScreen(mainWindow); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string Serialize() {
|
|
||||||
return resource.Namespace + ":" + resource.Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) {
|
|
||||||
return obj is Provided other && resource == other.resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode() {
|
|
||||||
return resource.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class WindowsFormsScreenLayout : IScreenLayout {
|
|
||||||
public IScreen PrimaryScreen => new WindowsFormsScreen(Screen.PrimaryScreen);
|
|
||||||
public IScreen TweetDuckScreen => new WindowsFormsScreen(Screen.FromControl(mainWindow));
|
|
||||||
public List<IScreen> AllScreens => Screen.AllScreens.Select(static screen => new WindowsFormsScreen(screen)).ToList<IScreen>();
|
|
||||||
|
|
||||||
private readonly FormBrowser mainWindow;
|
|
||||||
|
|
||||||
public WindowsFormsScreenLayout(FormBrowser mainWindow) {
|
|
||||||
this.mainWindow = mainWindow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class WindowsFormsScreen : IScreen {
|
|
||||||
public Screen Screen { get; }
|
|
||||||
public ScreenBounds Bounds { get; }
|
|
||||||
public string Name => Screen.DeviceName;
|
|
||||||
public bool IsPrimary => Screen.Primary;
|
|
||||||
|
|
||||||
public WindowsFormsScreen(Screen screen) {
|
|
||||||
this.Screen = screen;
|
|
||||||
this.Bounds = new ScreenBounds(screen.Bounds.X, screen.Bounds.Y, screen.Bounds.Width, screen.Bounds.Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly BasicTypeConverter<NotificationScreen> Converter = new() {
|
|
||||||
ConvertToString = static value => value.Serialize(),
|
|
||||||
ConvertToObject = static value => {
|
|
||||||
if (value == "0") {
|
|
||||||
return SameAsTweetDuck.Instance;
|
|
||||||
}
|
|
||||||
else if (int.TryParse(value, out int index)) {
|
|
||||||
return new Static(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
var resource = StringUtils.SplitInTwo(value, ':');
|
|
||||||
if (resource != null) {
|
|
||||||
return new Provided(new NamespacedResource(new Resource(resource.Value.before), new Resource(resource.Value.after)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SameAsTweetDuck.Instance;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,7 @@ namespace TweetDuck.Configuration {
|
|||||||
public const string ArgIgnoreGDPR = "-nogdpr";
|
public const string ArgIgnoreGDPR = "-nogdpr";
|
||||||
public const string ArgHttpVideo = "-httpvideo";
|
public const string ArgHttpVideo = "-httpvideo";
|
||||||
public const string ArgFreeze = "-freeze";
|
public const string ArgFreeze = "-freeze";
|
||||||
|
public const string ArgHideDeprecation = "-hidedeprecation";
|
||||||
|
|
||||||
// internal args
|
// internal args
|
||||||
public const string ArgRestart = "-restart";
|
public const string ArgRestart = "-restart";
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using TweetDuck.Browser;
|
using TweetDuck.Browser;
|
||||||
using TweetDuck.Browser.Notification;
|
|
||||||
using TweetDuck.Controls;
|
using TweetDuck.Controls;
|
||||||
using TweetLib.Core;
|
using TweetLib.Core;
|
||||||
using TweetLib.Core.Application;
|
using TweetLib.Core.Application;
|
||||||
@@ -67,7 +66,7 @@ namespace TweetDuck.Configuration {
|
|||||||
|
|
||||||
public DesktopNotification.Position NotificationPosition { get; set; } = DesktopNotification.Position.TopRight;
|
public DesktopNotification.Position NotificationPosition { get; set; } = DesktopNotification.Position.TopRight;
|
||||||
public Point CustomNotificationPosition { get; set; } = ControlExtensions.InvisibleLocation;
|
public Point CustomNotificationPosition { get; set; } = ControlExtensions.InvisibleLocation;
|
||||||
public NotificationScreen NotificationDisplay { get; set; } = NotificationScreen.SameAsTweetDuck.Instance;
|
public int NotificationDisplay { get; set; } = 0;
|
||||||
public int NotificationEdgeDistance { get; set; } = 8;
|
public int NotificationEdgeDistance { get; set; } = 8;
|
||||||
public int NotificationWindowOpacity { get; set; } = 100;
|
public int NotificationWindowOpacity { get; set; } = 100;
|
||||||
|
|
||||||
|
|||||||
36
windows/TweetDuck/Dialogs/DeprecationNoticeDialog.cs
Normal file
36
windows/TweetDuck/Dialogs/DeprecationNoticeDialog.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetLib.Core;
|
||||||
|
|
||||||
|
namespace TweetDuck.Dialogs;
|
||||||
|
|
||||||
|
static class DeprecationNoticeDialog {
|
||||||
|
public static bool Show() {
|
||||||
|
const string contents = """
|
||||||
|
TweetDuck is no longer being maintained:
|
||||||
|
- Twitter has been constantly breaking TweetDeck and therefore also breaking TweetDuck.
|
||||||
|
- Twitter will be replacing TweetDeck with a new version that is incompatible with most of the app's features.
|
||||||
|
- Twitter is planning to put TweetDeck behind a subscription paywall.
|
||||||
|
|
||||||
|
There will be no more updates.
|
||||||
|
Continue at your own risk.
|
||||||
|
""";
|
||||||
|
|
||||||
|
using FormMessage message = new FormMessage("TweetDuck Deprecation Notice", contents, MessageBoxIcon.Warning);
|
||||||
|
|
||||||
|
message.AddButton("Exit", DialogResult.Cancel, ControlType.Cancel);
|
||||||
|
message.AddButton("Continue", DialogResult.OK, ControlType.Accept | ControlType.Focused);
|
||||||
|
|
||||||
|
Button btnLearnMore = message.CreateButton("Learn More", x: 9, width: 106);
|
||||||
|
btnLearnMore.Anchor |= AnchorStyles.Left;
|
||||||
|
btnLearnMore.Margin = new Padding(0, 0, 48, 0);
|
||||||
|
btnLearnMore.Click += OnBtnLearnMoreClick;
|
||||||
|
message.AddActionControl(btnLearnMore);
|
||||||
|
|
||||||
|
return message.ShowDialog() == DialogResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnBtnLearnMoreClick(object? sender, EventArgs args) {
|
||||||
|
App.SystemHandler.OpenBrowser(Program.Website + "/deprecation");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -124,15 +124,7 @@ namespace TweetDuck.Dialogs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Button AddButton(string title, DialogResult result = DialogResult.OK, ControlType type = ControlType.None) {
|
public Button AddButton(string title, DialogResult result = DialogResult.OK, ControlType type = ControlType.None) {
|
||||||
Button button = new Button {
|
Button button = CreateButton(title);
|
||||||
Anchor = AnchorStyles.Bottom,
|
|
||||||
Font = SystemFonts.MessageBoxFont,
|
|
||||||
Location = new Point(0, 12),
|
|
||||||
Size = new Size(BrowserUtils.Scale(88, dpiScale), BrowserUtils.Scale(26, dpiScale)),
|
|
||||||
TabIndex = 256 - buttonCount,
|
|
||||||
Text = title,
|
|
||||||
UseVisualStyleBackColor = true
|
|
||||||
};
|
|
||||||
|
|
||||||
button.Click += (_, _) => {
|
button.Click += (_, _) => {
|
||||||
ClickedButton = button;
|
ClickedButton = button;
|
||||||
@@ -162,6 +154,18 @@ namespace TweetDuck.Dialogs {
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Button CreateButton(string title, int x = 0, int width = 88) {
|
||||||
|
return new Button {
|
||||||
|
Anchor = AnchorStyles.Bottom,
|
||||||
|
Font = SystemFonts.MessageBoxFont,
|
||||||
|
Location = new Point(x, 12),
|
||||||
|
Size = new Size(BrowserUtils.Scale(width, dpiScale), BrowserUtils.Scale(26, dpiScale)),
|
||||||
|
TabIndex = 256 - buttonCount,
|
||||||
|
Text = title,
|
||||||
|
UseVisualStyleBackColor = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void AddActionControl(Control control) {
|
public void AddActionControl(Control control) {
|
||||||
panelActions.Controls.Add(control);
|
panelActions.Controls.Add(control);
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,10 @@
|
|||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.panelContents.AutoScroll = true;
|
this.panelContents.AutoScroll = true;
|
||||||
this.panelContents.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
this.panelContents.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
this.panelContents.Location = new System.Drawing.Point(135, 12);
|
this.panelContents.Location = new System.Drawing.Point(134, 12);
|
||||||
this.panelContents.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
|
this.panelContents.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
|
||||||
this.panelContents.Name = "panelContents";
|
this.panelContents.Name = "panelContents";
|
||||||
this.panelContents.Size = new System.Drawing.Size(662, 482);
|
this.panelContents.Size = new System.Drawing.Size(663, 482);
|
||||||
this.panelContents.TabIndex = 1;
|
this.panelContents.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// panelButtons
|
// panelButtons
|
||||||
|
|||||||
@@ -86,21 +86,13 @@ namespace TweetDuck.Dialogs.Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
||||||
|
comboBoxDisplay.Items.Add("(Same as TweetDuck)");
|
||||||
|
|
||||||
bool foundScreen = false;
|
foreach (Screen screen in Screen.AllScreens) {
|
||||||
|
comboBoxDisplay.Items.Add($"{screen.DeviceName.TrimStart('\\', '.')} ({screen.Bounds.Width}x{screen.Bounds.Height})");
|
||||||
foreach (var screen in NotificationScreen.All) {
|
|
||||||
comboBoxDisplay.Items.Add(new NotificationScreenItem(screen));
|
|
||||||
if (screen.Equals(Config.NotificationDisplay)) {
|
|
||||||
comboBoxDisplay.SelectedIndex = comboBoxDisplay.Items.Count - 1;
|
|
||||||
foundScreen = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundScreen) {
|
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count - 1, Config.NotificationDisplay);
|
||||||
comboBoxDisplay.Items.Add(new NotificationScreenItem(Config.NotificationDisplay));
|
|
||||||
comboBoxDisplay.SelectedIndex = comboBoxDisplay.Items.Count - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
|
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
|
||||||
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value + " px";
|
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value + " px";
|
||||||
@@ -287,7 +279,7 @@ namespace TweetDuck.Dialogs.Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void comboBoxDisplay_SelectedValueChanged(object? sender, EventArgs e) {
|
private void comboBoxDisplay_SelectedValueChanged(object? sender, EventArgs e) {
|
||||||
Config.NotificationDisplay = ((NotificationScreenItem) comboBoxDisplay.SelectedItem).Screen;
|
Config.NotificationDisplay = comboBoxDisplay.SelectedIndex;
|
||||||
notification.ShowExampleNotification(false);
|
notification.ShowExampleNotification(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,21 +289,6 @@ namespace TweetDuck.Dialogs.Settings {
|
|||||||
notification.ShowExampleNotification(false);
|
notification.ShowExampleNotification(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NotificationScreenItem {
|
|
||||||
public NotificationScreen Screen { get; }
|
|
||||||
|
|
||||||
private readonly string displayName;
|
|
||||||
|
|
||||||
public NotificationScreenItem(NotificationScreen screen) {
|
|
||||||
this.Screen = screen;
|
|
||||||
this.displayName = screen.DisplayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Size
|
#region Size
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using CefSharp.WinForms;
|
|||||||
using TweetDuck.Application;
|
using TweetDuck.Application;
|
||||||
using TweetDuck.Browser;
|
using TweetDuck.Browser;
|
||||||
using TweetDuck.Browser.Base;
|
using TweetDuck.Browser.Base;
|
||||||
using TweetDuck.Browser.Notification;
|
|
||||||
using TweetDuck.Configuration;
|
using TweetDuck.Configuration;
|
||||||
using TweetDuck.Dialogs;
|
using TweetDuck.Dialogs;
|
||||||
using TweetDuck.Management;
|
using TweetDuck.Management;
|
||||||
@@ -17,7 +16,6 @@ using TweetLib.Browser.CEF.Utils;
|
|||||||
using TweetLib.Browser.Request;
|
using TweetLib.Browser.Request;
|
||||||
using TweetLib.Core;
|
using TweetLib.Core;
|
||||||
using TweetLib.Core.Application;
|
using TweetLib.Core.Application;
|
||||||
using TweetLib.Core.Features.Extensions;
|
|
||||||
using TweetLib.Core.Features.Plugins;
|
using TweetLib.Core.Features.Plugins;
|
||||||
using TweetLib.Core.Features.Plugins.Config;
|
using TweetLib.Core.Features.Plugins.Config;
|
||||||
using TweetLib.Core.Features.TweetDeck;
|
using TweetLib.Core.Features.TweetDeck;
|
||||||
@@ -92,7 +90,6 @@ namespace TweetDuck {
|
|||||||
public string? ResourceRewriteRules => Arguments.GetValue(Arguments.ArgFreeze);
|
public string? ResourceRewriteRules => Arguments.GetValue(Arguments.ArgFreeze);
|
||||||
|
|
||||||
public ConfigManager CreateConfigManager(string storagePath) {
|
public ConfigManager CreateConfigManager(string storagePath) {
|
||||||
ConfigManager.ConverterRegistry.Register(typeof(NotificationScreen), NotificationScreen.Converter);
|
|
||||||
return new ConfigManager<UserConfig, SystemConfig>(storagePath, Config);
|
return new ConfigManager<UserConfig, SystemConfig>(storagePath, Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +108,10 @@ namespace TweetDuck {
|
|||||||
if (Config.System.Migrate()) {
|
if (Config.System.Migrate()) {
|
||||||
Config.System.Save();
|
Config.System.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Arguments.HasFlag(Arguments.ArgHideDeprecation) && !DeprecationNoticeDialog.Show()) {
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Launch(ResourceCache resourceCache, PluginManager pluginManager) {
|
public void Launch(ResourceCache resourceCache, PluginManager pluginManager) {
|
||||||
@@ -140,9 +141,6 @@ namespace TweetDuck {
|
|||||||
Cef.Initialize(settings, false, new BrowserProcessHandler());
|
Cef.Initialize(settings, false, new BrowserProcessHandler());
|
||||||
|
|
||||||
Win.Application.ApplicationExit += static (_, _) => ExitCleanup();
|
Win.Application.ApplicationExit += static (_, _) => ExitCleanup();
|
||||||
|
|
||||||
ApiServices.Register();
|
|
||||||
ExtensionLoader.LoadAllInFolder(App.ExtensionPath);
|
|
||||||
var updateCheckClient = new UpdateCheckClient(Path.Combine(storagePath, InstallerFolder));
|
var updateCheckClient = new UpdateCheckClient(Path.Combine(storagePath, InstallerFolder));
|
||||||
var mainForm = new FormBrowser(resourceCache, pluginManager, updateCheckClient, lockManager.WindowRestoreMessage);
|
var mainForm = new FormBrowser(resourceCache, pluginManager, updateCheckClient, lockManager.WindowRestoreMessage);
|
||||||
Win.Application.Run(mainForm);
|
Win.Application.Run(mainForm);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Dialogs;
|
using TweetDuck.Dialogs;
|
||||||
using TweetDuck.Management;
|
using TweetDuck.Management;
|
||||||
@@ -36,16 +35,10 @@ namespace TweetDuck {
|
|||||||
btnIgnore.Enabled = canIgnore;
|
btnIgnore.Enabled = canIgnore;
|
||||||
form.ActiveControl = canIgnore ? btnIgnore : btnExit;
|
form.ActiveControl = canIgnore ? btnIgnore : btnExit;
|
||||||
|
|
||||||
Button btnOpenLog = new Button {
|
Button btnOpenLog = form.CreateButton("Show Error Log", x: 9, width: 106);
|
||||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
|
btnOpenLog.Anchor |= AnchorStyles.Left;
|
||||||
Enabled = loggedSuccessfully,
|
btnOpenLog.Enabled = loggedSuccessfully;
|
||||||
Font = SystemFonts.MessageBoxFont,
|
btnOpenLog.Margin = new Padding(0, 0, 48, 0);
|
||||||
Location = new Point(9, 12),
|
|
||||||
Margin = new Padding(0, 0, 48, 0),
|
|
||||||
Size = new Size(106, 26),
|
|
||||||
Text = "Show Error Log",
|
|
||||||
UseVisualStyleBackColor = true
|
|
||||||
};
|
|
||||||
|
|
||||||
btnOpenLog.Click += static (_, _) => {
|
btnOpenLog.Click += static (_, _) => {
|
||||||
if (!OpenLogFile()) {
|
if (!OpenLogFile()) {
|
||||||
|
|||||||
@@ -36,11 +36,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CefSharp.WinForms.NETCore" Version="107.1.90" />
|
<PackageReference Include="CefSharp.WinForms.NETCore" Version="109.1.110" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\lib\TweetLib.Api\TweetLib.Api.csproj" />
|
|
||||||
<ProjectReference Include="..\..\lib\TweetLib.Browser.CEF\TweetLib.Browser.CEF.csproj" />
|
<ProjectReference Include="..\..\lib\TweetLib.Browser.CEF\TweetLib.Browser.CEF.csproj" />
|
||||||
<ProjectReference Include="..\..\lib\TweetLib.Browser\TweetLib.Browser.csproj" />
|
<ProjectReference Include="..\..\lib\TweetLib.Browser\TweetLib.Browser.csproj" />
|
||||||
<ProjectReference Include="..\..\lib\TweetLib.Communication\TweetLib.Communication.csproj" />
|
<ProjectReference Include="..\..\lib\TweetLib.Communication\TweetLib.Communication.csproj" />
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CefSharp.WinForms.NETCore" Version="107.1.90" />
|
<PackageReference Include="CefSharp.WinForms.NETCore" Version="109.1.110" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user