diff --git a/lib/TweetLib.Browser.CEF/Data/ContextMenuActionRegistry.cs b/lib/TweetLib.Browser.CEF/Data/ContextMenuActionRegistry.cs index d310fb2b..48279266 100644 --- a/lib/TweetLib.Browser.CEF/Data/ContextMenuActionRegistry.cs +++ b/lib/TweetLib.Browser.CEF/Data/ContextMenuActionRegistry.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace TweetLib.Browser.CEF.Data { - public abstract class ContextMenuActionRegistry<T> { + abstract class ContextMenuActionRegistry<T> { private readonly Dictionary<T, Action> actions = new (); protected abstract T NextId(int n); diff --git a/lib/TweetLib.Browser.CEF/Logic/ContextMenuLogic.cs b/lib/TweetLib.Browser.CEF/Logic/ContextMenuLogic.cs index 62ba5310..d9e42a82 100644 --- a/lib/TweetLib.Browser.CEF/Logic/ContextMenuLogic.cs +++ b/lib/TweetLib.Browser.CEF/Logic/ContextMenuLogic.cs @@ -28,7 +28,7 @@ public abstract class ContextMenuLogic { 206 // AddToDictionary }; - protected sealed class ContextMenuActionRegistry : ContextMenuActionRegistry<int> { + private protected sealed class ContextMenuActionRegistry : ContextMenuActionRegistry<int> { private const int CommandUserFirst = 26500; protected override int NextId(int n) { diff --git a/lib/TweetLib.Browser.CEF/Logic/ResourceRequestHandlerLogic.cs b/lib/TweetLib.Browser.CEF/Logic/ResourceRequestHandlerLogic.cs index 7c1bb524..0d59c10f 100644 --- a/lib/TweetLib.Browser.CEF/Logic/ResourceRequestHandlerLogic.cs +++ b/lib/TweetLib.Browser.CEF/Logic/ResourceRequestHandlerLogic.cs @@ -30,19 +30,16 @@ public bool OnBeforeResourceLoad(TRequest request, IDisposable callback) { if (resourceRequestHandler != null) { var result = resourceRequestHandler.Handle(requestAdapter.GetUrl(request), requestAdapter.GetResourceType(request)); - switch (result) { - case RequestHandleResult.Redirect redirect: - requestAdapter.SetUrl(request, redirect.Url); - break; - - case RequestHandleResult.Process process: - requestAdapter.SetHeader(request, "Accept-Encoding", "identity"); - responseProcessors[requestAdapter.GetIdentifier(request)] = process.Processor; - break; - - case RequestHandleResult.Cancel: - callback.Dispose(); - return false; + if (result is RequestHandleResult.Redirect redirect) { + requestAdapter.SetUrl(request, redirect.Url); + } + else if (result is RequestHandleResult.Process process) { + requestAdapter.SetHeader(request, "Accept-Encoding", "identity"); + responseProcessors[requestAdapter.GetIdentifier(request)] = process.Processor; + } + else if (result == RequestHandleResult.Cancel) { + callback.Dispose(); + return false; } } diff --git a/lib/TweetLib.Browser.CEF/Logic/SchemeResourceVisitor.cs b/lib/TweetLib.Browser.CEF/Logic/SchemeResourceVisitor.cs index 4ed41243..70ba8549 100644 --- a/lib/TweetLib.Browser.CEF/Logic/SchemeResourceVisitor.cs +++ b/lib/TweetLib.Browser.CEF/Logic/SchemeResourceVisitor.cs @@ -6,11 +6,11 @@ using TweetLib.Browser.Request; namespace TweetLib.Browser.CEF.Logic { - internal abstract class SchemeResourceVisitor { + abstract class SchemeResourceVisitor { protected static readonly SchemeResource.Status FileIsEmpty = new (HttpStatusCode.NoContent, "File is empty."); } - internal sealed class SchemeResourceVisitor<TResourceHandler> : SchemeResourceVisitor, ISchemeResourceVisitor<TResourceHandler> { + sealed class SchemeResourceVisitor<TResourceHandler> : SchemeResourceVisitor, ISchemeResourceVisitor<TResourceHandler> { private readonly IResourceHandlerFactory<TResourceHandler> factory; public SchemeResourceVisitor(IResourceHandlerFactory<TResourceHandler> factory) { diff --git a/lib/TweetLib.Browser/Interfaces/IResourceProvider.cs b/lib/TweetLib.Browser/Interfaces/IResourceProvider.cs deleted file mode 100644 index 71eaa48b..00000000 --- a/lib/TweetLib.Browser/Interfaces/IResourceProvider.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Net; - -namespace TweetLib.Browser.Interfaces { - public interface IResourceProvider<T> { - T Status(HttpStatusCode code, string message); - T File(byte[] contents, string extension); - } -} diff --git a/lib/TweetLib.Browser/Request/RequestHandleResult.cs b/lib/TweetLib.Browser/Request/RequestHandleResult.cs index a905528b..c0732138 100644 --- a/lib/TweetLib.Browser/Request/RequestHandleResult.cs +++ b/lib/TweetLib.Browser/Request/RequestHandleResult.cs @@ -1,7 +1,9 @@ using TweetLib.Browser.Interfaces; namespace TweetLib.Browser.Request { - public abstract class RequestHandleResult { + public class RequestHandleResult { + public static RequestHandleResult Cancel { get; } = new (); + private RequestHandleResult() {} public sealed class Redirect : RequestHandleResult { @@ -19,11 +21,5 @@ public Process(IResponseProcessor processor) { Processor = processor; } } - - public sealed class Cancel : RequestHandleResult { - public static Cancel Instance { get; } = new (); - - private Cancel() {} - } } } diff --git a/lib/TweetLib.Core/App.cs b/lib/TweetLib.Core/App.cs index d67961a4..e871d2d4 100644 --- a/lib/TweetLib.Core/App.cs +++ b/lib/TweetLib.Core/App.cs @@ -17,22 +17,23 @@ public static class App { public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory; public static readonly bool IsPortable = Setup.IsPortable; - public static readonly string ResourcesPath = Path.Combine(ProgramPath, "resources"); - public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins"); - public static readonly string GuidePath = Path.Combine(ProgramPath, "guide"); + internal static readonly string ResourcesPath = Path.Combine(ProgramPath, "resources"); + internal static readonly string PluginPath = Path.Combine(ProgramPath, "plugins"); + internal static readonly string GuidePath = Path.Combine(ProgramPath, "guide"); 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 Logger Logger { get; } = new (Path.Combine(StoragePath, "TD_Log.txt"), Setup.IsDebugLogging); public static ConfigManager ConfigManager { get; } = Setup.CreateConfigManager(StoragePath); public static IAppErrorHandler ErrorHandler { get; } = Validate(Builder.ErrorHandler, nameof(Builder.ErrorHandler)); public static IAppSystemHandler SystemHandler { get; } = Validate(Builder.SystemHandler, nameof(Builder.SystemHandler)); - public static IAppMessageDialogs MessageDialogs { get; } = Validate(Builder.MessageDialogs, nameof(Builder.MessageDialogs)); - public static IAppFileDialogs? FileDialogs { get; } = Builder.FileDialogs; - + + internal static IAppMessageDialogs MessageDialogs { get; } = Validate(Builder.MessageDialogs, nameof(Builder.MessageDialogs)); + internal static IAppFileDialogs? FileDialogs { get; } = Builder.FileDialogs; + internal static IAppUserConfiguration UserConfiguration => ConfigManager.User; - internal static IAppSystemConfiguration SystemConfiguration => ConfigManager.System; private static string GetDataFolder() { string? custom = Setup.CustomDataFolder; @@ -75,7 +76,7 @@ internal static void Launch() { WebUtils.DefaultUserAgent = Lib.BrandName + " " + Version.Tag; - if (SystemConfiguration.UseSystemProxyForAllConnections) { + if (ConfigManager.System.UseSystemProxyForAllConnections) { WebUtils.EnableSystemProxy(); } diff --git a/lib/TweetLib.Core/Features/Notifications/DesktopNotification.cs b/lib/TweetLib.Core/Features/Notifications/DesktopNotification.cs index 59f01225..9dce895f 100644 --- a/lib/TweetLib.Core/Features/Notifications/DesktopNotification.cs +++ b/lib/TweetLib.Core/Features/Notifications/DesktopNotification.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using TweetLib.Utils.Data; @@ -46,7 +47,7 @@ public int GetDisplayDuration(int value) { return 2000 + Math.Max(1000, value * characters); } - public string GenerateHtml(string bodyClasses, string? headLayout, string? customStyles, IEnumerable<InjectedString> injections, string[] scripts) { // TODO + internal string GenerateHtml(string bodyClasses, string? headLayout, string? customStyles, IEnumerable<InjectedString> injections, string[] scripts) { // TODO headLayout ??= DefaultHeadLayout; customStyles ??= string.Empty; @@ -71,12 +72,7 @@ public string GenerateHtml(string bodyClasses, string? headLayout, string? custo build.Append("<tweetduck-script-placeholder></body></html>"); string result = build.ToString(); - - foreach (var injection in injections) { - result = injection.InjectInto(result); - } - - return result.Replace("<tweetduck-script-placeholder>", GenerateScripts(scripts)); + return injections.Aggregate(result, static (current, injection) => injection.InjectInto(current)).Replace("<tweetduck-script-placeholder>", GenerateScripts(scripts)); } private string GenerateScripts(string[] scripts) { diff --git a/lib/TweetLib.Core/Features/Notifications/NotificationBrowser.cs b/lib/TweetLib.Core/Features/Notifications/NotificationBrowser.cs index 360af353..2547aa65 100644 --- a/lib/TweetLib.Core/Features/Notifications/NotificationBrowser.cs +++ b/lib/TweetLib.Core/Features/Notifications/NotificationBrowser.cs @@ -13,7 +13,7 @@ internal static void SetNotificationLayout(string? fontSize, string? headLayout) } public static string? FontSize { get; private set; } - public static string? HeadLayout { get; private set; } + private static string? HeadLayout { get; set; } private NotificationBrowser(IBrowserComponent browserComponent, Func<NotificationBrowser, BrowserSetup> setup) : base(browserComponent, setup) {} diff --git a/lib/TweetLib.Core/Features/Plugins/Config/PluginConfig.cs b/lib/TweetLib.Core/Features/Plugins/Config/PluginConfig.cs index fd0ee996..7cc95db9 100644 --- a/lib/TweetLib.Core/Features/Plugins/Config/PluginConfig.cs +++ b/lib/TweetLib.Core/Features/Plugins/Config/PluginConfig.cs @@ -7,7 +7,7 @@ namespace TweetLib.Core.Features.Plugins.Config { public sealed class PluginConfig : IConfigObject<PluginConfig> { internal IEnumerable<string> DisabledPlugins => disabled; - public event EventHandler<PluginChangedStateEventArgs>? PluginChangedState; + internal event EventHandler<PluginChangedStateEventArgs>? PluginChangedState; private readonly HashSet<string> defaultDisabled; private readonly HashSet<string> disabled; diff --git a/lib/TweetLib.Core/Features/Plugins/Config/PluginConfigInstance.cs b/lib/TweetLib.Core/Features/Plugins/Config/PluginConfigInstance.cs index b80b1b97..f6c2ac40 100644 --- a/lib/TweetLib.Core/Features/Plugins/Config/PluginConfigInstance.cs +++ b/lib/TweetLib.Core/Features/Plugins/Config/PluginConfigInstance.cs @@ -6,12 +6,11 @@ namespace TweetLib.Core.Features.Plugins.Config { sealed class PluginConfigInstance : IConfigInstance { - public PluginConfig Instance { get; } - + private readonly PluginConfig instance; private readonly string filename; public PluginConfigInstance(string filename, PluginConfig instance) { - this.Instance = instance; + this.instance = instance; this.filename = filename; } @@ -27,7 +26,7 @@ public void Load() { newDisabled.Add(line); } - Instance.Reset(newDisabled); + instance.Reset(newDisabled); } } catch (FileNotFoundException) { // ignore @@ -43,7 +42,7 @@ public void Save() { using var writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None), Encoding.UTF8); writer.WriteLine("#Disabled"); - foreach (string identifier in Instance.DisabledPlugins) { + foreach (string identifier in instance.DisabledPlugins) { writer.WriteLine(identifier); } } catch (Exception e) { @@ -58,7 +57,7 @@ public void Reload() { public void Reset() { try { File.Delete(filename); - Instance.ResetToDefault(); + instance.ResetToDefault(); } catch (Exception e) { OnException("Could not delete the plugin configuration file.", e); return; diff --git a/lib/TweetLib.Core/Features/Plugins/Enums/PluginEnvironment.cs b/lib/TweetLib.Core/Features/Plugins/Enums/PluginEnvironment.cs index 281906b3..b500013c 100644 --- a/lib/TweetLib.Core/Features/Plugins/Enums/PluginEnvironment.cs +++ b/lib/TweetLib.Core/Features/Plugins/Enums/PluginEnvironment.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; namespace TweetLib.Core.Features.Plugins.Enums { - public enum PluginEnvironment { + enum PluginEnvironment { Browser, Notification } - internal static class PluginEnvironments { + static class PluginEnvironments { public static IEnumerable<PluginEnvironment> All { get; } = new PluginEnvironment[] { PluginEnvironment.Browser, PluginEnvironment.Notification diff --git a/lib/TweetLib.Core/Features/Plugins/Enums/PluginGroup.cs b/lib/TweetLib.Core/Features/Plugins/Enums/PluginGroup.cs index 7190a094..4716079a 100644 --- a/lib/TweetLib.Core/Features/Plugins/Enums/PluginGroup.cs +++ b/lib/TweetLib.Core/Features/Plugins/Enums/PluginGroup.cs @@ -7,7 +7,7 @@ public enum PluginGroup { Custom } - internal static class PluginGroups { + static class PluginGroups { public static IEnumerable<PluginGroup> All { get; } = new PluginGroup[] { PluginGroup.Official, PluginGroup.Custom diff --git a/lib/TweetLib.Core/Features/Plugins/Events/PluginChangedStateEventArgs.cs b/lib/TweetLib.Core/Features/Plugins/Events/PluginChangedStateEventArgs.cs index 16fbf620..414b5bbe 100644 --- a/lib/TweetLib.Core/Features/Plugins/Events/PluginChangedStateEventArgs.cs +++ b/lib/TweetLib.Core/Features/Plugins/Events/PluginChangedStateEventArgs.cs @@ -1,7 +1,7 @@ using System; namespace TweetLib.Core.Features.Plugins.Events { - public sealed class PluginChangedStateEventArgs : EventArgs { + internal sealed class PluginChangedStateEventArgs : EventArgs { public Plugin Plugin { get; } public bool IsEnabled { get; } diff --git a/lib/TweetLib.Core/Features/Plugins/Events/PluginErrorEventArgs.cs b/lib/TweetLib.Core/Features/Plugins/Events/PluginErrorEventArgs.cs index b1b9bb75..14106866 100644 --- a/lib/TweetLib.Core/Features/Plugins/Events/PluginErrorEventArgs.cs +++ b/lib/TweetLib.Core/Features/Plugins/Events/PluginErrorEventArgs.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace TweetLib.Core.Features.Plugins.Events { - public sealed class PluginErrorEventArgs : EventArgs { + internal sealed class PluginErrorEventArgs : EventArgs { public bool HasErrors => Errors.Count > 0; public IList<string> Errors { get; } diff --git a/lib/TweetLib.Core/Features/Plugins/Plugin.cs b/lib/TweetLib.Core/Features/Plugins/Plugin.cs index 7562ba6f..7caee371 100644 --- a/lib/TweetLib.Core/Features/Plugins/Plugin.cs +++ b/lib/TweetLib.Core/Features/Plugins/Plugin.cs @@ -17,31 +17,32 @@ public sealed class Plugin { public string Author { get; } public string Version { get; } public string Website { get; } - public string ConfigFile { get; } - public string ConfigDefault { get; } public Version RequiredVersion { get; } public bool CanRun { get; } - public bool HasConfig { - get => ConfigFile.Length > 0 && GetFullPathIfSafe(PluginFolder.Data, ConfigFile).Length > 0; + internal bool HasConfig { + get => configFile.Length > 0 && GetFullPathIfSafe(PluginFolder.Data, configFile).Length > 0; } - public string ConfigPath { - get => HasConfig ? Path.Combine(GetPluginFolder(PluginFolder.Data), ConfigFile) : string.Empty; + internal string ConfigPath { + get => HasConfig ? Path.Combine(GetPluginFolder(PluginFolder.Data), configFile) : string.Empty; } - public bool HasDefaultConfig { - get => ConfigDefault.Length > 0 && GetFullPathIfSafe(PluginFolder.Root, ConfigDefault).Length > 0; + private bool HasDefaultConfig { + get => configDefault.Length > 0 && GetFullPathIfSafe(PluginFolder.Root, configDefault).Length > 0; } - public string DefaultConfigPath { - get => HasDefaultConfig ? Path.Combine(GetPluginFolder(PluginFolder.Root), ConfigDefault) : string.Empty; + private string DefaultConfigPath { + get => HasDefaultConfig ? Path.Combine(GetPluginFolder(PluginFolder.Root), configDefault) : string.Empty; } private readonly string pathRoot; private readonly string pathData; private readonly ISet<PluginEnvironment> environments; + + private readonly string configFile; + private readonly string configDefault; private Plugin(PluginGroup group, string identifier, string pathRoot, string pathData, Builder builder) { this.pathRoot = pathRoot; @@ -56,18 +57,18 @@ private Plugin(PluginGroup group, string identifier, string pathRoot, string pat this.Author = builder.Author; this.Version = builder.Version; this.Website = builder.Website; - this.ConfigFile = builder.ConfigFile; - this.ConfigDefault = builder.ConfigDefault; + this.configFile = builder.ConfigFile; + this.configDefault = builder.ConfigDefault; this.RequiredVersion = builder.RequiredVersion; this.CanRun = AppVersion >= RequiredVersion; } - public bool HasEnvironment(PluginEnvironment environment) { + internal bool HasEnvironment(PluginEnvironment environment) { return environments.Contains(environment); } - public string GetScriptPath(PluginEnvironment environment) { + internal string GetScriptPath(PluginEnvironment environment) { return environments.Contains(environment) ? Path.Combine(pathRoot, environment.GetPluginScriptFile()) : string.Empty; } @@ -79,7 +80,7 @@ public string GetPluginFolder(PluginFolder folder) { }; } - public string GetFullPathIfSafe(PluginFolder folder, string relativePath) { + internal string GetFullPathIfSafe(PluginFolder folder, string relativePath) { string rootFolder = GetPluginFolder(folder); return FileUtils.ResolveRelativePathSafely(rootFolder, relativePath); } @@ -98,7 +99,7 @@ public override bool Equals(object obj) { // Builder - public sealed class Builder { + internal sealed class Builder { private static readonly Version DefaultRequiredVersion = new (0, 0, 0, 0); public string Name { get; set; } = string.Empty; diff --git a/lib/TweetLib.Core/Features/Plugins/PluginLoader.cs b/lib/TweetLib.Core/Features/Plugins/PluginLoader.cs index 71401462..d8faf0dc 100644 --- a/lib/TweetLib.Core/Features/Plugins/PluginLoader.cs +++ b/lib/TweetLib.Core/Features/Plugins/PluginLoader.cs @@ -7,7 +7,7 @@ using TweetLib.Utils.Data; namespace TweetLib.Core.Features.Plugins { - internal static class PluginLoader { + static class PluginLoader { private static readonly string[] EndTag = { "[END]" }; public static IEnumerable<Result<Plugin>> AllInFolder(string pluginFolder, string pluginDataFolder, PluginGroup group) { @@ -38,7 +38,7 @@ public static IEnumerable<Result<Plugin>> AllInFolder(string pluginFolder, strin } } - public static Plugin FromFolder(string name, string pathRoot, string pathData, PluginGroup group) { + private static Plugin FromFolder(string name, string pathRoot, string pathData, PluginGroup group) { Plugin.Builder builder = new Plugin.Builder(group, name, pathRoot, pathData); foreach (var environment in Directory.EnumerateFiles(pathRoot, "*.js", SearchOption.TopDirectoryOnly).Select(Path.GetFileName).Select(EnvironmentFromFileName)) { diff --git a/lib/TweetLib.Core/Features/Plugins/PluginManager.cs b/lib/TweetLib.Core/Features/Plugins/PluginManager.cs index 066c482c..12cb7495 100644 --- a/lib/TweetLib.Core/Features/Plugins/PluginManager.cs +++ b/lib/TweetLib.Core/Features/Plugins/PluginManager.cs @@ -18,15 +18,15 @@ public sealed class PluginManager { public string PluginFolder { get; } public string PluginDataFolder { get; } - public event EventHandler<PluginErrorEventArgs>? Reloaded; - public event EventHandler<PluginErrorEventArgs>? Executed; + internal event EventHandler<PluginErrorEventArgs>? Reloaded; + internal event EventHandler<PluginErrorEventArgs>? Executed; internal readonly PluginBridge bridge; private IScriptExecutor? browserExecutor; private readonly HashSet<Plugin> plugins = new (); - public PluginManager(PluginConfig config, string pluginFolder, string pluginDataFolder) { + internal PluginManager(PluginConfig config, string pluginFolder, string pluginDataFolder) { this.Config = config; this.Config.PluginChangedState += Config_PluginChangedState; this.PluginFolder = pluginFolder; diff --git a/lib/TweetLib.Core/Features/Plugins/PluginScriptGenerator.cs b/lib/TweetLib.Core/Features/Plugins/PluginScriptGenerator.cs index dc7d96d6..a008f8f4 100644 --- a/lib/TweetLib.Core/Features/Plugins/PluginScriptGenerator.cs +++ b/lib/TweetLib.Core/Features/Plugins/PluginScriptGenerator.cs @@ -3,7 +3,7 @@ using TweetLib.Core.Features.Plugins.Enums; namespace TweetLib.Core.Features.Plugins { - internal static class PluginScriptGenerator { + static class PluginScriptGenerator { public static string GenerateConfig(PluginConfig config) { return "window.TD_PLUGINS_DISABLE = [" + string.Join(",", config.DisabledPlugins.Select(static id => '"' + id + '"')) + "]"; } diff --git a/lib/TweetLib.Core/Features/PropertyObjectScript.cs b/lib/TweetLib.Core/Features/PropertyObjectScript.cs index 946145f4..f5449a29 100644 --- a/lib/TweetLib.Core/Features/PropertyObjectScript.cs +++ b/lib/TweetLib.Core/Features/PropertyObjectScript.cs @@ -3,8 +3,8 @@ using TweetLib.Core.Features.Twitter; namespace TweetLib.Core.Features { - public static class PropertyObjectScript { - public enum Environment { + static class PropertyObjectScript { + internal enum Environment { Browser, Notification } diff --git a/lib/TweetLib.Core/Features/TweetDeck/TweetDeckBrowser.cs b/lib/TweetLib.Core/Features/TweetDeck/TweetDeckBrowser.cs index c8a2f447..6c968fe1 100644 --- a/lib/TweetLib.Core/Features/TweetDeck/TweetDeckBrowser.cs +++ b/lib/TweetLib.Core/Features/TweetDeck/TweetDeckBrowser.cs @@ -247,10 +247,10 @@ private sealed class ResourceRequestHandler : BaseResourceRequestHandler { return new RequestHandleResult.Process(VendorScriptProcessor.Instance); case ResourceType.Script when url.Contains("analytics."): - return RequestHandleResult.Cancel.Instance; + return RequestHandleResult.Cancel; case ResourceType.Xhr when url.Contains(UrlVersionCheck): - return RequestHandleResult.Cancel.Instance; + return RequestHandleResult.Cancel; case ResourceType.Xhr when url.Contains("://api.twitter.com/") && url.Contains("include_entities=1") && !url.Contains("&include_ext_has_nft_avatar=1"): return new RequestHandleResult.Redirect(url.Replace("include_entities=1", "include_entities=1&include_ext_has_nft_avatar=1")); diff --git a/lib/TweetLib.Core/Features/Twitter/TwitterUrls.cs b/lib/TweetLib.Core/Features/Twitter/TwitterUrls.cs index ef1e620c..47f75ab3 100644 --- a/lib/TweetLib.Core/Features/Twitter/TwitterUrls.cs +++ b/lib/TweetLib.Core/Features/Twitter/TwitterUrls.cs @@ -1,9 +1,11 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.RegularExpressions; using TweetLib.Utils.Static; namespace TweetLib.Core.Features.Twitter { + [SuppressMessage("ReSharper", "MemberCanBeInternal")] public static class TwitterUrls { public const string TweetDeck = "https://tweetdeck.twitter.com"; private const string TwitterTrackingUrl = "t.co"; diff --git a/lib/TweetLib.Core/Systems/Configuration/FileConfigInstance.cs b/lib/TweetLib.Core/Systems/Configuration/FileConfigInstance.cs index a26a34df..a92ae392 100644 --- a/lib/TweetLib.Core/Systems/Configuration/FileConfigInstance.cs +++ b/lib/TweetLib.Core/Systems/Configuration/FileConfigInstance.cs @@ -4,8 +4,7 @@ namespace TweetLib.Core.Systems.Configuration { sealed class FileConfigInstance<T> : IConfigInstance where T : IConfigObject<T> { - public T Instance { get; } - + private readonly T instance; private readonly SimpleObjectSerializer<T> serializer; private readonly string filenameMain; @@ -13,7 +12,7 @@ sealed class FileConfigInstance<T> : IConfigInstance where T : IConfigObject<T> private readonly string identifier; public FileConfigInstance(string filename, T instance, string identifier, TypeConverterRegistry converterRegistry) { - this.Instance = instance; + this.instance = instance; this.serializer = new SimpleObjectSerializer<T>(converterRegistry); this.filenameMain = filename ?? throw new ArgumentNullException(nameof(filename), "Config file name must not be null!"); @@ -22,7 +21,7 @@ public FileConfigInstance(string filename, T instance, string identifier, TypeCo } private void LoadInternal(bool backup) { - serializer.Read(backup ? filenameBackup : filenameMain, Instance); + serializer.Read(backup ? filenameBackup : filenameMain, instance); } public void Load() { @@ -64,7 +63,7 @@ public void Save() { File.Move(filenameMain, filenameBackup); } - serializer.Write(filenameMain, Instance); + serializer.Write(filenameMain, instance); } catch (SerializationSoftException e) { OnException($"{e.Errors.Count} error{(e.Errors.Count == 1 ? " was" : "s were")} encountered while saving the configuration file for {identifier}.", e); } catch (Exception e) { @@ -77,7 +76,7 @@ public void Reload() { LoadInternal(false); } catch (FileNotFoundException) { try { - serializer.Write(filenameMain, Instance.ConstructWithDefaults()); + serializer.Write(filenameMain, instance.ConstructWithDefaults()); LoadInternal(false); } catch (Exception e) { OnException($"Could not regenerate the configuration file for {identifier}.", e); diff --git a/lib/TweetLib.Core/Systems/Dialogs/Dialogs.cs b/lib/TweetLib.Core/Systems/Dialogs/Dialogs.cs index bfd1f6db..0c63c033 100644 --- a/lib/TweetLib.Core/Systems/Dialogs/Dialogs.cs +++ b/lib/TweetLib.Core/Systems/Dialogs/Dialogs.cs @@ -1,5 +1,5 @@ namespace TweetLib.Core.Systems.Dialogs { - public static class Dialogs { + internal static class Dialogs { public const string OK = "OK"; } } diff --git a/lib/TweetLib.Core/Systems/Dialogs/FileDialogFilter.cs b/lib/TweetLib.Core/Systems/Dialogs/FileDialogFilter.cs index 80ca2da5..bd518e5c 100644 --- a/lib/TweetLib.Core/Systems/Dialogs/FileDialogFilter.cs +++ b/lib/TweetLib.Core/Systems/Dialogs/FileDialogFilter.cs @@ -5,7 +5,7 @@ public sealed class FileDialogFilter { public string Name { get; } public IReadOnlyList<string> Extensions { get; } - public FileDialogFilter(string name, params string[] extensions) { + internal FileDialogFilter(string name, params string[] extensions) { Name = name; Extensions = extensions; } diff --git a/lib/TweetLib.Core/Systems/Startup/LockFile.cs b/lib/TweetLib.Core/Systems/Startup/LockFile.cs index 93fe657e..f08e8043 100644 --- a/lib/TweetLib.Core/Systems/Startup/LockFile.cs +++ b/lib/TweetLib.Core/Systems/Startup/LockFile.cs @@ -99,7 +99,11 @@ private LockResult DetermineLockingProcessOrFail(Exception originalException) { using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { byte[] bytes = new byte[sizeof(int)]; - fileStream.Read(bytes, 0, bytes.Length); + + if (fileStream.Read(bytes, 0, bytes.Length) != bytes.Length) { + throw new IOException("Read fewer bytes than requested!"); + } + pid = BitConverter.ToInt32(bytes, 0); } diff --git a/lib/TweetLib.Core/Systems/Updates/UpdateDownloadStatus.cs b/lib/TweetLib.Core/Systems/Updates/UpdateDownloadStatus.cs index 906eef59..773976e5 100644 --- a/lib/TweetLib.Core/Systems/Updates/UpdateDownloadStatus.cs +++ b/lib/TweetLib.Core/Systems/Updates/UpdateDownloadStatus.cs @@ -10,7 +10,7 @@ public enum UpdateDownloadStatus { public static class UpdateDownloadStatusExtensions { public static bool IsFinished(this UpdateDownloadStatus status, bool canRetry) { - return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry); + return status is UpdateDownloadStatus.AssetMissing or UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry); } } } diff --git a/lib/TweetLib.Core/Systems/Updates/UpdateInfo.cs b/lib/TweetLib.Core/Systems/Updates/UpdateInfo.cs index 4eb86ac2..f56593ab 100644 --- a/lib/TweetLib.Core/Systems/Updates/UpdateInfo.cs +++ b/lib/TweetLib.Core/Systems/Updates/UpdateInfo.cs @@ -66,7 +66,7 @@ internal void BeginSilentDownload() { internal void DeleteInstaller() { DownloadStatus = UpdateDownloadStatus.None; - if (currentDownload != null && currentDownload.IsBusy) { + if (currentDownload is { IsBusy: true }) { currentDownload.CancelAsync(); // deletes file when cancelled return; } diff --git a/lib/TweetLib.Utils/Collections/CommandLineArgs.cs b/lib/TweetLib.Utils/Collections/CommandLineArgs.cs index ca02949f..4bf1ac9f 100644 --- a/lib/TweetLib.Utils/Collections/CommandLineArgs.cs +++ b/lib/TweetLib.Utils/Collections/CommandLineArgs.cs @@ -12,7 +12,7 @@ public static CommandLineArgs FromStringArray(char entryChar, string[] array) { return args; } - public static void ReadStringArray(char entryChar, string[] array, CommandLineArgs targetArgs) { + private static void ReadStringArray(char entryChar, string[] array, CommandLineArgs targetArgs) { for (int index = 0; index < array.Length; index++) { string entry = array[index]; diff --git a/lib/TweetLib.Utils/Collections/TwoKeyDictionary.cs b/lib/TweetLib.Utils/Collections/TwoKeyDictionary.cs index ec92162b..92757f47 100644 --- a/lib/TweetLib.Utils/Collections/TwoKeyDictionary.cs +++ b/lib/TweetLib.Utils/Collections/TwoKeyDictionary.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace TweetLib.Utils.Collections { @@ -8,6 +9,8 @@ namespace TweetLib.Utils.Collections { /// <typeparam name="K1">The type of the outer key.</typeparam> /// <typeparam name="K2">The type of the inner key.</typeparam> /// <typeparam name="V">The type of the values.</typeparam> + [SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")] + [SuppressMessage("ReSharper", "UnusedMember.Global")] public sealed class TwoKeyDictionary<K1, K2, V> { private readonly Dictionary<K1, Dictionary<K2, V>> dict; private readonly int innerCapacity; diff --git a/lib/TweetLib.Utils/Data/InjectedString.cs b/lib/TweetLib.Utils/Data/InjectedString.cs index 1cc04dad..8a58850d 100644 --- a/lib/TweetLib.Utils/Data/InjectedString.cs +++ b/lib/TweetLib.Utils/Data/InjectedString.cs @@ -30,10 +30,13 @@ public string InjectInto(string targetHTML) { case Position.Before: cutIndex = index; break; + case Position.After: cutIndex = index + search.Length; break; - default: return targetHTML; + + default: + return targetHTML; } return targetHTML.Insert(cutIndex, html); diff --git a/lib/TweetLib.Utils/IO/CombinedFileStream.cs b/lib/TweetLib.Utils/IO/CombinedFileStream.cs index 0e1743a0..41bb6932 100644 --- a/lib/TweetLib.Utils/IO/CombinedFileStream.cs +++ b/lib/TweetLib.Utils/IO/CombinedFileStream.cs @@ -21,6 +21,15 @@ private static string JoinIdentifier(string[] identifier) { return string.Join(KeySeparator.ToString(), identifier.Select(ValidateIdentifier)); } + private static void ReadExactly(Stream stream, byte[] buffer) { + var length = buffer.Length; + var read = stream.Read(buffer, 0, length); + + if (read != length) { + throw new IOException("Read fewer bytes than requested: " + read + " < " + length); + } + } + private readonly Stream stream; public CombinedFileStream(Stream stream) { @@ -79,13 +88,13 @@ private void WriteStreamImpl(string identifier, Stream sourceStream) { } byte[] name = new byte[nameLength]; - stream.Read(name, 0, nameLength); + ReadExactly(stream, name); byte[] contentLength = new byte[4]; - stream.Read(contentLength, 0, 4); + ReadExactly(stream, contentLength); byte[] contents = new byte[BitConverter.ToInt32(contentLength, 0)]; - stream.Read(contents, 0, contents.Length); + ReadExactly(stream, contents); return new Entry(Encoding.UTF8.GetString(name), contents); } @@ -98,10 +107,10 @@ private void WriteStreamImpl(string identifier, Stream sourceStream) { } byte[] name = new byte[nameLength]; - stream.Read(name, 0, nameLength); + ReadExactly(stream, name); byte[] contentLength = new byte[4]; - stream.Read(contentLength, 0, 4); + ReadExactly(stream, contentLength); stream.Position += BitConverter.ToInt32(contentLength, 0); @@ -120,9 +129,7 @@ void IDisposable.Dispose() { public sealed class Entry { private string Identifier { get; } - public string KeyName { - get { return StringUtils.ExtractBefore(Identifier, KeySeparator); } - } + public string KeyName => StringUtils.ExtractBefore(Identifier, KeySeparator); public string[] KeyValue { get { diff --git a/lib/TweetLib.Utils/Serialization/TypeConverterRegistry.cs b/lib/TweetLib.Utils/Serialization/TypeConverterRegistry.cs index ea2fee13..637dc146 100644 --- a/lib/TweetLib.Utils/Serialization/TypeConverterRegistry.cs +++ b/lib/TweetLib.Utils/Serialization/TypeConverterRegistry.cs @@ -9,7 +9,7 @@ public void Register(Type type, ITypeConverter converter) { converters[type] = converter; } - public ITypeConverter? TryGet(Type type) { + internal ITypeConverter? TryGet(Type type) { return converters.TryGetValue(type, out var converter) ? converter : null; } } diff --git a/windows/TweetDuck.Video/FormPlayer.cs b/windows/TweetDuck.Video/FormPlayer.cs index 47f8428d..db950d9a 100644 --- a/windows/TweetDuck.Video/FormPlayer.cs +++ b/windows/TweetDuck.Video/FormPlayer.cs @@ -77,7 +77,7 @@ public FormPlayer(IntPtr handle, int dpi, int volume, string url, string token) Marshal.ReleaseComObject(media); - return $"{(progress / 60).ToString("00")}:{(progress % 60).ToString("00")}"; + return $"{(progress / 60):00}:{(progress % 60):00}"; }); labelTooltip.AttachTooltip(trackBarVolume, false, args => $"Volume : {trackBarVolume.Value}%"); diff --git a/windows/TweetDuck.Video/Program.cs b/windows/TweetDuck.Video/Program.cs index 08d6a59e..4fa8ceb8 100644 --- a/windows/TweetDuck.Video/Program.cs +++ b/windows/TweetDuck.Video/Program.cs @@ -8,8 +8,8 @@ namespace TweetDuck.Video { static class Program { // referenced in VideoPlayer // set by task manager -- public const int "CodeProcessKilled" = 1; - public const int CodeInvalidArgs = 2; - public const int CodeLaunchFail = 3; + private const int CodeInvalidArgs = 2; + private const int CodeLaunchFail = 3; public const int CodeMediaError = 4; public const int CodeOwnerGone = 5; public const int CodeUserRequested = 6; diff --git a/windows/TweetDuck/Browser/Notification/FormNotificationExample.cs b/windows/TweetDuck/Browser/Notification/FormNotificationExample.cs index b41a7937..23efde65 100644 --- a/windows/TweetDuck/Browser/Notification/FormNotificationExample.cs +++ b/windows/TweetDuck/Browser/Notification/FormNotificationExample.cs @@ -18,14 +18,17 @@ private static NotificationBrowser CreateBrowserImpl(IBrowserComponent browserCo protected override FormBorderStyle NotificationBorderStyle { get { + var style = base.NotificationBorderStyle; + if (Config.NotificationSize == DesktopNotification.Size.Custom) { - switch (base.NotificationBorderStyle) { - case FormBorderStyle.FixedSingle: return FormBorderStyle.Sizable; - case FormBorderStyle.FixedToolWindow: return FormBorderStyle.SizableToolWindow; - } + return style switch { + FormBorderStyle.FixedSingle => FormBorderStyle.Sizable, + FormBorderStyle.FixedToolWindow => FormBorderStyle.SizableToolWindow, + _ => style + }; } - return base.NotificationBorderStyle; + return style; } } diff --git a/windows/TweetDuck/Browser/Notification/FormNotificationMain.cs b/windows/TweetDuck/Browser/Notification/FormNotificationMain.cs index ccfa9c2c..12a6790e 100644 --- a/windows/TweetDuck/Browser/Notification/FormNotificationMain.cs +++ b/windows/TweetDuck/Browser/Notification/FormNotificationMain.cs @@ -48,7 +48,8 @@ private static int FontSizeLevel { private readonly int timerBarHeight; - protected int timeLeft, totalTime; + private int timeLeft; + protected int totalTime; protected bool pausedDuringNotification; private readonly NativeMethods.HookProc mouseHookDelegate; diff --git a/windows/TweetDuck/Browser/TrayIcon.cs b/windows/TweetDuck/Browser/TrayIcon.cs index 44b83ccb..31463570 100644 --- a/windows/TweetDuck/Browser/TrayIcon.cs +++ b/windows/TweetDuck/Browser/TrayIcon.cs @@ -48,7 +48,7 @@ public bool HasNotifications { private readonly ContextMenu contextMenu; private bool hasNotifications; - public TrayIcon() { + private TrayIcon() { InitializeComponent(); this.contextMenu = new ContextMenu(); diff --git a/windows/TweetDuck/Configuration/Arguments.cs b/windows/TweetDuck/Configuration/Arguments.cs index 9f78fa95..157ed314 100644 --- a/windows/TweetDuck/Configuration/Arguments.cs +++ b/windows/TweetDuck/Configuration/Arguments.cs @@ -32,7 +32,7 @@ public static CommandLineArgs GetCurrentClean() { return args; } - public static CommandLineArgs GetCurrentForInstaller() { + private static CommandLineArgs GetCurrentForInstaller() { CommandLineArgs args = GetCurrentClean(); args.AddFlag(ArgUpdated); return args; diff --git a/windows/TweetDuck/Configuration/UserConfig.cs b/windows/TweetDuck/Configuration/UserConfig.cs index 1344818d..26a3fcda 100644 --- a/windows/TweetDuck/Configuration/UserConfig.cs +++ b/windows/TweetDuck/Configuration/UserConfig.cs @@ -11,6 +11,7 @@ using TweetLib.Utils.Data; namespace TweetDuck.Configuration { + [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] sealed class UserConfig : BaseConfig<UserConfig>, IAppUserConfiguration { public bool FirstRun { get; set; } = true; diff --git a/windows/TweetDuck/Dialogs/FormAbout.cs b/windows/TweetDuck/Dialogs/FormAbout.cs index 96eacbc0..0ea02c3e 100644 --- a/windows/TweetDuck/Dialogs/FormAbout.cs +++ b/windows/TweetDuck/Dialogs/FormAbout.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel; using System.Drawing; -using System.IO; using System.Windows.Forms; using TweetDuck.Management; using TweetLib.Core; @@ -22,7 +21,7 @@ public FormAbout() { labelIssues.Links.Add(new LinkLabel.Link(0, labelIssues.Text.Length, Lib.IssueTrackerUrl)); try { - pictureLogo.Image = Image.FromFile(Path.Combine(App.ResourcesPath, "images/logo.png")); + pictureLogo.Image = Image.FromFile(App.LogoPath); } catch (Exception) { // ignore } diff --git a/windows/TweetDuck/Dialogs/FormPlugins.cs b/windows/TweetDuck/Dialogs/FormPlugins.cs index eb690f25..216be1eb 100644 --- a/windows/TweetDuck/Dialogs/FormPlugins.cs +++ b/windows/TweetDuck/Dialogs/FormPlugins.cs @@ -16,7 +16,7 @@ sealed partial class FormPlugins : Form, FormManager.IAppDialog { private readonly PluginManager pluginManager; - public FormPlugins() { + private FormPlugins() { InitializeComponent(); Text = Program.BrandName + " Plugins"; diff --git a/windows/TweetDuck/Dialogs/Settings/TabSettingsSounds.cs b/windows/TweetDuck/Dialogs/Settings/TabSettingsSounds.cs index 81100d77..46459845 100644 --- a/windows/TweetDuck/Dialogs/Settings/TabSettingsSounds.cs +++ b/windows/TweetDuck/Dialogs/Settings/TabSettingsSounds.cs @@ -24,7 +24,7 @@ public TabSettingsSounds(Action playSoundNotification) { tbCustomSound.Text = Config.NotificationSoundPath; tbCustomSound_TextChanged(tbCustomSound, EventArgs.Empty); - NativeMethods.SendMessage(tbCustomSound.Handle, NativeMethods.EM_SETCUEBANNER, 0, "(default TweetDeck sound)"); + NativeMethods.SetCueBanner(tbCustomSound, "(default TweetDeck sound)"); } public override void OnReady() { diff --git a/windows/TweetDuck/Plugins/PluginControl.cs b/windows/TweetDuck/Plugins/PluginControl.cs index 2dfef825..17071d0f 100644 --- a/windows/TweetDuck/Plugins/PluginControl.cs +++ b/windows/TweetDuck/Plugins/PluginControl.cs @@ -16,7 +16,7 @@ sealed partial class PluginControl : UserControl { private int nextHeight; - public PluginControl() { + private PluginControl() { InitializeComponent(); } diff --git a/windows/TweetDuck/Program.cs b/windows/TweetDuck/Program.cs index 5199888e..c3eecad3 100644 --- a/windows/TweetDuck/Program.cs +++ b/windows/TweetDuck/Program.cs @@ -71,7 +71,7 @@ private static void Main() { ErrorHandler = reporter, SystemHandler = new SystemHandler(), MessageDialogs = new MessageDialogs(), - FileDialogs = new FileDialogs(), + FileDialogs = new FileDialogs() }); errorReporter = reporter; diff --git a/windows/TweetDuck/Utils/NativeMethods.cs b/windows/TweetDuck/Utils/NativeMethods.cs index cee7fde7..a1e938d3 100644 --- a/windows/TweetDuck/Utils/NativeMethods.cs +++ b/windows/TweetDuck/Utils/NativeMethods.cs @@ -8,16 +8,16 @@ namespace TweetDuck.Utils { [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")] [SuppressMessage("ReSharper", "InconsistentNaming")] static class NativeMethods { - public static readonly IntPtr HWND_BROADCAST = new IntPtr(0xFFFF); + private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xFFFF); public static readonly IntPtr HOOK_HANDLED = new IntPtr(-1); public const int HWND_TOPMOST = -1; public const uint SWP_NOACTIVATE = 0x0010; - public const int WS_DISABLED = 0x08000000; - public const int GWL_STYLE = -16; - public const int SB_HORZ = 0; - public const int EM_SETCUEBANNER = 0x1501; + + private const int WS_DISABLED = 0x08000000; + private const int GWL_STYLE = -16; + private const int EM_SETCUEBANNER = 0x1501; public const int WM_MOUSE_LL = 14; public const int WM_MOUSEWHEEL = 0x020A; @@ -57,10 +57,10 @@ private struct MSLLHOOKSTRUCT { private static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags); [DllImport("user32.dll")] - public static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam); + private static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam); [DllImport("user32.dll")] - public static extern bool PostMessage(IntPtr hWnd, uint msg, UIntPtr wParam, IntPtr lParam); + private static extern bool PostMessage(IntPtr hWnd, uint msg, UIntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] public static extern uint RegisterWindowMessage(string messageName); @@ -100,6 +100,10 @@ public static void SetFormDisabled(Form form, bool disabled) { } } + public static void SetCueBanner(Control control, string cueText) { + SendMessage(control.Handle, EM_SETCUEBANNER, 0, cueText); + } + public static void BroadcastMessage(uint msg, uint wParam, int lParam) { PostMessage(HWND_BROADCAST, msg, new UIntPtr(wParam), new IntPtr(lParam)); }