mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-04-23 12:15:48 +02:00
Address inspections
This commit is contained in:
parent
c4aa62fc3a
commit
933e0e54df
lib
TweetLib.Browser.CEF
Data
Logic
TweetLib.Browser
TweetLib.Core
App.cs
Features
Notifications
Plugins
PropertyObjectScript.csTweetDeck
Twitter
Systems
Configuration
Dialogs
Startup
Updates
TweetLib.Utils
Collections
Data
IO
Serialization
windows
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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 + '"')) + "]";
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
namespace TweetLib.Core.Systems.Dialogs {
|
||||
public static class Dialogs {
|
||||
internal static class Dialogs {
|
||||
public const string OK = "OK";
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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}%");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -48,7 +48,7 @@ public bool HasNotifications {
|
||||
private readonly ContextMenu contextMenu;
|
||||
private bool hasNotifications;
|
||||
|
||||
public TrayIcon() {
|
||||
private TrayIcon() {
|
||||
InitializeComponent();
|
||||
|
||||
this.contextMenu = new ContextMenu();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ sealed partial class FormPlugins : Form, FormManager.IAppDialog {
|
||||
|
||||
private readonly PluginManager pluginManager;
|
||||
|
||||
public FormPlugins() {
|
||||
private FormPlugins() {
|
||||
InitializeComponent();
|
||||
|
||||
Text = Program.BrandName + " Plugins";
|
||||
|
@ -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() {
|
||||
|
@ -16,7 +16,7 @@ sealed partial class PluginControl : UserControl {
|
||||
|
||||
private int nextHeight;
|
||||
|
||||
public PluginControl() {
|
||||
private PluginControl() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ private static void Main() {
|
||||
ErrorHandler = reporter,
|
||||
SystemHandler = new SystemHandler(),
|
||||
MessageDialogs = new MessageDialogs(),
|
||||
FileDialogs = new FileDialogs(),
|
||||
FileDialogs = new FileDialogs()
|
||||
});
|
||||
|
||||
errorReporter = reporter;
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user