1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-04-23 12:15:48 +02:00

Address inspections

This commit is contained in:
chylex 2022-02-05 22:45:44 +01:00
parent c4aa62fc3a
commit 933e0e54df
Signed by: chylex
GPG Key ID: 4DE42C8F19A80548
46 changed files with 140 additions and 132 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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() {}
}
}
}

View File

@ -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();
}

View File

@ -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) {

View File

@ -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) {}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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; }

View File

@ -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; }

View File

@ -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;

View File

@ -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)) {

View File

@ -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;

View File

@ -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 + '"')) + "]";
}

View File

@ -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
}

View File

@ -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"));

View File

@ -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";

View File

@ -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);

View File

@ -1,5 +1,5 @@
namespace TweetLib.Core.Systems.Dialogs {
public static class Dialogs {
internal static class Dialogs {
public const string OK = "OK";
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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];

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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}%");

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -48,7 +48,7 @@ public bool HasNotifications {
private readonly ContextMenu contextMenu;
private bool hasNotifications;
public TrayIcon() {
private TrayIcon() {
InitializeComponent();
this.contextMenu = new ContextMenu();

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -16,7 +16,7 @@ sealed partial class FormPlugins : Form, FormManager.IAppDialog {
private readonly PluginManager pluginManager;
public FormPlugins() {
private FormPlugins() {
InitializeComponent();
Text = Program.BrandName + " Plugins";

View File

@ -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() {

View File

@ -16,7 +16,7 @@ sealed partial class PluginControl : UserControl {
private int nextHeight;
public PluginControl() {
private PluginControl() {
InitializeComponent();
}

View File

@ -71,7 +71,7 @@ private static void Main() {
ErrorHandler = reporter,
SystemHandler = new SystemHandler(),
MessageDialogs = new MessageDialogs(),
FileDialogs = new FileDialogs(),
FileDialogs = new FileDialogs()
});
errorReporter = reporter;

View File

@ -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));
}