1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-09-14 10:32:10 +02:00

Compare commits

..

36 Commits

Author SHA1 Message Date
22f491d98a Release 1.12.3 2018-01-22 07:13:50 +01:00
7908c8ebd9 Goddammit VS 2018-01-22 06:54:58 +01:00
e114a93714 Refactor and move BrowserCache, VideoPlayer, and ExportManager 2018-01-22 06:41:20 +01:00
931761600f Move and refactor browser list options a bit more again 2018-01-22 05:17:50 +01:00
e5b4b03e1a Meh 2018-01-21 09:11:40 +01:00
f1e8b3fbf0 Move option for custom program for opening links at the end for better accessibility 2018-01-21 06:33:50 +01:00
4d64243a07 Turn WindowsUtils.Browser fields into get-only properties 2018-01-21 04:25:06 +01:00
3422b4d4d6 Fix height, tab order, and recently broken scroll focus handling in Options 2018-01-21 03:29:11 +01:00
b170d529fd Add an option to disable smooth scrolling 2018-01-21 03:11:12 +01:00
83741db5aa Fix broken smooth & horizontal scrolling with cursor above columns
Closes #192
2018-01-21 01:18:59 +01:00
c4b2b3ab25 Add verbose error logging to video player & tweak Reporter.Log 2018-01-19 23:37:45 +01:00
676df44985 Fix dialog title inconsistencies 2018-01-19 22:29:53 +01:00
037adc6b5c Add a way to select a custom program for opening links
References #185
2018-01-19 20:08:48 +01:00
186d17dd98 Add an option to select an installed browser to open links in
Closes #185
2018-01-19 19:19:40 +01:00
ab9ff980ef Fix dragging twitter links over columns from some sources or w/ url parameters not working 2018-01-19 06:05:46 +01:00
f297cb2623 Add line escaping to FileSerializer for easier manual file editing 2018-01-18 20:37:29 +01:00
b53c672768 Refactor Program.ResetConfig & Program.RestartWithArgs 2018-01-18 10:58:58 +01:00
1a2b967749 Move Chromium data from LocalAppData/CEF to TweetDuck storage folder 2018-01-18 10:47:16 +01:00
6ba30c48cf Remove BrowserUtils.HeaderAcceptLanguage and use default value instead 2018-01-18 10:37:43 +01:00
1af9ee9ced Release 1.12.2 2018-01-17 16:19:28 +01:00
e50480aa35 Fix edit-design plugin modal labels changing margins with different themes 2018-01-16 22:55:21 +01:00
6943c7813f Fix hovering scrollbars not changing their color with edit-design plugin enabled 2018-01-16 22:54:53 +01:00
7c9b4382ca Fix Follow dialog closing when clicking any but the first Follow button 2018-01-16 19:20:14 +01:00
3187f97592 Rewrite 'Keep Like/Follow dialogs open' code after TD removed the old way 2018-01-15 21:25:43 +01:00
b71a367052 Merge pull request #196 from chylex/delet_audio_lib
Remove audio library
2018-01-14 11:13:31 +01:00
2d4bbf2a6f Fix sound notification extension detection and add warning to mp3 files 2018-01-14 00:08:43 +01:00
6e59dfddcc Remove audio library 2018-01-13 23:38:30 +01:00
bd92fc6ee0 Use <audio> for custom sound notifications & allow volume control for default one
Closes #195
2018-01-13 22:59:34 +01:00
2f61de7025 Add GetHandlerFactory extension method to BrowserUtils 2018-01-13 22:37:24 +01:00
8fcec7ec7c Merge remote-tracking branch 'refs/remotes/origin/master' into delet_audio_lib 2018-01-13 19:50:13 +01:00
33d9ba3871 Refactor UserConfig event invocations into a generic method 2018-01-13 19:49:16 +01:00
4f8c778ba0 Ignore errors in automatic cache clearing
Closes #194
2018-01-13 15:35:20 +01:00
804c739038 Fix broken element dragging (timeline tweets and maybe more) 2018-01-13 15:27:07 +01:00
a0445fbb12 Release 1.12.1.1 2018-01-12 12:48:14 +01:00
7ab5d7b796 Release 1.12.1 2018-01-12 12:40:09 +01:00
7f83a7773b Fix 'Show this thread' not working >_> 2018-01-12 12:39:46 +01:00
52 changed files with 741 additions and 674 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using TweetDuck.Core.Controls;
@@ -49,9 +50,13 @@ namespace TweetDuck.Configuration{
public bool KeepLikeFollowDialogsOpen { get; set; } = true;
public bool BestImageQuality { get; set; } = true;
public bool EnableAnimatedImages { get; set; } = true;
public int VideoPlayerVolume { get; set; } = 50;
private int _zoomLevel = 100;
public bool EnableSmoothScrolling { get; set; } = true;
public string BrowserPath { get; set; } = null;
private int _zoomLevel = 100;
private bool _muteNotifications;
public int VideoPlayerVolume { get; set; } = 50;
public bool EnableSpellCheck { get; set; } = false;
public string SpellCheckLanguage { get; set; } = "en-US";
@@ -82,8 +87,8 @@ namespace TweetDuck.Configuration{
public Size CustomNotificationSize { get; set; } = Size.Empty;
public int NotificationScrollSpeed { get; set; } = 100;
public int NotificationSoundVolume { get; set; } = 100;
private string _notificationSoundPath;
private int _notificationSoundVolume = 100;
public string CustomCefArgs { get; set; } = null;
public string CustomBrowserCSS { get; set; } = null;
@@ -93,45 +98,33 @@ namespace TweetDuck.Configuration{
public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
public bool IsCustomNotificationSizeSet => CustomNotificationSize != Size.Empty;
public bool IsCustomSoundNotificationSet => NotificationSoundPath != string.Empty;
public TwitterUtils.ImageQuality TwitterImageQuality => BestImageQuality ? TwitterUtils.ImageQuality.Orig : TwitterUtils.ImageQuality.Default;
public string NotificationSoundPath{
get => string.IsNullOrEmpty(_notificationSoundPath) ? string.Empty : _notificationSoundPath;
set => _notificationSoundPath = value;
get => _notificationSoundPath ?? string.Empty;
set => UpdatePropertyWithEvent(ref _notificationSoundPath, value, SoundNotificationChanged);
}
public int NotificationSoundVolume{
get => _notificationSoundVolume;
set => UpdatePropertyWithEvent(ref _notificationSoundVolume, value, SoundNotificationChanged);
}
public bool MuteNotifications{
get => _muteNotifications;
set{
if (_muteNotifications != value){
_muteNotifications = value;
MuteToggled?.Invoke(this, EventArgs.Empty);
}
}
set => UpdatePropertyWithEvent(ref _muteNotifications, value, MuteToggled);
}
public int ZoomLevel{
get => _zoomLevel;
set{
if (_zoomLevel != value){
_zoomLevel = value;
ZoomLevelChanged?.Invoke(this, EventArgs.Empty);
}
}
set => UpdatePropertyWithEvent(ref _zoomLevel, value, ZoomLevelChanged);
}
public TrayIcon.Behavior TrayBehavior{
get => _trayBehavior;
set{
if (_trayBehavior != value){
_trayBehavior = value;
TrayBehaviorChanged?.Invoke(this, EventArgs.Empty);
}
}
set => UpdatePropertyWithEvent(ref _trayBehavior, value, TrayBehaviorChanged);
}
// EVENTS
@@ -139,6 +132,7 @@ namespace TweetDuck.Configuration{
public event EventHandler MuteToggled;
public event EventHandler ZoomLevelChanged;
public event EventHandler TrayBehaviorChanged;
public event EventHandler SoundNotificationChanged;
// END OF CONFIG
@@ -148,6 +142,13 @@ namespace TweetDuck.Configuration{
this.file = file;
}
private void UpdatePropertyWithEvent<T>(ref T field, T value, EventHandler eventHandler){
if (!EqualityComparer<T>.Default.Equals(field, value)){
field = value;
eventHandler?.Invoke(this, EventArgs.Empty);
}
}
public void Save(){
try{
if (File.Exists(file)){
@@ -177,6 +178,18 @@ namespace TweetDuck.Configuration{
}
}
public void Reset(){
try{
File.Delete(file);
File.Delete(GetBackupFile(file));
}catch(Exception e){
Program.Reporter.HandleException("Configuration Error", "Could not delete configuration files to reset the options.", true, e);
return;
}
Reload();
}
private void LoadInternal(bool backup){
Serializer.Read(backup ? GetBackupFile(file) : file, this);

View File

@@ -19,7 +19,6 @@ namespace TweetDuck.Core.Bridge{
build.Append("x.openSearchInFirstColumn=").Append(Bool(Program.UserConfig.OpenSearchInFirstColumn));
build.Append("x.keepLikeFollowDialogsOpen=").Append(Bool(Program.UserConfig.KeepLikeFollowDialogsOpen));
build.Append("x.muteNotifications=").Append(Bool(Program.UserConfig.MuteNotifications));
build.Append("x.hasCustomNotificationSound=").Append(Bool(Program.UserConfig.NotificationSoundPath.Length > 0));
build.Append("x.notificationMediaPreviews=").Append(Bool(Program.UserConfig.NotificationMediaPreviews));
build.Append("x.translationTarget=").Append(Str(Program.UserConfig.TranslationTarget));
}

View File

@@ -126,7 +126,7 @@ namespace TweetDuck.Core.Bridge{
public void OnTweetSound(){
form.InvokeAsyncSafe(() => {
form.OnTweetNotification();
form.PlayNotificationSound();
form.OnTweetSound();
});
}

View File

@@ -5,17 +5,16 @@ using TweetDuck.Configuration;
using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Notification.Screenshot;
using TweetDuck.Core.Other;
using TweetDuck.Core.Other.Analytics;
using TweetDuck.Core.Other.Management;
using TweetDuck.Core.Other.Settings;
using TweetDuck.Core.Utils;
using TweetDuck.Plugins;
using TweetDuck.Plugins.Events;
using TweetDuck.Updates;
using TweetLib.Audio;
namespace TweetDuck.Core{
sealed partial class FormBrowser : Form{
@@ -50,7 +49,6 @@ namespace TweetDuck.Core{
private FormWindowState prevState;
private TweetScreenshotManager notificationScreenshotManager;
private SoundNotification soundNotification;
private VideoPlayer videoPlayer;
private AnalyticsManager analytics;
@@ -82,7 +80,6 @@ namespace TweetDuck.Core{
contextMenu.Dispose();
notificationScreenshotManager?.Dispose();
soundNotification?.Dispose();
videoPlayer?.Dispose();
analytics?.Dispose();
};
@@ -291,22 +288,6 @@ namespace TweetDuck.Core{
});
}
private void soundNotification_PlaybackError(object sender, PlaybackErrorEventArgs e){
e.Ignore = true;
using(FormMessage form = new FormMessage("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, MessageBoxIcon.Error)){
form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
Button btnOpenSettings = form.AddButton("View Options");
btnOpenSettings.Width += 16;
btnOpenSettings.Location = new Point(btnOpenSettings.Location.X-16, btnOpenSettings.Location.Y);
if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnOpenSettings){
OpenSettings(typeof(TabSettingsSounds));
}
}
}
protected override void WndProc(ref Message m){
if (isLoaded && m.Msg == Program.WindowRestoreMessage){
if (WindowsUtils.CurrentProcessID == m.WParam.ToInt32()){
@@ -357,6 +338,10 @@ namespace TweetDuck.Core{
browser.ReloadColumns();
}
public void PlaySoundNotification(){
browser.PlaySoundNotification();
}
public void ApplyROT13(){
browser.ApplyROT13();
}
@@ -459,19 +444,7 @@ namespace TweetDuck.Core{
}
}
public void PlayNotificationSound(){
if (Config.NotificationSoundPath.Length == 0){
return;
}
if (soundNotification == null){
soundNotification = new SoundNotification();
soundNotification.PlaybackError += soundNotification_PlaybackError;
}
soundNotification.SetVolume(Config.NotificationSoundVolume);
soundNotification.Play(Config.NotificationSoundPath);
public void OnTweetSound(){
TriggerAnalyticsEvent(AnalyticsFile.Event.SoundNotification);
}

View File

@@ -8,6 +8,7 @@ using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils;
using System.Collections.Generic;
using System.Linq;
using TweetDuck.Core.Management;
using TweetDuck.Core.Other;
namespace TweetDuck.Core.Handling{

View File

@@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace TweetDuck.Core.Utils{
namespace TweetDuck.Core.Management{
static class BrowserCache{
public static string CacheFolder => Path.Combine(Program.StoragePath, "Cache");
@@ -36,8 +36,14 @@ namespace TweetDuck.Core.Utils{
}
else if (shouldRun && AutoClearTimer == null){
AutoClearTimer = new Timer(state => {
if (AutoClearTimer != null && CalculateCacheSize() >= Program.SystemConfig.ClearCacheThreshold*1024L*1024L){
SetClearOnExit();
if (AutoClearTimer != null){
try{
if (CalculateCacheSize() >= Program.SystemConfig.ClearCacheThreshold*1024L*1024L){
SetClearOnExit();
}
}catch(Exception){
// TODO should probably log errors and report them at some point
}
}
}, null, TimeSpan.FromSeconds(30), TimeSpan.FromHours(4));
}

View File

@@ -2,38 +2,49 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TweetDuck.Core.Other;
using TweetDuck.Data;
using TweetDuck.Plugins;
using TweetDuck.Plugins.Enums;
namespace TweetDuck.Core.Other.Settings.Export{
sealed class ExportManager{
namespace TweetDuck.Core.Management{
sealed class ProfileManager{
private static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
private static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
[Flags]
public enum Items{
None = 0,
UserConfig = 1,
SystemConfig = 2, // TODO implement later
Session = 4,
PluginData = 8,
All = UserConfig|SystemConfig|Session|PluginData
}
public bool IsRestarting { get; private set; }
public Exception LastException { get; private set; }
private readonly string file;
private readonly PluginManager plugins;
public ExportManager(string file, PluginManager plugins){
public ProfileManager(string file, PluginManager plugins){
this.file = file;
this.plugins = plugins;
}
public bool Export(ExportFileFlags flags){
public bool Export(Items items){
try{
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
if (flags.HasFlag(ExportFileFlags.UserConfig)){
if (items.HasFlag(Items.UserConfig)){
stream.WriteFile("config", Program.UserConfigFilePath);
}
if (flags.HasFlag(ExportFileFlags.SystemConfig)){
if (items.HasFlag(Items.SystemConfig)){
stream.WriteFile("system", Program.SystemConfigFilePath);
}
if (flags.HasFlag(ExportFileFlags.PluginData)){
if (items.HasFlag(Items.PluginData)){
stream.WriteFile("plugin.config", Program.PluginConfigFilePath);
foreach(Plugin plugin in plugins.Plugins){
@@ -47,7 +58,7 @@ namespace TweetDuck.Core.Other.Settings.Export{
}
}
if (flags.HasFlag(ExportFileFlags.Session)){
if (items.HasFlag(Items.Session)){
stream.WriteFile("cookies", CookiesPath);
}
@@ -61,8 +72,8 @@ namespace TweetDuck.Core.Other.Settings.Export{
}
}
public ExportFileFlags GetImportFlags(){
ExportFileFlags flags = ExportFileFlags.None;
public Items FindImportItems(){
Items items = Items.None;
try{
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
@@ -71,33 +82,33 @@ namespace TweetDuck.Core.Other.Settings.Export{
while((key = stream.SkipFile()) != null){
switch(key){
case "config":
flags |= ExportFileFlags.UserConfig;
items |= Items.UserConfig;
break;
case "system":
flags |= ExportFileFlags.SystemConfig;
items |= Items.SystemConfig;
break;
case "plugin.config":
case "plugin.data":
flags |= ExportFileFlags.PluginData;
items |= Items.PluginData;
break;
case "cookies":
flags |= ExportFileFlags.Session;
items |= Items.Session;
break;
}
}
}
}catch(Exception e){
LastException = e;
flags = ExportFileFlags.None;
items = Items.None;
}
return flags;
return items;
}
public bool Import(ExportFileFlags flags){
public bool Import(Items items){
try{
HashSet<string> missingPlugins = new HashSet<string>();
@@ -107,14 +118,14 @@ namespace TweetDuck.Core.Other.Settings.Export{
while((entry = stream.ReadFile()) != null){
switch(entry.KeyName){
case "config":
if (flags.HasFlag(ExportFileFlags.UserConfig)){
if (items.HasFlag(Items.UserConfig)){
entry.WriteToFile(Program.UserConfigFilePath);
}
break;
case "system":
if (flags.HasFlag(ExportFileFlags.SystemConfig)){
if (items.HasFlag(Items.SystemConfig)){
entry.WriteToFile(Program.SystemConfigFilePath);
IsRestarting = true;
}
@@ -122,14 +133,14 @@ namespace TweetDuck.Core.Other.Settings.Export{
break;
case "plugin.config":
if (flags.HasFlag(ExportFileFlags.PluginData)){
if (items.HasFlag(Items.PluginData)){
entry.WriteToFile(Program.PluginConfigFilePath);
}
break;
case "plugin.data":
if (flags.HasFlag(ExportFileFlags.PluginData)){
if (items.HasFlag(Items.PluginData)){
string[] value = entry.KeyValue;
entry.WriteToFile(Path.Combine(Program.PluginDataPath, value[0], value[1]), true);
@@ -142,7 +153,7 @@ namespace TweetDuck.Core.Other.Settings.Export{
break;
case "cookies":
if (flags.HasFlag(ExportFileFlags.Session)){
if (items.HasFlag(Items.Session)){
entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath));
IsRestarting = true;
}

View File

@@ -3,10 +3,11 @@ using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Other;
using TweetDuck.Core.Utils;
using TweetLib.Communication;
namespace TweetDuck.Core.Other.Management{
namespace TweetDuck.Core.Management{
sealed class VideoPlayer : IDisposable{
public bool Running{
get{
@@ -55,11 +56,9 @@ namespace TweetDuck.Core.Other.Management{
})) != null){
currentProcess.EnableRaisingEvents = true;
currentProcess.Exited += process_Exited;
#if DEBUG
currentProcess.BeginOutputReadLine();
currentProcess.OutputDataReceived += (sender, args) => Debug.WriteLine("VideoPlayer: "+args.Data);
#endif
currentProcess.OutputDataReceived += process_OutputDataReceived;
}
currentPipe.DisposeToken();
@@ -146,6 +145,12 @@ namespace TweetDuck.Core.Other.Management{
}
}
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e){
if (!string.IsNullOrEmpty(e.Data)){
Program.Reporter.Log("[VideoPlayer] "+e.Data);
}
}
private void process_Exited(object sender, EventArgs e){
int exitCode = currentProcess.ExitCode;

View File

@@ -139,8 +139,7 @@ namespace TweetDuck.Core.Notification{
DpiScale = this.GetDPIScale();
DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
handlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
browser.GetHandlerFactory().RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
Controls.Add(browser);

View File

@@ -1,32 +1,53 @@
using System;
using TweetLib.Audio;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using CefSharp;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Other;
using TweetDuck.Core.Other.Settings;
namespace TweetDuck.Core.Notification{
sealed class SoundNotification : IDisposable{
public string SupportedFormats => player.SupportedFormats;
public event EventHandler<PlaybackErrorEventArgs> PlaybackError;
static class SoundNotification{
public const string SupportedFormats = "*.wav;*.ogg;*.flac;*.opus;*.weba;*.webm"; // TODO add mp3 when supported
public static IResourceHandler CreateFileHandler(string path){
string mimeType;
private readonly AudioPlayer player;
switch(Path.GetExtension(path)){
case ".weba":
case ".webm": mimeType = "audio/webm"; break;
case ".wav": mimeType = "audio/wav"; break;
case ".ogg": mimeType = "audio/ogg"; break;
case ".flac": mimeType = "audio/flac"; break;
case ".opus": mimeType = "audio/ogg; codecs=opus"; break;
case ".mp3": TryShowError("MP3 sound notifications are temporarily unsupported, please convert the file to another format, such as .ogg, .wav, or .flac."); return null;
default: mimeType = null; break;
}
public SoundNotification(){
this.player = AudioPlayer.New();
this.player.PlaybackError += Player_PlaybackError;
try{
return ResourceHandler.FromFilePath(path, mimeType);
}catch{
TryShowError("Could not find custom notification sound file:\n"+path);
return null;
}
}
public void Play(string file){
player.Play(file);
}
private static void TryShowError(string message){
FormBrowser browser = FormManager.TryFind<FormBrowser>();
public bool SetVolume(int volume){
return player.SetVolume(volume);
}
browser?.InvokeAsyncSafe(() => {
using(FormMessage form = new FormMessage("Sound Notification Error", message, MessageBoxIcon.Error)){
form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
Button btnViewOptions = form.AddButton("View Options");
btnViewOptions.Width += 16;
btnViewOptions.Location = new Point(btnViewOptions.Location.X-16, btnViewOptions.Location.Y);
private void Player_PlaybackError(object sender, PlaybackErrorEventArgs e){
PlaybackError?.Invoke(this, e);
}
public void Dispose(){
player.Dispose();
if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnViewOptions){
browser.OpenSettings(typeof(TabSettingsSounds));
}
}
});
}
}
}

View File

@@ -33,7 +33,7 @@
//
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnClose.AutoSize = true;
this.btnClose.Location = new System.Drawing.Point(449, 447);
this.btnClose.Location = new System.Drawing.Point(449, 483);
this.btnClose.Name = "btnClose";
this.btnClose.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnClose.Size = new System.Drawing.Size(49, 23);
@@ -52,7 +52,7 @@
this.panelContents.Location = new System.Drawing.Point(135, 12);
this.panelContents.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.panelContents.Name = "panelContents";
this.panelContents.Size = new System.Drawing.Size(363, 429);
this.panelContents.Size = new System.Drawing.Size(363, 465);
this.panelContents.TabIndex = 1;
//
// panelButtons
@@ -63,14 +63,14 @@
this.panelButtons.Location = new System.Drawing.Point(12, 12);
this.panelButtons.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.panelButtons.Name = "panelButtons";
this.panelButtons.Size = new System.Drawing.Size(124, 429);
this.panelButtons.Size = new System.Drawing.Size(124, 465);
this.panelButtons.TabIndex = 0;
//
// btnManageOptions
//
this.btnManageOptions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnManageOptions.AutoSize = true;
this.btnManageOptions.Location = new System.Drawing.Point(12, 447);
this.btnManageOptions.Location = new System.Drawing.Point(12, 483);
this.btnManageOptions.Name = "btnManageOptions";
this.btnManageOptions.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnManageOptions.Size = new System.Drawing.Size(101, 23);
@@ -83,7 +83,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(510, 482);
this.ClientSize = new System.Drawing.Size(510, 518);
this.Controls.Add(this.btnManageOptions);
this.Controls.Add(this.panelContents);
this.Controls.Add(this.panelButtons);

View File

@@ -40,7 +40,7 @@ namespace TweetDuck.Core.Other{
AddButton("Locales", () => new TabSettingsLocales());
AddButton("System Tray", () => new TabSettingsTray());
AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins)));
AddButton("Sounds", () => new TabSettingsSounds());
AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification));
AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins));
AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS));

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using TweetDuck.Configuration;
@@ -9,11 +8,20 @@ namespace TweetDuck.Core.Other.Settings{
public IEnumerable<Control> InteractiveControls{
get{
foreach(Panel panel in Controls.OfType<Panel>()){
foreach(Control control in panel.Controls){
yield return control;
IEnumerable<Control> FindInteractiveControls(Control parent){
foreach(Control control in parent.Controls){
if (control is Panel subPanel){
foreach(Control subControl in FindInteractiveControls(subPanel)){
yield return subControl;
}
}
else{
yield return control;
}
}
}
return FindInteractiveControls(this);
}
}

View File

@@ -2,7 +2,7 @@
using System.IO;
using System.Windows.Forms;
using TweetDuck.Configuration;
using TweetDuck.Core.Other.Settings.Export;
using TweetDuck.Core.Management;
using TweetDuck.Plugins;
namespace TweetDuck.Core.Other.Settings.Dialogs{
@@ -11,24 +11,25 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Deciding, Reset, Import, Export
}
public ExportFileFlags Flags{
get => selectedFlags;
private ProfileManager.Items SelectedItems{
get => _selectedItems;
set{
// this will call events and SetFlag, which also updates the UI
cbConfig.Checked = value.HasFlag(ExportFileFlags.UserConfig);
cbSession.Checked = value.HasFlag(ExportFileFlags.Session);
cbPluginData.Checked = value.HasFlag(ExportFileFlags.PluginData);
cbConfig.Checked = value.HasFlag(ProfileManager.Items.UserConfig);
cbSession.Checked = value.HasFlag(ProfileManager.Items.Session);
cbPluginData.Checked = value.HasFlag(ProfileManager.Items.PluginData);
}
}
public bool ShouldReloadBrowser { get; private set; }
private readonly PluginManager plugins;
private State currentState;
private ExportManager importManager;
private ExportFileFlags selectedFlags = ExportFileFlags.None;
private State currentState;
private ProfileManager importManager;
private ProfileManager.Items _selectedItems = ProfileManager.Items.None;
public DialogSettingsManage(PluginManager plugins){
InitializeComponent();
@@ -42,15 +43,15 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
}
private void cbConfig_CheckedChanged(object sender, EventArgs e){
SetFlag(ExportFileFlags.UserConfig, cbConfig.Checked);
SetFlag(ProfileManager.Items.UserConfig, cbConfig.Checked);
}
private void cbSession_CheckedChanged(object sender, EventArgs e){
SetFlag(ExportFileFlags.Session, cbSession.Checked);
SetFlag(ProfileManager.Items.Session, cbSession.Checked);
}
private void cbPluginData_CheckedChanged(object sender, EventArgs e){
SetFlag(ExportFileFlags.PluginData, cbPluginData.Checked);
SetFlag(ProfileManager.Items.PluginData, cbPluginData.Checked);
}
private void btnContinue_Click(object sender, EventArgs e){
@@ -63,7 +64,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
currentState = State.Reset;
Text = "Restore Defaults";
Flags = ExportFileFlags.UserConfig;
SelectedItems = ProfileManager.Items.UserConfig;
}
// Import
@@ -81,11 +82,11 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
file = dialog.FileName;
}
importManager = new ExportManager(file, plugins);
importManager = new ProfileManager(file, plugins);
currentState = State.Import;
Text = "Import Profile";
Flags = importManager.GetImportFlags();
SelectedItems = importManager.FindImportItems();
cbConfig.Enabled = cbConfig.Checked;
cbSession.Enabled = cbSession.Checked;
@@ -98,7 +99,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Text = "Export Profile";
btnContinue.Text = "Export Profile";
Flags = ExportFileFlags.All & ~ExportFileFlags.Session;
SelectedItems = ProfileManager.Items.All & ~ProfileManager.Items.Session;
}
// Continue...
@@ -108,11 +109,11 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
case State.Reset:
if (FormMessage.Warning("Reset TweetDuck Options", "This will reset the selected items. Are you sure you want to proceed?", FormMessage.Yes, FormMessage.No)){
if (Flags.HasFlag(ExportFileFlags.UserConfig)){
Program.ResetConfig();
if (SelectedItems.HasFlag(ProfileManager.Items.UserConfig)){
Program.UserConfig.Reset();
}
if (Flags.HasFlag(ExportFileFlags.SystemConfig)){
if (SelectedItems.HasFlag(ProfileManager.Items.SystemConfig)){
try{
File.Delete(Program.SystemConfigFilePath);
}catch(Exception ex){
@@ -120,7 +121,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
}
}
if (Flags.HasFlag(ExportFileFlags.PluginData)){
if (SelectedItems.HasFlag(ProfileManager.Items.PluginData)){
try{
File.Delete(Program.PluginConfigFilePath);
Directory.Delete(Program.PluginDataPath, true);
@@ -129,10 +130,10 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
}
}
if (Flags.HasFlag(ExportFileFlags.Session)){
if (SelectedItems.HasFlag(ProfileManager.Items.Session)){
Program.Restart(Arguments.ArgDeleteCookies);
}
else if (Flags.HasFlag(ExportFileFlags.SystemConfig)){
else if (SelectedItems.HasFlag(ProfileManager.Items.SystemConfig)){
Program.Restart();
}
else{
@@ -146,14 +147,14 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
break;
case State.Import:
if (importManager.Import(Flags)){
if (importManager.Import(SelectedItems)){
Program.UserConfig.Reload();
if (importManager.IsRestarting){
if (Flags.HasFlag(ExportFileFlags.Session)){
if (SelectedItems.HasFlag(ProfileManager.Items.Session)){
Program.Restart(Arguments.ArgImportCookies);
}
else if (Flags.HasFlag(ExportFileFlags.SystemConfig)){
else if (SelectedItems.HasFlag(ProfileManager.Items.SystemConfig)){
Program.Restart();
}
}
@@ -189,9 +190,9 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Program.UserConfig.Save();
Program.SystemConfig.Save();
ExportManager manager = new ExportManager(file, plugins);
ProfileManager manager = new ProfileManager(file, plugins);
if (!manager.Export(Flags)){
if (!manager.Export(SelectedItems)){
Program.Reporter.HandleException("Profile Export Error", "An exception happened while exporting TweetDuck profile.", true, manager.LastException);
}
@@ -206,15 +207,15 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Close();
}
private void SetFlag(ExportFileFlags flag, bool enable){
selectedFlags = enable ? selectedFlags | flag : selectedFlags & ~flag;
btnContinue.Enabled = selectedFlags != ExportFileFlags.None;
private void SetFlag(ProfileManager.Items flag, bool enable){
_selectedItems = enable ? _selectedItems | flag : _selectedItems & ~flag;
btnContinue.Enabled = _selectedItems != ProfileManager.Items.None;
if (currentState == State.Import){
btnContinue.Text = selectedFlags.HasFlag(ExportFileFlags.Session) ? "Import && Restart" : "Import Profile";
btnContinue.Text = _selectedItems.HasFlag(ProfileManager.Items.Session) ? "Import && Restart" : "Import Profile";
}
else if (currentState == State.Reset){
btnContinue.Text = selectedFlags.HasFlag(ExportFileFlags.Session) ? "Restore && Restart" : "Restore Defaults";
btnContinue.Text = _selectedItems.HasFlag(ProfileManager.Items.Session) ? "Restore && Restart" : "Restore Defaults";
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
namespace TweetDuck.Core.Other.Settings.Export{
[Flags]
enum ExportFileFlags{
None = 0,
UserConfig = 1,
SystemConfig = 2, // TODO implement later
Session = 4,
PluginData = 8,
All = UserConfig|SystemConfig|Session|PluginData
}
}

View File

@@ -56,7 +56,7 @@
this.btnClearCache.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.btnClearCache.Name = "btnClearCache";
this.btnClearCache.Size = new System.Drawing.Size(144, 23);
this.btnClearCache.TabIndex = 1;
this.btnClearCache.TabIndex = 5;
this.btnClearCache.Text = "Clear Cache (calculating)";
this.btnClearCache.UseVisualStyleBackColor = true;
//
@@ -67,7 +67,7 @@
this.checkHardwareAcceleration.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkHardwareAcceleration.Name = "checkHardwareAcceleration";
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
this.checkHardwareAcceleration.TabIndex = 0;
this.checkHardwareAcceleration.TabIndex = 3;
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
//
@@ -136,7 +136,7 @@
this.numClearCacheThreshold.Minimum = 100;
this.numClearCacheThreshold.Name = "numClearCacheThreshold";
this.numClearCacheThreshold.Size = new System.Drawing.Size(72, 20);
this.numClearCacheThreshold.TabIndex = 4;
this.numClearCacheThreshold.TabIndex = 1;
this.numClearCacheThreshold.TextSuffix = " MB";
this.numClearCacheThreshold.Value = 250;
//
@@ -147,7 +147,7 @@
this.checkClearCacheAuto.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkClearCacheAuto.Name = "checkClearCacheAuto";
this.checkClearCacheAuto.Size = new System.Drawing.Size(215, 17);
this.checkClearCacheAuto.TabIndex = 3;
this.checkClearCacheAuto.TabIndex = 0;
this.checkClearCacheAuto.Text = "Clear Cache Automatically When Above";
this.checkClearCacheAuto.UseVisualStyleBackColor = true;
//
@@ -195,7 +195,7 @@
this.panelClearCacheAuto.Margin = new System.Windows.Forms.Padding(0);
this.panelClearCacheAuto.Name = "panelClearCacheAuto";
this.panelClearCacheAuto.Size = new System.Drawing.Size(322, 26);
this.panelClearCacheAuto.TabIndex = 3;
this.panelClearCacheAuto.TabIndex = 6;
//
// labelCache
//
@@ -204,7 +204,7 @@
this.labelCache.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelCache.Name = "labelCache";
this.labelCache.Size = new System.Drawing.Size(38, 13);
this.labelCache.TabIndex = 2;
this.labelCache.TabIndex = 4;
this.labelCache.Text = "Cache";
//
// panelConfiguration
@@ -216,7 +216,7 @@
this.panelConfiguration.Margin = new System.Windows.Forms.Padding(0);
this.panelConfiguration.Name = "panelConfiguration";
this.panelConfiguration.Size = new System.Drawing.Size(322, 29);
this.panelConfiguration.TabIndex = 5;
this.panelConfiguration.TabIndex = 8;
//
// labelConfiguration
//
@@ -226,7 +226,7 @@
this.labelConfiguration.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelConfiguration.Name = "labelConfiguration";
this.labelConfiguration.Size = new System.Drawing.Size(104, 20);
this.labelConfiguration.TabIndex = 4;
this.labelConfiguration.TabIndex = 7;
this.labelConfiguration.Text = "Configuration";
//
// flowPanel
@@ -247,7 +247,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 295);
this.flowPanel.TabIndex = 6;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsAdvanced

View File

@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using TweetDuck.Configuration;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Management;
using TweetDuck.Core.Other.Settings.Dialogs;
using TweetDuck.Core.Utils;

View File

@@ -47,7 +47,7 @@
this.panelDataCollection.Margin = new System.Windows.Forms.Padding(0);
this.panelDataCollection.Name = "panelDataCollection";
this.panelDataCollection.Size = new System.Drawing.Size(322, 26);
this.panelDataCollection.TabIndex = 1;
this.panelDataCollection.TabIndex = 3;
//
// labelDataCollectionLink
//
@@ -58,7 +58,7 @@
this.labelDataCollectionLink.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelDataCollectionLink.Name = "labelDataCollectionLink";
this.labelDataCollectionLink.Size = new System.Drawing.Size(66, 17);
this.labelDataCollectionLink.TabIndex = 3;
this.labelDataCollectionLink.TabIndex = 1;
this.labelDataCollectionLink.TabStop = true;
this.labelDataCollectionLink.Text = "(learn more)";
this.labelDataCollectionLink.UseCompatibleTextRendering = true;
@@ -70,7 +70,7 @@
this.checkDataCollection.Margin = new System.Windows.Forms.Padding(6, 6, 0, 3);
this.checkDataCollection.Name = "checkDataCollection";
this.checkDataCollection.Size = new System.Drawing.Size(135, 17);
this.checkDataCollection.TabIndex = 2;
this.checkDataCollection.TabIndex = 0;
this.checkDataCollection.Text = "Send Anonymous Data";
this.checkDataCollection.UseVisualStyleBackColor = true;
//
@@ -101,7 +101,7 @@
this.btnSendFeedback.Name = "btnSendFeedback";
this.btnSendFeedback.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnSendFeedback.Size = new System.Drawing.Size(164, 23);
this.btnSendFeedback.TabIndex = 0;
this.btnSendFeedback.TabIndex = 1;
this.btnSendFeedback.Text = "Send Feedback / Bug Report";
this.btnSendFeedback.UseVisualStyleBackColor = true;
//
@@ -112,7 +112,7 @@
this.labelDataCollection.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelDataCollection.Name = "labelDataCollection";
this.labelDataCollection.Size = new System.Drawing.Size(79, 13);
this.labelDataCollection.TabIndex = 1;
this.labelDataCollection.TabIndex = 2;
this.labelDataCollection.Text = "Data Collection";
//
// labelFeedback
@@ -141,7 +141,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 209);
this.flowPanel.TabIndex = 2;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsFeedback

View File

@@ -41,6 +41,10 @@
this.labelUpdates = new System.Windows.Forms.Label();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.checkKeepLikeFollowDialogsOpen = new System.Windows.Forms.CheckBox();
this.labelBrowserSettings = new System.Windows.Forms.Label();
this.checkSmoothScrolling = new System.Windows.Forms.CheckBox();
this.labelBrowserPath = new System.Windows.Forms.Label();
this.comboBoxBrowserPath = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).BeginInit();
this.panelZoom.SuspendLayout();
this.flowPanel.SuspendLayout();
@@ -53,28 +57,28 @@
this.checkExpandLinks.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkExpandLinks.Name = "checkExpandLinks";
this.checkExpandLinks.Size = new System.Drawing.Size(166, 17);
this.checkExpandLinks.TabIndex = 0;
this.checkExpandLinks.TabIndex = 1;
this.checkExpandLinks.Text = "Expand Links When Hovered";
this.checkExpandLinks.UseVisualStyleBackColor = true;
//
// checkUpdateNotifications
//
this.checkUpdateNotifications.AutoSize = true;
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 268);
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 386);
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
this.checkUpdateNotifications.Size = new System.Drawing.Size(165, 17);
this.checkUpdateNotifications.TabIndex = 0;
this.checkUpdateNotifications.TabIndex = 14;
this.checkUpdateNotifications.Text = "Check Updates Automatically";
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
//
// btnCheckUpdates
//
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 291);
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 409);
this.btnCheckUpdates.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.btnCheckUpdates.Name = "btnCheckUpdates";
this.btnCheckUpdates.Size = new System.Drawing.Size(144, 23);
this.btnCheckUpdates.TabIndex = 1;
this.btnCheckUpdates.TabIndex = 15;
this.btnCheckUpdates.Text = "Check Updates Now";
this.btnCheckUpdates.UseVisualStyleBackColor = true;
//
@@ -85,7 +89,7 @@
this.labelZoomValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelZoomValue.Name = "labelZoomValue";
this.labelZoomValue.Size = new System.Drawing.Size(38, 13);
this.labelZoomValue.TabIndex = 8;
this.labelZoomValue.TabIndex = 1;
this.labelZoomValue.Text = "100%";
this.labelZoomValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
@@ -96,7 +100,7 @@
this.checkSwitchAccountSelectors.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkSwitchAccountSelectors.Name = "checkSwitchAccountSelectors";
this.checkSwitchAccountSelectors.Size = new System.Drawing.Size(172, 17);
this.checkSwitchAccountSelectors.TabIndex = 1;
this.checkSwitchAccountSelectors.TabIndex = 2;
this.checkSwitchAccountSelectors.Text = "Shift Selects Multiple Accounts";
this.checkSwitchAccountSelectors.UseVisualStyleBackColor = true;
//
@@ -107,7 +111,7 @@
this.checkBestImageQuality.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkBestImageQuality.Name = "checkBestImageQuality";
this.checkBestImageQuality.Size = new System.Drawing.Size(114, 17);
this.checkBestImageQuality.TabIndex = 3;
this.checkBestImageQuality.TabIndex = 5;
this.checkBestImageQuality.Text = "Best Image Quality";
this.checkBestImageQuality.UseVisualStyleBackColor = true;
//
@@ -118,7 +122,7 @@
this.checkOpenSearchInFirstColumn.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkOpenSearchInFirstColumn.Name = "checkOpenSearchInFirstColumn";
this.checkOpenSearchInFirstColumn.Size = new System.Drawing.Size(219, 17);
this.checkOpenSearchInFirstColumn.TabIndex = 2;
this.checkOpenSearchInFirstColumn.TabIndex = 3;
this.checkOpenSearchInFirstColumn.Text = "Add Search Columns Before First Column";
this.checkOpenSearchInFirstColumn.UseVisualStyleBackColor = true;
//
@@ -133,18 +137,18 @@
this.trackBarZoom.Name = "trackBarZoom";
this.trackBarZoom.Size = new System.Drawing.Size(148, 30);
this.trackBarZoom.SmallChange = 5;
this.trackBarZoom.TabIndex = 7;
this.trackBarZoom.TabIndex = 0;
this.trackBarZoom.TickFrequency = 25;
this.trackBarZoom.Value = 100;
//
// labelZoom
//
this.labelZoom.AutoSize = true;
this.labelZoom.Location = new System.Drawing.Point(3, 173);
this.labelZoom.Location = new System.Drawing.Point(3, 291);
this.labelZoom.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelZoom.Name = "labelZoom";
this.labelZoom.Size = new System.Drawing.Size(34, 13);
this.labelZoom.TabIndex = 6;
this.labelZoom.TabIndex = 11;
this.labelZoom.Text = "Zoom";
//
// zoomUpdateTimer
@@ -168,11 +172,11 @@
this.panelZoom.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelZoom.Controls.Add(this.trackBarZoom);
this.panelZoom.Controls.Add(this.labelZoomValue);
this.panelZoom.Location = new System.Drawing.Point(0, 186);
this.panelZoom.Location = new System.Drawing.Point(0, 304);
this.panelZoom.Margin = new System.Windows.Forms.Padding(0);
this.panelZoom.Name = "panelZoom";
this.panelZoom.Size = new System.Drawing.Size(322, 36);
this.panelZoom.TabIndex = 1;
this.panelZoom.TabIndex = 12;
//
// checkAnimatedAvatars
//
@@ -181,7 +185,7 @@
this.checkAnimatedAvatars.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkAnimatedAvatars.Name = "checkAnimatedAvatars";
this.checkAnimatedAvatars.Size = new System.Drawing.Size(145, 17);
this.checkAnimatedAvatars.TabIndex = 4;
this.checkAnimatedAvatars.TabIndex = 6;
this.checkAnimatedAvatars.Text = "Enable Animated Avatars";
this.checkAnimatedAvatars.UseVisualStyleBackColor = true;
//
@@ -189,11 +193,11 @@
//
this.labelUpdates.AutoSize = true;
this.labelUpdates.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelUpdates.Location = new System.Drawing.Point(0, 242);
this.labelUpdates.Location = new System.Drawing.Point(0, 360);
this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelUpdates.Name = "labelUpdates";
this.labelUpdates.Size = new System.Drawing.Size(70, 20);
this.labelUpdates.TabIndex = 2;
this.labelUpdates.TabIndex = 13;
this.labelUpdates.Text = "Updates";
//
// flowPanel
@@ -208,6 +212,10 @@
this.flowPanel.Controls.Add(this.checkKeepLikeFollowDialogsOpen);
this.flowPanel.Controls.Add(this.checkBestImageQuality);
this.flowPanel.Controls.Add(this.checkAnimatedAvatars);
this.flowPanel.Controls.Add(this.labelBrowserSettings);
this.flowPanel.Controls.Add(this.checkSmoothScrolling);
this.flowPanel.Controls.Add(this.labelBrowserPath);
this.flowPanel.Controls.Add(this.comboBoxBrowserPath);
this.flowPanel.Controls.Add(this.labelZoom);
this.flowPanel.Controls.Add(this.panelZoom);
this.flowPanel.Controls.Add(this.labelUpdates);
@@ -216,8 +224,8 @@
this.flowPanel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 319);
this.flowPanel.TabIndex = 4;
this.flowPanel.Size = new System.Drawing.Size(322, 438);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// checkKeepLikeFollowDialogsOpen
@@ -227,17 +235,59 @@
this.checkKeepLikeFollowDialogsOpen.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkKeepLikeFollowDialogsOpen.Name = "checkKeepLikeFollowDialogsOpen";
this.checkKeepLikeFollowDialogsOpen.Size = new System.Drawing.Size(176, 17);
this.checkKeepLikeFollowDialogsOpen.TabIndex = 7;
this.checkKeepLikeFollowDialogsOpen.TabIndex = 4;
this.checkKeepLikeFollowDialogsOpen.Text = "Keep Like/Follow Dialogs Open";
this.checkKeepLikeFollowDialogsOpen.UseVisualStyleBackColor = true;
//
// labelBrowserSettings
//
this.labelBrowserSettings.AutoSize = true;
this.labelBrowserSettings.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelBrowserSettings.Location = new System.Drawing.Point(0, 181);
this.labelBrowserSettings.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelBrowserSettings.Name = "labelBrowserSettings";
this.labelBrowserSettings.Size = new System.Drawing.Size(130, 20);
this.labelBrowserSettings.TabIndex = 7;
this.labelBrowserSettings.Text = "Browser Settings";
//
// checkSmoothScrolling
//
this.checkSmoothScrolling.AutoSize = true;
this.checkSmoothScrolling.Location = new System.Drawing.Point(6, 207);
this.checkSmoothScrolling.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkSmoothScrolling.Name = "checkSmoothScrolling";
this.checkSmoothScrolling.Size = new System.Drawing.Size(105, 17);
this.checkSmoothScrolling.TabIndex = 8;
this.checkSmoothScrolling.Text = "Smooth Scrolling";
this.checkSmoothScrolling.UseVisualStyleBackColor = true;
//
// labelBrowserPath
//
this.labelBrowserPath.AutoSize = true;
this.labelBrowserPath.Location = new System.Drawing.Point(3, 239);
this.labelBrowserPath.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelBrowserPath.Name = "labelBrowserPath";
this.labelBrowserPath.Size = new System.Drawing.Size(95, 13);
this.labelBrowserPath.TabIndex = 9;
this.labelBrowserPath.Text = "Open Links With...";
//
// comboBoxBrowserPath
//
this.comboBoxBrowserPath.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxBrowserPath.FormattingEnabled = true;
this.comboBoxBrowserPath.Location = new System.Drawing.Point(5, 255);
this.comboBoxBrowserPath.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxBrowserPath.Name = "comboBoxBrowserPath";
this.comboBoxBrowserPath.Size = new System.Drawing.Size(173, 21);
this.comboBoxBrowserPath.TabIndex = 10;
//
// TabSettingsGeneral
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsGeneral";
this.Size = new System.Drawing.Size(340, 337);
this.Size = new System.Drawing.Size(340, 456);
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).EndInit();
this.panelZoom.ResumeLayout(false);
this.flowPanel.ResumeLayout(false);
@@ -265,5 +315,9 @@
private System.Windows.Forms.CheckBox checkAnimatedAvatars;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
private System.Windows.Forms.CheckBox checkKeepLikeFollowDialogsOpen;
private System.Windows.Forms.Label labelBrowserPath;
private System.Windows.Forms.ComboBox comboBoxBrowserPath;
private System.Windows.Forms.Label labelBrowserSettings;
private System.Windows.Forms.CheckBox checkSmoothScrolling;
}
}

View File

@@ -1,6 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Utils;
using TweetDuck.Updates;
namespace TweetDuck.Core.Other.Settings{
@@ -9,6 +13,9 @@ namespace TweetDuck.Core.Other.Settings{
private readonly UpdateHandler updates;
private int updateCheckEventId = -1;
private readonly int browserListIndexDefault;
private readonly int browserListIndexCustom;
public TabSettingsGeneral(FormBrowser browser, UpdateHandler updates){
InitializeComponent();
@@ -25,15 +32,14 @@ namespace TweetDuck.Core.Other.Settings{
toolTip.SetToolTip(checkBestImageQuality, "When right-clicking a tweet image, the context menu options\r\nwill use links to the original image size (:orig in the URL).");
toolTip.SetToolTip(checkAnimatedAvatars, "Some old Twitter avatars could be uploaded as animated GIFs.");
toolTip.SetToolTip(checkSmoothScrolling, "Toggles smooth mouse wheel scrolling.");
toolTip.SetToolTip(comboBoxBrowserPath, "Sets the default browser for opening links.");
toolTip.SetToolTip(labelZoomValue, "Changes the zoom level.\r\nAlso affects notifications and screenshots.");
toolTip.SetToolTip(trackBarZoom, toolTip.GetToolTip(labelZoomValue));
toolTip.SetToolTip(checkUpdateNotifications, "Checks for updates every hour.\r\nIf an update is dismissed, it will not appear again.");
toolTip.SetToolTip(btnCheckUpdates, "Forces an update check, even for updates that had been dismissed.");
trackBarZoom.SetValueSafe(Config.ZoomLevel);
labelZoomValue.Text = trackBarZoom.Value+"%";
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
checkSwitchAccountSelectors.Checked = Config.SwitchAccountSelectors;
checkOpenSearchInFirstColumn.Checked = Config.OpenSearchInFirstColumn;
@@ -41,6 +47,19 @@ namespace TweetDuck.Core.Other.Settings{
checkBestImageQuality.Checked = Config.BestImageQuality;
checkAnimatedAvatars.Checked = Config.EnableAnimatedImages;
checkSmoothScrolling.Checked = Config.EnableSmoothScrolling;
foreach(WindowsUtils.Browser browserInfo in WindowsUtils.FindInstalledBrowsers()){
comboBoxBrowserPath.Items.Add(browserInfo);
}
browserListIndexDefault = comboBoxBrowserPath.Items.Add("(default browser)");
browserListIndexCustom = comboBoxBrowserPath.Items.Add("(custom program...)");
UpdateBrowserPathSelection();
trackBarZoom.SetValueSafe(Config.ZoomLevel);
labelZoomValue.Text = trackBarZoom.Value+"%";
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
}
@@ -51,6 +70,9 @@ namespace TweetDuck.Core.Other.Settings{
checkKeepLikeFollowDialogsOpen.CheckedChanged += checkKeepLikeFollowDialogsOpen_CheckedChanged;
checkBestImageQuality.CheckedChanged += checkBestImageQuality_CheckedChanged;
checkAnimatedAvatars.CheckedChanged += checkAnimatedAvatars_CheckedChanged;
checkSmoothScrolling.CheckedChanged += checkSmoothScrolling_CheckedChanged;
comboBoxBrowserPath.SelectedIndexChanged += comboBoxBrowserPath_SelectedIndexChanged;
trackBarZoom.ValueChanged += trackBarZoom_ValueChanged;
checkUpdateNotifications.CheckedChanged += checkUpdateNotifications_CheckedChanged;
@@ -86,6 +108,51 @@ namespace TweetDuck.Core.Other.Settings{
BrowserProcessHandler.UpdatePrefs().ContinueWith(task => browser.ReloadColumns());
}
private void checkSmoothScrolling_CheckedChanged(object sender, EventArgs e){
Config.EnableSmoothScrolling = checkSmoothScrolling.Checked;
PromptRestart();
}
private void UpdateBrowserPathSelection(){
if (string.IsNullOrEmpty(Config.BrowserPath) || !File.Exists(Config.BrowserPath)){
comboBoxBrowserPath.SelectedIndex = browserListIndexDefault;
}
else{
WindowsUtils.Browser browserInfo = comboBoxBrowserPath.Items.OfType<WindowsUtils.Browser>().FirstOrDefault(browser => browser.Path == Config.BrowserPath);
if (browserInfo == null){
comboBoxBrowserPath.SelectedIndex = browserListIndexCustom;
}
else{
comboBoxBrowserPath.SelectedItem = browserInfo;
}
}
}
private void comboBoxBrowserPath_SelectedIndexChanged(object sender, EventArgs e){
if (comboBoxBrowserPath.SelectedIndex == browserListIndexCustom){
using(OpenFileDialog dialog = new OpenFileDialog{
AutoUpgradeEnabled = true,
DereferenceLinks = true,
InitialDirectory = Path.GetDirectoryName(Config.BrowserPath), // returns null if argument is null
Title = "Open Links With...",
Filter = "Executables (*.exe;*.bat;*.cmd)|*.exe;*.bat;*.cmd|All Files (*.*)|*.*"
}){
if (dialog.ShowDialog() == DialogResult.OK){
Config.BrowserPath = dialog.FileName;
}
else{
comboBoxBrowserPath.SelectedIndexChanged -= comboBoxBrowserPath_SelectedIndexChanged;
UpdateBrowserPathSelection();
comboBoxBrowserPath.SelectedIndexChanged += comboBoxBrowserPath_SelectedIndexChanged;
}
}
}
else{
Config.BrowserPath = (comboBoxBrowserPath.SelectedItem as WindowsUtils.Browser)?.Path; // default browser item is a string and casts to null
}
}
private void trackBarZoom_ValueChanged(object sender, EventArgs e){
if (trackBarZoom.AlignValueToTick()){
zoomUpdateTimer.Stop();

View File

@@ -43,7 +43,7 @@
this.checkSpellCheck.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkSpellCheck.Name = "checkSpellCheck";
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
this.checkSpellCheck.TabIndex = 5;
this.checkSpellCheck.TabIndex = 1;
this.checkSpellCheck.Text = "Enable Spell Check";
this.checkSpellCheck.UseVisualStyleBackColor = true;
//
@@ -74,7 +74,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 193);
this.flowPanel.TabIndex = 4;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// labelSpellCheckLanguage
@@ -84,7 +84,7 @@
this.labelSpellCheckLanguage.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelSpellCheckLanguage.Name = "labelSpellCheckLanguage";
this.labelSpellCheckLanguage.Size = new System.Drawing.Size(115, 13);
this.labelSpellCheckLanguage.TabIndex = 11;
this.labelSpellCheckLanguage.TabIndex = 2;
this.labelSpellCheckLanguage.Text = "Spell Check Language";
//
// comboBoxSpellCheckLanguage
@@ -95,7 +95,7 @@
this.comboBoxSpellCheckLanguage.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxSpellCheckLanguage.Name = "comboBoxSpellCheckLanguage";
this.comboBoxSpellCheckLanguage.Size = new System.Drawing.Size(311, 21);
this.comboBoxSpellCheckLanguage.TabIndex = 9;
this.comboBoxSpellCheckLanguage.TabIndex = 3;
//
// labelTranslations
//
@@ -105,7 +105,7 @@
this.labelTranslations.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelTranslations.Name = "labelTranslations";
this.labelTranslations.Size = new System.Drawing.Size(116, 20);
this.labelTranslations.TabIndex = 10;
this.labelTranslations.TabIndex = 4;
this.labelTranslations.Text = "Bing Translator";
//
// labelTranslationTarget
@@ -115,7 +115,7 @@
this.labelTranslationTarget.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelTranslationTarget.Name = "labelTranslationTarget";
this.labelTranslationTarget.Size = new System.Drawing.Size(89, 13);
this.labelTranslationTarget.TabIndex = 8;
this.labelTranslationTarget.TabIndex = 5;
this.labelTranslationTarget.Text = "Target Language";
//
// comboBoxTranslationTarget
@@ -126,7 +126,7 @@
this.comboBoxTranslationTarget.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxTranslationTarget.Name = "comboBoxTranslationTarget";
this.comboBoxTranslationTarget.Size = new System.Drawing.Size(311, 21);
this.comboBoxTranslationTarget.TabIndex = 7;
this.comboBoxTranslationTarget.TabIndex = 6;
//
// TabSettingsLocales
//

View File

@@ -84,7 +84,7 @@
this.labelEdgeDistanceValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelEdgeDistanceValue.Name = "labelEdgeDistanceValue";
this.labelEdgeDistanceValue.Size = new System.Drawing.Size(40, 13);
this.labelEdgeDistanceValue.TabIndex = 9;
this.labelEdgeDistanceValue.TabIndex = 1;
this.labelEdgeDistanceValue.Text = "0 px";
this.labelEdgeDistanceValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
@@ -95,7 +95,7 @@
this.labelDisplay.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelDisplay.Name = "labelDisplay";
this.labelDisplay.Size = new System.Drawing.Size(41, 13);
this.labelDisplay.TabIndex = 5;
this.labelDisplay.TabIndex = 15;
this.labelDisplay.Text = "Display";
//
// comboBoxDisplay
@@ -106,7 +106,7 @@
this.comboBoxDisplay.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxDisplay.Name = "comboBoxDisplay";
this.comboBoxDisplay.Size = new System.Drawing.Size(144, 21);
this.comboBoxDisplay.TabIndex = 6;
this.comboBoxDisplay.TabIndex = 16;
//
// labelEdgeDistance
//
@@ -115,7 +115,7 @@
this.labelEdgeDistance.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelEdgeDistance.Name = "labelEdgeDistance";
this.labelEdgeDistance.Size = new System.Drawing.Size(103, 13);
this.labelEdgeDistance.TabIndex = 7;
this.labelEdgeDistance.TabIndex = 17;
this.labelEdgeDistance.Text = "Distance From Edge";
//
// radioLocCustom
@@ -183,7 +183,7 @@
this.trackBarEdgeDistance.Name = "trackBarEdgeDistance";
this.trackBarEdgeDistance.Size = new System.Drawing.Size(148, 30);
this.trackBarEdgeDistance.SmallChange = 2;
this.trackBarEdgeDistance.TabIndex = 8;
this.trackBarEdgeDistance.TabIndex = 0;
this.trackBarEdgeDistance.TickFrequency = 4;
this.trackBarEdgeDistance.Value = 8;
//
@@ -201,7 +201,7 @@
this.tableLayoutDurationButtons.RowCount = 1;
this.tableLayoutDurationButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutDurationButtons.Size = new System.Drawing.Size(171, 27);
this.tableLayoutDurationButtons.TabIndex = 5;
this.tableLayoutDurationButtons.TabIndex = 12;
//
// btnDurationMedium
//
@@ -255,7 +255,7 @@
this.labelDurationValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelDurationValue.Name = "labelDurationValue";
this.labelDurationValue.Size = new System.Drawing.Size(52, 13);
this.labelDurationValue.TabIndex = 4;
this.labelDurationValue.TabIndex = 1;
this.labelDurationValue.Text = "0 ms/c";
this.labelDurationValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
@@ -267,7 +267,7 @@
this.trackBarDuration.Minimum = 10;
this.trackBarDuration.Name = "trackBarDuration";
this.trackBarDuration.Size = new System.Drawing.Size(148, 30);
this.trackBarDuration.TabIndex = 3;
this.trackBarDuration.TabIndex = 0;
this.trackBarDuration.TickFrequency = 5;
this.trackBarDuration.Value = 25;
//
@@ -278,7 +278,7 @@
this.checkSkipOnLinkClick.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkSkipOnLinkClick.Name = "checkSkipOnLinkClick";
this.checkSkipOnLinkClick.Size = new System.Drawing.Size(113, 17);
this.checkSkipOnLinkClick.TabIndex = 2;
this.checkSkipOnLinkClick.TabIndex = 3;
this.checkSkipOnLinkClick.Text = "Skip On Link Click";
this.checkSkipOnLinkClick.UseVisualStyleBackColor = true;
//
@@ -289,7 +289,7 @@
this.checkColumnName.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkColumnName.Name = "checkColumnName";
this.checkColumnName.Size = new System.Drawing.Size(129, 17);
this.checkColumnName.TabIndex = 0;
this.checkColumnName.TabIndex = 1;
this.checkColumnName.Text = "Display Column Name";
this.checkColumnName.UseVisualStyleBackColor = true;
//
@@ -300,7 +300,7 @@
this.labelIdlePause.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelIdlePause.Name = "labelIdlePause";
this.labelIdlePause.Size = new System.Drawing.Size(89, 13);
this.labelIdlePause.TabIndex = 4;
this.labelIdlePause.TabIndex = 5;
this.labelIdlePause.Text = "Pause When Idle";
//
// comboBoxIdlePause
@@ -311,7 +311,7 @@
this.comboBoxIdlePause.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxIdlePause.Name = "comboBoxIdlePause";
this.comboBoxIdlePause.Size = new System.Drawing.Size(144, 21);
this.comboBoxIdlePause.TabIndex = 5;
this.comboBoxIdlePause.TabIndex = 6;
//
// checkNonIntrusive
//
@@ -320,7 +320,7 @@
this.checkNonIntrusive.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkNonIntrusive.Name = "checkNonIntrusive";
this.checkNonIntrusive.Size = new System.Drawing.Size(128, 17);
this.checkNonIntrusive.TabIndex = 3;
this.checkNonIntrusive.TabIndex = 4;
this.checkNonIntrusive.Text = "Non-Intrusive Popups";
this.checkNonIntrusive.UseVisualStyleBackColor = true;
//
@@ -331,7 +331,7 @@
this.checkTimerCountDown.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkTimerCountDown.Name = "checkTimerCountDown";
this.checkTimerCountDown.Size = new System.Drawing.Size(119, 17);
this.checkTimerCountDown.TabIndex = 1;
this.checkTimerCountDown.TabIndex = 9;
this.checkTimerCountDown.Text = "Timer Counts Down";
this.checkTimerCountDown.UseVisualStyleBackColor = true;
//
@@ -342,7 +342,7 @@
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkNotificationTimer.Name = "checkNotificationTimer";
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
this.checkNotificationTimer.TabIndex = 0;
this.checkNotificationTimer.TabIndex = 8;
this.checkNotificationTimer.Text = "Display Notification Timer";
this.checkNotificationTimer.UseVisualStyleBackColor = true;
//
@@ -388,7 +388,7 @@
this.panelEdgeDistance.Margin = new System.Windows.Forms.Padding(0);
this.panelEdgeDistance.Name = "panelEdgeDistance";
this.panelEdgeDistance.Size = new System.Drawing.Size(322, 36);
this.panelEdgeDistance.TabIndex = 1;
this.panelEdgeDistance.TabIndex = 18;
//
// checkMediaPreviews
//
@@ -397,7 +397,7 @@
this.checkMediaPreviews.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkMediaPreviews.Name = "checkMediaPreviews";
this.checkMediaPreviews.Size = new System.Drawing.Size(131, 17);
this.checkMediaPreviews.TabIndex = 1;
this.checkMediaPreviews.TabIndex = 2;
this.checkMediaPreviews.Text = "Show Media Previews";
this.checkMediaPreviews.UseVisualStyleBackColor = true;
//
@@ -407,7 +407,7 @@
this.labelScrollSpeedValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelScrollSpeedValue.Name = "labelScrollSpeedValue";
this.labelScrollSpeedValue.Size = new System.Drawing.Size(38, 13);
this.labelScrollSpeedValue.TabIndex = 4;
this.labelScrollSpeedValue.TabIndex = 1;
this.labelScrollSpeedValue.Text = "100%";
this.labelScrollSpeedValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
@@ -421,7 +421,7 @@
this.trackBarScrollSpeed.Name = "trackBarScrollSpeed";
this.trackBarScrollSpeed.Size = new System.Drawing.Size(148, 30);
this.trackBarScrollSpeed.SmallChange = 5;
this.trackBarScrollSpeed.TabIndex = 3;
this.trackBarScrollSpeed.TabIndex = 0;
this.trackBarScrollSpeed.TickFrequency = 25;
this.trackBarScrollSpeed.Value = 100;
//
@@ -432,7 +432,7 @@
this.labelScrollSpeed.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelScrollSpeed.Name = "labelScrollSpeed";
this.labelScrollSpeed.Size = new System.Drawing.Size(67, 13);
this.labelScrollSpeed.TabIndex = 2;
this.labelScrollSpeed.TabIndex = 21;
this.labelScrollSpeed.Text = "Scroll Speed";
//
// labelLocation
@@ -443,7 +443,7 @@
this.labelLocation.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelLocation.Name = "labelLocation";
this.labelLocation.Size = new System.Drawing.Size(70, 20);
this.labelLocation.TabIndex = 4;
this.labelLocation.TabIndex = 13;
this.labelLocation.Text = "Location";
//
// panelLocation
@@ -458,7 +458,7 @@
this.panelLocation.Margin = new System.Windows.Forms.Padding(0);
this.panelLocation.Name = "panelLocation";
this.panelLocation.Size = new System.Drawing.Size(322, 49);
this.panelLocation.TabIndex = 5;
this.panelLocation.TabIndex = 14;
//
// panelTimer
//
@@ -469,7 +469,7 @@
this.panelTimer.Margin = new System.Windows.Forms.Padding(0);
this.panelTimer.Name = "panelTimer";
this.panelTimer.Size = new System.Drawing.Size(322, 36);
this.panelTimer.TabIndex = 3;
this.panelTimer.TabIndex = 11;
//
// labelDuration
//
@@ -478,7 +478,7 @@
this.labelDuration.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelDuration.Name = "labelDuration";
this.labelDuration.Size = new System.Drawing.Size(47, 13);
this.labelDuration.TabIndex = 2;
this.labelDuration.TabIndex = 10;
this.labelDuration.Text = "Duration";
//
// labelTimer
@@ -489,7 +489,7 @@
this.labelTimer.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelTimer.Name = "labelTimer";
this.labelTimer.Size = new System.Drawing.Size(48, 20);
this.labelTimer.TabIndex = 2;
this.labelTimer.TabIndex = 7;
this.labelTimer.Text = "Timer";
//
// labelSize
@@ -500,7 +500,7 @@
this.labelSize.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelSize.Name = "labelSize";
this.labelSize.Size = new System.Drawing.Size(40, 20);
this.labelSize.TabIndex = 6;
this.labelSize.TabIndex = 19;
this.labelSize.Text = "Size";
//
// panelSize
@@ -513,7 +513,7 @@
this.panelSize.Margin = new System.Windows.Forms.Padding(0);
this.panelSize.Name = "panelSize";
this.panelSize.Size = new System.Drawing.Size(322, 25);
this.panelSize.TabIndex = 7;
this.panelSize.TabIndex = 20;
//
// durationUpdateTimer
//
@@ -552,7 +552,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 678);
this.flowPanel.TabIndex = 8;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// panelScrollSpeed
@@ -564,7 +564,7 @@
this.panelScrollSpeed.Margin = new System.Windows.Forms.Padding(0);
this.panelScrollSpeed.Name = "panelScrollSpeed";
this.panelScrollSpeed.Size = new System.Drawing.Size(322, 36);
this.panelScrollSpeed.TabIndex = 9;
this.panelScrollSpeed.TabIndex = 22;
//
// TabSettingsNotifications
//

View File

@@ -170,7 +170,7 @@ namespace TweetDuck.Core.Other.Settings{
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = false;
notification.ShowExampleNotification(false);
if (notification.IsFullyOutsideView() && FormMessage.Question("Notification is outside view", "The notification seems to be outside of view, would you like to reset its position?", FormMessage.Yes, FormMessage.No)){
if (notification.IsFullyOutsideView() && FormMessage.Question("Notification is Outside View", "The notification seems to be outside of view, would you like to reset its position?", FormMessage.Yes, FormMessage.No)){
Config.NotificationPosition = TweetNotification.Position.TopRight;
notification.MoveToVisibleLocation();

View File

@@ -36,6 +36,7 @@
this.trackBarVolume = new System.Windows.Forms.TrackBar();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.panelVolume = new System.Windows.Forms.Panel();
this.volumeUpdateTimer = new System.Windows.Forms.Timer(this.components);
this.panelSoundNotification.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit();
this.flowPanel.SuspendLayout();
@@ -58,7 +59,7 @@
this.labelVolumeValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.labelVolumeValue.Name = "labelVolumeValue";
this.labelVolumeValue.Size = new System.Drawing.Size(38, 13);
this.labelVolumeValue.TabIndex = 6;
this.labelVolumeValue.TabIndex = 1;
this.labelVolumeValue.Text = "100%";
this.labelVolumeValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
@@ -105,7 +106,7 @@
this.labelSoundNotification.Margin = new System.Windows.Forms.Padding(0);
this.labelSoundNotification.Name = "labelSoundNotification";
this.labelSoundNotification.Size = new System.Drawing.Size(198, 20);
this.labelSoundNotification.TabIndex = 1;
this.labelSoundNotification.TabIndex = 0;
this.labelSoundNotification.Text = "Custom Sound Notification";
//
// panelSoundNotification
@@ -119,7 +120,7 @@
this.panelSoundNotification.Margin = new System.Windows.Forms.Padding(0);
this.panelSoundNotification.Name = "panelSoundNotification";
this.panelSoundNotification.Size = new System.Drawing.Size(322, 55);
this.panelSoundNotification.TabIndex = 2;
this.panelSoundNotification.TabIndex = 1;
//
// labelVolume
//
@@ -128,7 +129,7 @@
this.labelVolume.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelVolume.Name = "labelVolume";
this.labelVolume.Size = new System.Drawing.Size(42, 13);
this.labelVolume.TabIndex = 4;
this.labelVolume.TabIndex = 2;
this.labelVolume.Text = "Volume";
//
// trackBarVolume
@@ -139,7 +140,7 @@
this.trackBarVolume.Maximum = 100;
this.trackBarVolume.Name = "trackBarVolume";
this.trackBarVolume.Size = new System.Drawing.Size(148, 30);
this.trackBarVolume.TabIndex = 5;
this.trackBarVolume.TabIndex = 0;
this.trackBarVolume.TickFrequency = 10;
this.trackBarVolume.Value = 100;
this.trackBarVolume.ValueChanged += new System.EventHandler(this.trackBarVolume_ValueChanged);
@@ -157,7 +158,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 136);
this.flowPanel.TabIndex = 3;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// panelVolume
@@ -168,7 +169,12 @@
this.panelVolume.Margin = new System.Windows.Forms.Padding(0);
this.panelVolume.Name = "panelVolume";
this.panelVolume.Size = new System.Drawing.Size(322, 36);
this.panelVolume.TabIndex = 2;
this.panelVolume.TabIndex = 3;
//
// volumeUpdateTimer
//
this.volumeUpdateTimer.Interval = 250;
this.volumeUpdateTimer.Tick += new System.EventHandler(this.volumeUpdateTimer_Tick);
//
// TabSettingsSounds
//
@@ -201,5 +207,6 @@
private System.Windows.Forms.TrackBar trackBarVolume;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
private System.Windows.Forms.Panel panelVolume;
private System.Windows.Forms.Timer volumeUpdateTimer;
}
}

View File

@@ -4,25 +4,18 @@ using System.IO;
using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Notification;
using TweetLib.Audio;
namespace TweetDuck.Core.Other.Settings{
sealed partial class TabSettingsSounds : BaseTabSettings{
private readonly SoundNotification soundNotification;
private readonly bool supportsChangingVolume;
private readonly Action playSoundNotification;
public TabSettingsSounds(){
public TabSettingsSounds(Action playSoundNotification){
InitializeComponent();
soundNotification = new SoundNotification();
soundNotification.PlaybackError += sound_PlaybackError;
Disposed += (sender, args) => soundNotification.Dispose();
this.playSoundNotification = playSoundNotification;
supportsChangingVolume = soundNotification.SetVolume(Config.NotificationSoundVolume);
toolTip.SetToolTip(tbCustomSound, "When empty, the default TweetDeck sound notification is used.");
trackBarVolume.Enabled = supportsChangingVolume && !string.IsNullOrEmpty(Config.NotificationSoundPath);
trackBarVolume.SetValueSafe(Config.NotificationSoundVolume);
labelVolumeValue.Text = trackBarVolume.Value+"%";
@@ -39,22 +32,29 @@ namespace TweetDuck.Core.Other.Settings{
public override void OnClosing(){
Config.NotificationSoundPath = tbCustomSound.Text;
Config.NotificationSoundVolume = trackBarVolume.Value;
}
private bool RefreshCanPlay(){
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
bool canPlay = isEmpty || File.Exists(tbCustomSound.Text);
tbCustomSound.ForeColor = canPlay ? SystemColors.WindowText : Color.Red;
btnPlaySound.Enabled = canPlay;
btnResetSound.Enabled = !isEmpty;
return canPlay;
}
private void tbCustomSound_TextChanged(object sender, EventArgs e){
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Red;
btnPlaySound.Enabled = !isEmpty;
btnResetSound.Enabled = !isEmpty;
trackBarVolume.Enabled = supportsChangingVolume && !isEmpty;
RefreshCanPlay();
}
private void btnPlaySound_Click(object sender, EventArgs e){
soundNotification.Play(tbCustomSound.Text);
}
private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){
FormMessage.Error("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, FormMessage.OK);
if (RefreshCanPlay()){
Config.NotificationSoundPath = tbCustomSound.Text;
Config.NotificationSoundVolume = trackBarVolume.Value;
playSoundNotification();
}
}
private void btnBrowseSound_Click(object sender, EventArgs e){
@@ -62,7 +62,7 @@ namespace TweetDuck.Core.Other.Settings{
AutoUpgradeEnabled = true,
DereferenceLinks = true,
Title = "Custom Notification Sound",
Filter = "Sound file ("+soundNotification.SupportedFormats+")|"+soundNotification.SupportedFormats+"|All files (*.*)|*.*"
Filter = $"Sound file ({SoundNotification.SupportedFormats})|{SoundNotification.SupportedFormats}|All files (*.*)|*.*"
}){
if (dialog.ShowDialog() == DialogResult.OK){
tbCustomSound.Text = dialog.FileName;
@@ -75,9 +75,14 @@ namespace TweetDuck.Core.Other.Settings{
}
private void trackBarVolume_ValueChanged(object sender, EventArgs e){
volumeUpdateTimer.Stop();
volumeUpdateTimer.Start();
labelVolumeValue.Text = trackBarVolume.Value+"%";
}
private void volumeUpdateTimer_Tick(object sender, EventArgs e){
Config.NotificationSoundVolume = trackBarVolume.Value;
soundNotification.SetVolume(Config.NotificationSoundVolume);
labelVolumeValue.Text = Config.NotificationSoundVolume+"%";
volumeUpdateTimer.Stop();
}
}
}

View File

@@ -40,7 +40,7 @@
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3);
this.checkTrayHighlight.Name = "checkTrayHighlight";
this.checkTrayHighlight.Size = new System.Drawing.Size(103, 17);
this.checkTrayHighlight.TabIndex = 2;
this.checkTrayHighlight.TabIndex = 3;
this.checkTrayHighlight.Text = "Enable Highlight";
this.checkTrayHighlight.UseVisualStyleBackColor = true;
//
@@ -52,7 +52,7 @@
this.comboBoxTrayType.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
this.comboBoxTrayType.Name = "comboBoxTrayType";
this.comboBoxTrayType.Size = new System.Drawing.Size(144, 21);
this.comboBoxTrayType.TabIndex = 0;
this.comboBoxTrayType.TabIndex = 1;
//
// labelTrayIcon
//
@@ -61,7 +61,7 @@
this.labelTrayIcon.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
this.labelTrayIcon.Name = "labelTrayIcon";
this.labelTrayIcon.Size = new System.Drawing.Size(52, 13);
this.labelTrayIcon.TabIndex = 1;
this.labelTrayIcon.TabIndex = 2;
this.labelTrayIcon.Text = "Tray Icon";
//
// labelTray
@@ -88,7 +88,7 @@
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 97);
this.flowPanel.TabIndex = 2;
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsTray

View File

@@ -7,6 +7,7 @@ using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Utils;
using TweetDuck.Plugins;
using TweetDuck.Plugins.Enums;
@@ -36,6 +37,8 @@ namespace TweetDuck.Core{
private readonly ChromiumWebBrowser browser;
private readonly PluginManager plugins;
private string prevSoundNotificationPath = null;
public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge bridge){
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
DialogHandler = new FileDialogHandler(),
@@ -70,6 +73,7 @@ namespace TweetDuck.Core{
Program.UserConfig.MuteToggled += UserConfig_MuteToggled;
Program.UserConfig.ZoomLevelChanged += UserConfig_ZoomLevelChanged;
Program.UserConfig.SoundNotificationChanged += UserConfig_SoundNotificationInfoChanged;
}
// setup and management
@@ -91,6 +95,7 @@ namespace TweetDuck.Core{
Program.UserConfig.MuteToggled -= UserConfig_MuteToggled;
Program.UserConfig.ZoomLevelChanged -= UserConfig_ZoomLevelChanged;
Program.UserConfig.SoundNotificationChanged -= UserConfig_SoundNotificationInfoChanged;
browser.Dispose();
}
@@ -129,6 +134,7 @@ namespace TweetDuck.Core{
ScriptLoader.ExecuteFile(e.Frame, "code.js");
InjectBrowserCSS();
ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser);
TweetDeckBridge.ResetStaticProperties();
@@ -167,6 +173,27 @@ namespace TweetDuck.Core{
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
}
private void UserConfig_SoundNotificationInfoChanged(object sender, EventArgs e){
const string soundUrl = "https://ton.twimg.com/tduck/updatesnd";
bool hasCustomSound = Program.UserConfig.IsCustomSoundNotificationSet;
if (prevSoundNotificationPath != Program.UserConfig.NotificationSoundPath){
DefaultResourceHandlerFactory handlerFactory = browser.GetHandlerFactory();
IResourceHandler resourceHandler = hasCustomSound ? SoundNotification.CreateFileHandler(Program.UserConfig.NotificationSoundPath) : null;
if (resourceHandler != null){
handlerFactory.RegisterHandler(soundUrl, resourceHandler);
}
else{
handlerFactory.UnregisterHandler(soundUrl);
}
prevSoundNotificationPath = Program.UserConfig.NotificationSoundPath;
}
browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Program.UserConfig.NotificationSoundVolume);
}
// external handling
public UpdateHandler CreateUpdateHandler(UpdaterSettings settings){
@@ -215,6 +242,10 @@ namespace TweetDuck.Core{
browser.ExecuteScriptAsync("TDGF_reloadColumns()");
}
public void PlaySoundNotification(){
browser.ExecuteScriptAsync("TDGF_playSoundNotification()");
}
public void ApplyROT13(){
browser.ExecuteScriptAsync("TDGF_applyROT13()");
}

View File

@@ -10,7 +10,6 @@ using TweetDuck.Core.Other;
namespace TweetDuck.Core.Utils{
static class BrowserUtils{
public static string HeaderAcceptLanguage => "en-us,en";
public static string HeaderUserAgent => Program.BrandName+" "+Application.ProductVersion;
public static void SetupCefArgs(IDictionary<string, string> args){
@@ -18,6 +17,10 @@ namespace TweetDuck.Core.Utils{
args["disable-gpu"] = "1";
args["disable-gpu-vsync"] = "1";
}
if (!Program.UserConfig.EnableSmoothScrolling){
args["disable-smooth-scrolling"] = "1";
}
args["disable-pdf-extension"] = "1";
args["disable-plugins-discovery"] = "1";
@@ -35,6 +38,10 @@ namespace TweetDuck.Core.Utils{
return (ChromiumWebBrowser)browserControl;
}
public static DefaultResourceHandlerFactory GetHandlerFactory(this ChromiumWebBrowser browser){
return (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
}
private const string TwitterTrackingUrl = "t.co";
public enum UrlCheckResult{
@@ -62,14 +69,25 @@ namespace TweetDuck.Core.Utils{
FormGuide.Show(hash);
}
else{
WindowsUtils.OpenAssociatedProgram(url);
string browserPath = Program.UserConfig.BrowserPath;
if (browserPath == null || !File.Exists(browserPath)){
WindowsUtils.OpenAssociatedProgram(url);
}
else{
try{
using(Process.Start(browserPath, url)){}
}catch(Exception e){
Program.Reporter.HandleException("Error Opening Browser", "Could not open the browser.", true, e);
}
}
}
break;
case UrlCheckResult.Tracking:
if (FormMessage.Warning("Blocked URL", "TweetDuck has blocked a tracking url due to privacy concerns. Do you want to visit it anyway?\n"+url, FormMessage.Yes, FormMessage.No)){
WindowsUtils.OpenAssociatedProgram(url);
goto case UrlCheckResult.Fine;
}
break;

View File

@@ -87,7 +87,7 @@ namespace TweetDuck.Core.Utils{
using(SaveFileDialog dialog = new SaveFileDialog{
AutoUpgradeEnabled = true,
OverwritePrompt = urls.Length == 1,
Title = "Save image",
Title = "Save Image",
FileName = $"{string.Join(" ", fileNameParts.Where(part => part.Length > 0))}{ext}",
Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
}){
@@ -118,7 +118,7 @@ namespace TweetDuck.Core.Utils{
using(SaveFileDialog dialog = new SaveFileDialog{
AutoUpgradeEnabled = true,
OverwritePrompt = true,
Title = "Save video",
Title = "Save Video",
FileName = string.IsNullOrEmpty(username) ? filename : $"{username} {filename}",
Filter = "Video"+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
}){

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
@@ -6,6 +7,7 @@ using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
namespace TweetDuck.Core.Utils{
static class WindowsUtils{
@@ -62,7 +64,7 @@ namespace TweetDuck.Core.Utils{
}catch(Win32Exception e) when (e.NativeErrorCode == 0x000004C7){ // operation canceled by the user
return false;
}catch(Exception e){
Program.Reporter.HandleException("Error opening file", e.Message, true, e);
Program.Reporter.HandleException("Error Opening Program", "Could not open the associated program for "+file, true, e);
return false;
}
}
@@ -130,5 +132,63 @@ namespace TweetDuck.Core.Utils{
Program.Reporter.HandleException("Clipboard Error", "TweetDuck could not access the clipboard as it is currently used by another process.", true, e);
}
}
public static IEnumerable<Browser> FindInstalledBrowsers(){
IEnumerable<Browser> ReadBrowsersFromKey(RegistryHive hive){
using(RegistryKey root = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
using(RegistryKey browserList = root.OpenSubKey(@"SOFTWARE\Clients\StartMenuInternet", false)){
if (browserList == null){
yield break;
}
foreach(string sub in browserList.GetSubKeyNames()){
using(RegistryKey browserKey = browserList.OpenSubKey(sub, false))
using(RegistryKey shellKey = browserKey?.OpenSubKey(@"shell\open\command")){
if (shellKey == null){
continue;
}
string browserName = browserKey.GetValue(null) as string;
string browserPath = shellKey.GetValue(null) as string;
if (string.IsNullOrEmpty(browserName) || string.IsNullOrEmpty(browserPath)){
continue;
}
if (browserPath[0] == '"' && browserPath[browserPath.Length-1] == '"'){
browserPath = browserPath.Substring(1, browserPath.Length-2);
}
yield return new Browser(browserName, browserPath);
}
}
}
}
HashSet<Browser> browsers = new HashSet<Browser>();
try{
browsers.UnionWith(ReadBrowsersFromKey(RegistryHive.CurrentUser));
browsers.UnionWith(ReadBrowsersFromKey(RegistryHive.LocalMachine));
}catch{
// oops I guess
}
return browsers;
}
public sealed class Browser{
public string Name { get; }
public string Path { get; }
public Browser(string name, string path){
this.Name = name;
this.Path = path;
}
public override int GetHashCode() => Name.GetHashCode();
public override bool Equals(object obj) => obj is Browser other && Name == other.Name;
public override string ToString() => Name;
}
}
}

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using TweetDuck.Core.Utils;
namespace TweetDuck.Data.Serialization{
@@ -11,6 +12,44 @@ namespace TweetDuck.Data.Serialization{
private const string NewLineReal = "\r\n";
private const string NewLineCustom = "\r~\n";
private static string EscapeLine(string input) => input.Replace("\\", "\\\\").Replace(Environment.NewLine, "\\\r\n");
private static string UnescapeLine(string input) => input.Replace(NewLineCustom, Environment.NewLine);
private static string UnescapeStream(StreamReader reader){
string data = reader.ReadToEnd();
StringBuilder build = new StringBuilder(data.Length);
int index = 0;
while(true){
int nextIndex = data.IndexOf('\\', index);
if (nextIndex == -1 || nextIndex+1 >= data.Length){
break;
}
else{
build.Append(data.Substring(index, nextIndex-index));
char next = data[nextIndex+1];
if (next == '\\'){ // convert double backslash to single backslash
build.Append('\\');
index = nextIndex+2;
}
else if (next == '\r' && nextIndex+2 < data.Length && data[nextIndex+2] == '\n'){ // convert backslash followed by CRLF to custom new line
build.Append(NewLineCustom);
index = nextIndex+3;
}
else{ // single backslash
build.Append('\\');
index = nextIndex+1;
}
}
}
return build.Append(data.Substring(index)).ToString();
}
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
public delegate void HandleUnknownPropertiesHandler(T obj, Dictionary<string, string> data);
@@ -36,13 +75,13 @@ namespace TweetDuck.Data.Serialization{
Type type = prop.Value.PropertyType;
object value = prop.Value.GetValue(obj);
if (!converters.TryGetValue(type, out ITypeConverter serializer)) {
if (!converters.TryGetValue(type, out ITypeConverter serializer)){
serializer = BasicSerializerObj;
}
if (serializer.TryWriteType(type, value, out string converted)){
if (converted != null){
writer.Write($"{prop.Key} {converted.Replace(Environment.NewLine, NewLineCustom)}");
writer.Write($"{prop.Key} {EscapeLine(converted)}");
writer.Write(NewLineReal);
}
}
@@ -65,7 +104,7 @@ namespace TweetDuck.Data.Serialization{
throw new FormatException("Input appears to be a binary file.");
}
foreach(string line in reader.ReadToEnd().Split(new string[]{ NewLineReal }, StringSplitOptions.RemoveEmptyEntries)){
foreach(string line in UnescapeStream(reader).Split(new string[]{ NewLineReal }, StringSplitOptions.RemoveEmptyEntries)){
int space = line.IndexOf(' ');
if (space == -1){
@@ -73,7 +112,7 @@ namespace TweetDuck.Data.Serialization{
}
string property = line.Substring(0, space);
string value = line.Substring(space+1).Replace(NewLineCustom, Environment.NewLine);
string value = UnescapeLine(line.Substring(space+1));
if (props.TryGetValue(property, out PropertyInfo info)){
if (!converters.TryGetValue(info.PropertyType, out ITypeConverter serializer)) {

View File

@@ -10,7 +10,7 @@ using TweetDuck.Configuration;
using TweetDuck.Core;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Other;
using TweetDuck.Core.Other.Settings.Export;
using TweetDuck.Core.Management;
using TweetDuck.Core.Utils;
using TweetDuck.Data;
using TweetDuck.Updates;
@@ -20,7 +20,7 @@ namespace TweetDuck{
public const string BrandName = "TweetDuck";
public const string Website = "https://tweetduck.chylex.com";
public const string VersionTag = "1.12";
public const string VersionTag = "1.12.3";
public static readonly bool IsPortable = File.Exists("makeportable");
@@ -32,6 +32,7 @@ namespace TweetDuck{
public static readonly string PluginDataPath = Path.Combine(StoragePath, "TD_Plugins");
private static readonly string InstallerPath = Path.Combine(StoragePath, "TD_Updates");
private static readonly string CefDataPath = Path.Combine(StoragePath, "TD_Chromium");
public static string UserConfigFilePath => Path.Combine(StoragePath, "TD_UserConfig.cfg");
public static string SystemConfigFilePath => Path.Combine(StoragePath, "TD_SystemConfig.cfg");
@@ -117,10 +118,10 @@ namespace TweetDuck{
SystemConfig = SystemConfig.Load(SystemConfigFilePath);
if (Arguments.HasFlag(Arguments.ArgImportCookies)){
ExportManager.ImportCookies();
ProfileManager.ImportCookies();
}
else if (Arguments.HasFlag(Arguments.ArgDeleteCookies)){
ExportManager.DeleteCookies();
ProfileManager.DeleteCookies();
}
if (Arguments.HasFlag(Arguments.ArgUpdated)){
@@ -131,10 +132,10 @@ namespace TweetDuck{
CefSharpSettings.WcfEnabled = false;
CefSettings settings = new CefSettings{
AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage,
UserAgent = BrowserUtils.HeaderUserAgent,
BrowserSubprocessPath = BrandName+".Browser.exe",
CachePath = StoragePath,
UserDataPath = CefDataPath,
LogFile = ConsoleLogFilePath,
#if !DEBUG
LogSeverity = Arguments.HasFlag(Arguments.ArgLogging) ? LogSeverity.Info : LogSeverity.Disable
@@ -191,18 +192,6 @@ namespace TweetDuck{
}
}
public static void ResetConfig(){
try{
File.Delete(UserConfigFilePath);
File.Delete(UserConfig.GetBackupFile(UserConfigFilePath));
}catch(Exception e){
Reporter.HandleException("Configuration Reset Error", "Could not delete configuration files to reset the options.", true, e);
return;
}
UserConfig.Reload();
}
public static void Restart(params string[] extraArgs){
CommandLineArgs args = Arguments.GetCurrentClean();
CommandLineArgs.ReadStringArray('-', extraArgs, args);
@@ -210,13 +199,14 @@ namespace TweetDuck{
}
public static void RestartWithArgs(CommandLineArgs args){
FormBrowser browserForm = Application.OpenForms.OfType<FormBrowser>().FirstOrDefault();
if (browserForm == null)return;
browserForm.ForceClose();
FormBrowser browserForm = FormManager.TryFind<FormBrowser>();
ExitCleanup();
RestartWithArgsInternal(args);
if (browserForm != null){
browserForm.ForceClose();
ExitCleanup();
RestartWithArgsInternal(args);
}
}
private static void RestartWithArgsInternal(CommandLineArgs args){

View File

@@ -1,6 +1,6 @@
# Support
[Follow TweetDuck on Twitter](https://twitter.com/TryTweetDuck) &nbsp;|&nbsp; [Support via PayPal](https://paypal.me/chylex) &nbsp;|&nbsp; [Support via Patreon](https://www.patreon.com/chylex)
[Follow the developer](https://twitter.com/chylexmc) &nbsp;|&nbsp; [Support via PayPal](https://paypal.me/chylex) &nbsp;|&nbsp; [Support via Patreon](https://www.patreon.com/chylex)
# Build Instructions

View File

@@ -23,6 +23,10 @@ namespace TweetDuck{
}
public bool Log(string data){
#if DEBUG
Debug.WriteLine(data);
#endif
StringBuilder build = new StringBuilder();
if (!File.Exists(logFile)){

View File

@@ -8,7 +8,7 @@ Edit layout & design
chylex
[version]
1.1.8
1.1.9
[website]
https://tweetduck.chylex.com

View File

@@ -367,12 +367,12 @@ enabled(){
this.css.insert(".app-content, .app-columns-container { background-color: #444448 !important }");
this.css.insert(".column-drag-handle { opacity: 0.5 !important }");
this.css.insert(".column-drag-handle:hover { opacity: 1 !important }");
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb { background-color: #666 !important }");
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #666 !important }");
notificationScrollbarColor = "666";
break;
case "light":
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb { background-color: #d2d6da !important }");
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #d2d6da !important }");
this.css.insert(".app-columns-container.scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #a5aeb5 !important }");
notificationScrollbarColor = "a5aeb5";
break;
@@ -562,7 +562,7 @@ ${this.config.revertIcons ? `
` : ``}
${notificationScrollbarColor ? `
.scroll-styled-v::-webkit-scrollbar-thumb, .scroll-styled-h::-webkit-scrollbar-thumb { background-color: #${notificationScrollbarColor} !important }
.scroll-styled-v::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #${notificationScrollbarColor} !important }
` : ``}
</style>`);
};

View File

@@ -233,7 +233,7 @@
}
.td-avatar-shape-item-outer label {
margin: 10px 0 0;
margin: 10px 0 0 !important;
}
.td-avatar-shape {

View File

@@ -507,10 +507,35 @@
//
// Block: Hook into the notification sound effect.
//
HTMLAudioElement.prototype.play = prependToFunction(HTMLAudioElement.prototype.play, function(){
return $TDX.muteNotifications || $TDX.hasCustomNotificationSound;
return $TDX.muteNotifications;
});
window.TDGF_setSoundNotificationData = function(custom, volume){
let audio = document.getElementById("update-sound");
audio.volume = volume/100;
const sourceId = "tduck-custom-sound-source";
let source = document.getElementById(sourceId);
if (custom && !source){
source = document.createElement("source");
source.id = sourceId;
source.src = "https://ton.twimg.com/tduck/updatesnd";
audio.prepend(source);
}
else if (!custom && source){
audio.removeChild(source);
}
audio.load();
};
window.TDGF_playSoundNotification = function(){
document.getElementById("update-sound").play();
};
//
// Block: Update highlighted column and tweet for context menu and other functionality.
//
@@ -734,16 +759,14 @@
// Block: Allow drag & drop behavior for dropping links on columns to open their detail view.
//
(function(){
let tweetRegex = /^https?:\/\/twitter\.com\/[A-Za-z0-9_]+\/status\/(\d+)\/?$/;
const tweetRegex = /^https?:\/\/twitter\.com\/[A-Za-z0-9_]+\/status\/(\d+)\/?\??/;
const selector = "section.js-column";
let isDraggingValid = false;
window.TDGF_onGlobalDragStart = function(type, data){
isDraggingValid = (type === "link" || type === "text") && tweetRegex.test(data);
};
app.delegate("section.js-column", {
const events = {
dragover: function(e){
e.originalEvent.dataTransfer.dropEffect = isDraggingValid ? "move" : "none";
e.originalEvent.dataTransfer.dropEffect = isDraggingValid ? "all" : "none";
e.preventDefault();
e.stopPropagation();
},
@@ -767,7 +790,17 @@
e.preventDefault();
e.stopPropagation();
}
});
};
window.TDGF_onGlobalDragStart = function(type, data){
if (type === "link"){
isDraggingValid = tweetRegex.test(data);
app.delegate(selector, events);
}
else{
app.undelegate(selector, events);
}
};
})();
//
@@ -1174,13 +1207,52 @@
//
// Block: Revert Like/Follow dialogs being closed after clicking an action.
//
if (ensurePropertyExists(TD, "decider", "get")){
const prevFunc = TD.decider.get;
(function(){
const prevSetTimeout = window.setTimeout;
TD.decider.get = function(key){
return $TDX.keepLikeFollowDialogsOpen && key.startsWith("tweetdeck_subsequent_") ? false : prevFunc.apply(this, arguments);
const overrideState = function(){
return if !$TDX.keepLikeFollowDialogsOpen;
window.setTimeout = function(func, timeout){
return timeout !== 500 && prevSetTimeout.apply(this, arguments);
};
};
}
const restoreState = function(context, key){
window.setTimeout = prevSetTimeout;
if ($TDX.keepLikeFollowDialogsOpen && key in context.state){
context.state[key] = false;
}
};
$(document).on("uiShowFavoriteFromOptions", function(){
$(".js-btn-fav", ".js-modal-inner").each(function(){
let event = $._data(this, "events").click[0];
let handler = event.handler;
event.handler = function(){
overrideState();
handler.apply(this, arguments);
restoreState($._data(document, "events").dataFavoriteState[0].handler.context, "stopSubsequentLikes");
};
});
});
$(document).on("uiShowFollowFromOptions", function(){
$(".js-component", ".js-modal-inner").each(function(){
let event = $._data(this, "events").click[0];
let handler = event.handler;
let context = handler.context;
event.handler = function(){
overrideState();
handler.apply(this, arguments);
restoreState(context, "stopSubsequentFollows");
};
});
});
})();
//
// Block: Fix DM reply input box not getting focused after opening a conversation.
@@ -1206,6 +1278,15 @@
};
}
//
// Block: Remove column mouse wheel handler, which allows smooth scrolling inside columns, and horizontally scrolling column container when holding Shift.
//
if (ensurePropertyExists(TD, "ui", "columns", "setupColumn")){
TD.ui.columns.setupColumn = appendToFunction(TD.ui.columns.setupColumn, function(e){
$(".js-column[data-column='"+e.model.getKey()+"']").off("mousewheel onmousewheel");
});
}
//
// Block: Detect and notify about connection issues.
//

View File

@@ -44,6 +44,10 @@
margin-top: 15px;
}
#td-introduction-modal p:last-child {
margin-top: 18px;
}
#td-introduction-modal footer {
padding: 10px 0;
}
@@ -78,10 +82,10 @@
<div class="mdl-inner">
<div class="mdl-content">
<p>Thank you for downloading TweetDuck!</p>
<p><a id="td-introduction-follow" href="#">Follow @TryTweetDuck</a> for latest news and updates about the app.</p>
<div class="main-menu"></div>
<p><strong>Right-click anywhere</strong> or click <strong>Settings&nbsp;&nbsp;TweetDuck</strong> in the left panel to open the main menu. You can also right-click links, tweets, images and videos, and desktop notifications to access their respective context menus.</p>
<p>Click <strong>Show Guide</strong> to see awesome features TweetDuck offers, or view the guide later by going to <strong>About TweetDuck</strong> and clicking the help button on top.</p>
<p>Follow the developer <a id="td-introduction-follow" href="#">@chylexmc</a> for latest news &amp; updates about the app, and some occasional rants.</p>
</div>
<footer class="txt-right">
<div class="anondata">
@@ -102,7 +106,7 @@
onSuccess(tdUser);
}
else{
TD.controller.clients.getPreferredClient().getUsersByIds([ "731137856052269056" ], users => onSuccess(users[0]), onError);
TD.controller.clients.getPreferredClient().getUsersByIds([ "572571847" ], users => onSuccess(users[0]), onError);
}
};

View File

@@ -114,7 +114,7 @@
return if !btn;
btn.addEventListener("click", function(){
$TD.showNotificationTweetDetail();
$TD.showTweetDetail();
});
})();

View File

@@ -159,7 +159,7 @@
<Compile Include="Core\Other\FormPlugins.Designer.cs">
<DependentUpon>FormPlugins.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\Management\VideoPlayer.cs" />
<Compile Include="Core\Management\VideoPlayer.cs" />
<Compile Include="Core\Other\Settings\Dialogs\DialogSettingsAnalytics.cs">
<SubType>Form</SubType>
</Compile>
@@ -213,8 +213,7 @@
<Compile Include="Core\Utils\StringUtils.cs" />
<Compile Include="Core\Utils\TwitterUtils.cs" />
<Compile Include="Data\CombinedFileStream.cs" />
<Compile Include="Core\Other\Settings\Export\ExportFileFlags.cs" />
<Compile Include="Core\Other\Settings\Export\ExportManager.cs" />
<Compile Include="Core\Management\ProfileManager.cs" />
<Compile Include="Core\Other\Settings\TabSettingsAdvanced.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -294,7 +293,7 @@
<Compile Include="Core\Other\TrayIcon.Designer.cs">
<DependentUpon>TrayIcon.cs</DependentUpon>
</Compile>
<Compile Include="Core\Utils\BrowserCache.cs" />
<Compile Include="Core\Management\BrowserCache.cs" />
<Compile Include="Core\Utils\BrowserUtils.cs" />
<Compile Include="Core\Utils\NativeMethods.cs" />
<Compile Include="Updates\UpdateDownloadStatus.cs" />
@@ -378,10 +377,6 @@
<Content Include="Resources\Scripts\update.js" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="lib\TweetLib.Audio\TweetLib.Audio.csproj">
<Project>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</Project>
<Name>TweetLib.Audio</Name>
</ProjectReference>
<ProjectReference Include="subprocess\TweetDuck.Browser.csproj">
<Project>{b10b0017-819e-4f71-870f-8256b36a26aa}</Project>
<Name>TweetDuck.Browser</Name>

View File

@@ -8,8 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Browser", "subpro
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests.csproj", "{A958FA7A-4A2C-42A7-BFA0-159343483F4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Audio", "lib\TweetLib.Audio\TweetLib.Audio.csproj", "{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Video", "video\TweetDuck.Video.csproj", "{278B2D11-402D-44B6-B6A1-8FA67DB65565}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
@@ -32,10 +30,6 @@ Global
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.ActiveCfg = Debug|x86
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.Build.0 = Debug|x86
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.ActiveCfg = Release|x86
{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.ActiveCfg = Debug|x86
{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.Build.0 = Debug|x86
{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.ActiveCfg = Release|x86
{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.Build.0 = Release|x86
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.ActiveCfg = Debug|x86
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.Build.0 = Debug|x86
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Release|x86.ActiveCfg = Release|x86

View File

@@ -59,6 +59,7 @@ Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\Cache"
Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\GPUCache"
[InstallDelete]
Type: files; Name: "{app}\TweetLib.Audio.dll"
Type: filesandordirs; Name: "{app}\plugins\official"
Type: files; Name: "{app}\locales\am.pak"
Type: files; Name: "{app}\locales\ar.pak"

View File

@@ -1,41 +0,0 @@
using System;
using System.Runtime.InteropServices;
using TweetLib.Audio.Impl;
namespace TweetLib.Audio{
public abstract class AudioPlayer : IDisposable{
private static bool? IsWMPAvailable;
public static AudioPlayer New(){
if (IsWMPAvailable.HasValue){
if (IsWMPAvailable.Value){
return new SoundPlayerImplWMP();
}
else{
return new SoundPlayerImplFallback();
}
}
try{
SoundPlayerImplWMP implWMP = new SoundPlayerImplWMP();
IsWMPAvailable = true;
return implWMP;
}catch(COMException){
IsWMPAvailable = false;
return new SoundPlayerImplFallback();
}
}
public abstract string SupportedFormats { get; }
public abstract event EventHandler<PlaybackErrorEventArgs> PlaybackError;
public abstract void Play(string file);
public abstract bool SetVolume(int volume);
protected abstract void Dispose(bool disposing);
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -1,53 +0,0 @@
using System;
using System.IO;
using System.Media;
namespace TweetLib.Audio.Impl{
sealed class SoundPlayerImplFallback : AudioPlayer{
public override string SupportedFormats => "*.wav";
public override event EventHandler<PlaybackErrorEventArgs> PlaybackError;
private readonly SoundPlayer player;
private bool ignorePlaybackError;
public SoundPlayerImplFallback(){
player = new SoundPlayer{
LoadTimeout = 5000
};
}
public override void Play(string file){
if (player.SoundLocation != file){
player.SoundLocation = file;
ignorePlaybackError = false;
}
try{
player.Play();
}catch(FileNotFoundException e){
OnNotificationSoundError("File not found: "+e.FileName);
}catch(InvalidOperationException){
OnNotificationSoundError("File format was not recognized.");
}catch(TimeoutException){
OnNotificationSoundError("File took too long to load.");
}
}
public override bool SetVolume(int volume){
return false;
}
protected override void Dispose(bool disposing){
player.Dispose();
}
private void OnNotificationSoundError(string message){
if (!ignorePlaybackError){
PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
PlaybackError?.Invoke(this, args);
ignorePlaybackError = args.Ignore;
}
}
}
}

View File

@@ -1,124 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using WMPLib;
namespace TweetLib.Audio.Impl{
sealed class SoundPlayerImplWMP : AudioPlayer{
public override string SupportedFormats => "*.wav;*.mp3;*.mp2;*.m4a;*.mid;*.midi;*.rmi;*.wma;*.aif;*.aifc;*.aiff;*.snd;*.au";
public override event EventHandler<PlaybackErrorEventArgs> PlaybackError;
private readonly Form owner;
private readonly ControlWMP wmp;
private bool wasTryingToPlay;
private bool ignorePlaybackError;
private WindowsMediaPlayer Player => wmp.Ocx;
public SoundPlayerImplWMP(){
owner = new Form();
wmp = new ControlWMP();
wmp.BeginInit();
owner.Controls.Add(wmp);
wmp.EndInit();
Player.uiMode = "none";
Player.settings.autoStart = false;
Player.settings.enableErrorDialogs = false;
Player.settings.invokeURLs = false;
Player.settings.volume = 0;
Player.MediaChange += player_MediaChange;
Player.MediaError += player_MediaError;
}
public override void Play(string file){
wasTryingToPlay = true;
try{
if (Player.URL != file){
Player.close();
Player.URL = file;
ignorePlaybackError = false;
}
else{
Player.controls.stop();
}
Player.controls.play();
}catch(Exception e){
OnNotificationSoundError("An error occurred in Windows Media Player: "+e.Message);
}
}
public override bool SetVolume(int volume){
Player.settings.volume = volume;
return true;
}
protected override void Dispose(bool disposing){
wmp.Dispose();
owner.Dispose();
}
private void player_MediaChange(object item){
IWMPMedia2 media = item as IWMPMedia2;
if (media == null){
OnNotificationSoundError("Unknown error.");
return;
}
// ReSharper disable once CompareOfFloatsByEqualityOperator
else if (media.Error == null && media.duration == 0.0){
OnNotificationSoundError("File does not contain an audio track.");
}
else if (media.Error != null){
OnNotificationSoundError(media.Error);
}
Marshal.ReleaseComObject(media);
}
private void player_MediaError(object pMediaObject){
IWMPMedia2 media = pMediaObject as IWMPMedia2;
if (media == null){
OnNotificationSoundError("Unknown error.");
return;
}
else if (media.Error != null){
OnNotificationSoundError(media.Error);
}
Marshal.ReleaseComObject(media);
}
private void OnNotificationSoundError(IWMPErrorItem error){
OnNotificationSoundError(error.errorCode == -1072885353 ? "Invalid media file." : error.errorDescription);
Marshal.ReleaseComObject(error);
}
private void OnNotificationSoundError(string message){
if (wasTryingToPlay){
wasTryingToPlay = false;
if (!ignorePlaybackError){
PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
PlaybackError?.Invoke(this, args);
ignorePlaybackError = args.Ignore;
}
}
}
[Clsid("{6bf52a52-394a-11d3-b153-00c04f79faa6}")]
private sealed class ControlWMP : AxHost{
public WindowsMediaPlayer Ocx { get; private set; }
public ControlWMP() : base("6bf52a52-394a-11d3-b153-00c04f79faa6"){}
protected override void AttachInterfaces(){
Ocx = (WindowsMediaPlayer)GetOcx();
}
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
namespace TweetLib.Audio{
public sealed class PlaybackErrorEventArgs : EventArgs{
public string Message { get; }
public bool Ignore { get; set; }
public PlaybackErrorEventArgs(string message){
this.Message = message;
this.Ignore = false;
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TweetDuck Audio Library")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TweetDuck Audio Library")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("e9e1fd1b-f480-45b7-9970-be2ecfd309ac")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.1.0")]
[assembly: AssemblyFileVersion("1.1.1.0")]

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TweetLib.Audio</RootNamespace>
<AssemblyName>TweetLib.Audio</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ResolveComReferenceSilent>True</ResolveComReferenceSilent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Include="AudioPlayer.cs" />
<Compile Include="PlaybackErrorEventArgs.cs" />
<Compile Include="Impl\SoundPlayerImplFallback.cs" />
<Compile Include="Impl\SoundPlayerImplWMP.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<COMReference Include="WMPLib">
<Guid>{6BF52A50-394A-11D3-B153-00C04F79FAA6}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -13,7 +13,9 @@ namespace UnitTests.Data{
private class SerializationTestBasic{
public bool TestBool { get; set; }
public int TestInt { get; set; }
public string TestString { get; set; }
public string TestStringBasic { get; set; }
public string TestStringNewLine { get; set; }
public string TestStringBackslash { get; set; }
public string TestStringNull { get; set; }
public TestEnum TestEnum { get; set; }
}
@@ -25,7 +27,9 @@ namespace UnitTests.Data{
SerializationTestBasic write = new SerializationTestBasic{
TestBool = true,
TestInt = -100,
TestString = "abc"+Environment.NewLine+"def",
TestStringBasic = "hello123",
TestStringNewLine = "abc"+Environment.NewLine+"def"+Environment.NewLine,
TestStringBackslash = @"C:\Test\\\Abc\",
TestStringNull = null,
TestEnum = TestEnum.D
};
@@ -38,7 +42,9 @@ namespace UnitTests.Data{
Assert.IsTrue(read.TestBool);
Assert.AreEqual(-100, read.TestInt);
Assert.AreEqual("abc"+Environment.NewLine+"def", read.TestString);
Assert.AreEqual("hello123", read.TestStringBasic);
Assert.AreEqual("abc"+Environment.NewLine+"def"+Environment.NewLine, read.TestStringNewLine);
Assert.AreEqual(@"C:\Test\\\Abc\", read.TestStringBackslash);
Assert.IsNull(read.TestStringNull);
Assert.AreEqual(TestEnum.D, read.TestEnum);
}

View File

@@ -102,8 +102,10 @@ namespace TweetDuck.Video{
}
private void player_MediaError(object pMediaObject){
Console.Out.WriteLine(((IWMPMedia2)pMediaObject).Error.errorDescription);
IWMPErrorItem error = ((IWMPMedia2)pMediaObject).Error;
Console.Out.WriteLine($"Media Error {error.errorCode}: {error.errorDescription}");
Marshal.ReleaseComObject(error);
Marshal.ReleaseComObject(pMediaObject);
Environment.Exit(Program.CODE_MEDIA_ERROR);
}

View File

@@ -5,7 +5,7 @@ using System.Windows.Forms;
namespace TweetDuck.Video{
static class Program{
internal const string Version = "1.2.1.0";
internal const string Version = "1.2.2.0";
// referenced in VideoPlayer
// set by task manager -- public const int CODE_PROCESS_KILLED = 1;
@@ -40,7 +40,7 @@ namespace TweetDuck.Video{
try{
Application.Run(new FormPlayer(ownerHandle, defaultVolume, videoUrl, pipeToken));
}catch(Exception e){
Console.Out.WriteLine(e.Message);
Console.Out.WriteLine(e);
return CODE_LAUNCH_FAIL;
}