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

Compare commits

..

93 Commits

Author SHA1 Message Date
62449450f3 Release 1.12.4 2018-01-29 08:40:38 +01:00
b290c94635 Fix a video player crash caused by not handling remote commands on UI thread 2018-01-29 08:20:33 +01:00
f909b887d9 Fix screenshot issues (wrong media size and margin, hide "Show this thread") 2018-01-28 21:48:57 +01:00
5cf4843212 Fix broken screenshots of tweets with just one line of text 2018-01-28 21:40:18 +01:00
b3d1e1bfac Fix example notification timer breaking on skip (forward mouse button or Enter) 2018-01-28 20:54:49 +01:00
df47499a28 Update example notification (username, avatar, improve text) 2018-01-28 20:50:18 +01:00
421475ec87 Add a notification and way to follow the new TweetDuck account 2018-01-28 20:22:13 +01:00
29d999b8eb Remove old data collection notification that was shown after updating 2018-01-28 20:05:50 +01:00
acacd9a5e5 Fix reversed button tab order in FormMessage 2018-01-28 19:39:12 +01:00
b81c26f93f Add an option to ignore tracking URL warnings (t.co) 2018-01-28 19:38:40 +01:00
00b212944c Implement top tier account bamboozle scheme 2018-01-28 19:12:32 +01:00
70ba006e4d Reorganize logo file resources and remove about.png 2018-01-26 17:44:41 +01:00
118e0cae62 Compress the logo in the About form 2018-01-26 17:36:15 +01:00
c003bb4e71 Add a way to display the TweetDuck logo in the browser 2018-01-26 17:32:54 +01:00
e9b2fa7603 Release 1.12.3.1 2018-01-26 15:58:17 +01:00
35afaa105d Fix text alignment in the Feedback tab in Options 2018-01-26 15:49:44 +01:00
2e300a7b8f Fix broken stylesheets in notifications after a recent TweetDeck update
Closes #199
2018-01-26 15:43:52 +01:00
f3f5b88550 Refactor resource handler related extension methods 2018-01-22 14:53:38 +01:00
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
fc9e8a808f Fix emoji inline tweak not working in DMs 2018-01-11 21:48:00 +01:00
5ab8976bc7 Fix broken links in guide because Chromium is an idiot 2018-01-11 21:06:31 +01:00
e2a28f2811 Allow typing unambiguous :emoji: in inline replies 2018-01-11 20:15:56 +01:00
137a20ed0e Fix notification tooltip not disappearing when skipping/closing without moving mouse 2018-01-11 00:06:18 +01:00
f956f696f4 Limit some $TD functions to browser/notification, change displayTooltip params 2018-01-10 23:53:37 +01:00
bb7cbde38f Make 'Show this thread' in notification open tweet detail
Closes #191
2018-01-10 22:47:50 +01:00
8c452d3fa2 Fix clipboard html styles when copying text from notifications 2018-01-10 22:47:06 +01:00
f65c33c432 Add newly added option to analytics report 2018-01-10 22:17:30 +01:00
da2758ccb1 Add option to keep Like/Follow dialogs open
Closes #193
2018-01-10 14:22:47 +01:00
de10112b7f Remove non-english locale files from the installation 2018-01-03 16:23:56 +01:00
301d4fb171 Replace app locale option with spell check language & use correct lang list 2018-01-03 16:04:11 +01:00
f0a79add14 Fix broken example notification after closing it and then changing options 2018-01-03 14:52:47 +01:00
d33bc9fe25 Release 1.12 2018-01-01 01:48:48 +01:00
a2a5dfd435 Reset the official plugins folder in the update installer 2018-01-01 01:27:58 +01:00
f3d7c8d4c3 Set language header to match app locale 2017-12-31 14:21:21 +01:00
67f60dd787 Merge pull request #190 from chylex/locale_magic
Add options for app locale (remove argument) & target translation language
2017-12-31 14:03:15 +01:00
62310ce4a4 Add an option to set target language for tweet translations 2017-12-31 13:59:19 +01:00
3a27089364 Add an option to set app locale in a new Options tab & remove locale argument 2017-12-31 13:29:38 +01:00
a05460f562 Make BrowserCache.CacheFolder a property 2017-12-31 12:14:45 +01:00
390872c305 Merge pull request #189 from chylex/settings_ui_plz 2017-12-31 10:26:23 +01:00
594d12df79 Reorganize all Options tabs into FlowLayoutPanels 2017-12-31 10:20:42 +01:00
c42c12c72b Move Options tooltips outside designer files & reorder options in code 2017-12-31 08:10:24 +01:00
c37f4fe365 Merge branch 'master' of https://github.com/chylex/TweetDuck 2017-12-31 07:02:20 +01:00
8d37d68770 Fix dragging links not stripping t.co shortener
Closes #183
2017-12-31 06:59:17 +01:00
1b3d1fb36a Tweak readme wording 2017-12-31 05:36:32 +01:00
2f352ef9bb Update CefSharp to 63-pre01 and update documentation 2017-12-31 05:34:36 +01:00
527f3cab4c Fix reinstantiating AnalyticsManager when restoring from tray & test stuff 2017-12-31 05:01:23 +01:00
f67bf27db2 Add an option to automatically clear cache after exceeding a set size
Closes #182
2017-12-30 02:06:36 +01:00
a8bb3ba349 Improve performance and safety of cache size checking & clearing 2017-12-28 04:52:53 +01:00
321ab12213 WTF is AnyCPU doing in the project files 2017-12-28 00:50:51 +01:00
4cab18e557 Merge pull request #187 from chylex/cefsharp63
Update CefSharp to 63 (early build) & delete GC reload
2017-12-28 00:39:07 +01:00
c15ea97a36 Update CEF again 2017-12-28 00:32:26 +01:00
a0cc4109df Delete GC reload in CEF 63 (#186) 2017-12-28 00:03:24 +01:00
f66ff1000a Replace AbstractRequestHandler with CefSharp's implementation 2017-12-21 22:45:29 +01:00
51a9bb6d3c Update CefSharp to 63 pre-release 2017-12-21 20:25:36 +01:00
07017bd29b Fix cut off usernames in Messages column 2017-12-21 20:15:02 +01:00
45b6f49a08 Fix middle-click and ctrl-click handling in CEF 62 2017-12-07 20:07:15 +01:00
103ad72788 Update CefSharp to 62 (early build) 2017-12-07 19:50:43 +01:00
543259f29f Release 1.11.2 2017-11-21 07:07:24 +01:00
94 changed files with 2229 additions and 2001 deletions

View File

@@ -5,7 +5,6 @@ namespace TweetDuck.Configuration{
static class Arguments{
// public args
public const string ArgDataFolder = "-datafolder";
public const string ArgLocale = "-locale";
public const string ArgLogging = "-log";
public const string ArgDebugUpdates = "-debugupdates";

View File

@@ -4,7 +4,9 @@ using TweetDuck.Data.Serialization;
namespace TweetDuck.Configuration{
sealed class SystemConfig{
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>();
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>{
HandleUnknownProperties = FileSerializer<SystemConfig>.IgnoreProperties("EnableBrowserGCReload", "BrowserMemoryThreshold")
};
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
File.Exists(Path.Combine(Program.ProgramPath, "libGLESv2.dll"));
@@ -13,8 +15,8 @@ namespace TweetDuck.Configuration{
private bool _hardwareAcceleration = true;
public bool EnableBrowserGCReload { get; set; } = true;
public int BrowserMemoryThreshold { get; set; } = 400;
public bool ClearCacheAutomatically { get; set; } = true;
public int ClearCacheThreshold { get; set; } = 250;
// SPECIAL PROPERTIES

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using TweetDuck.Core.Controls;
@@ -10,7 +11,9 @@ using TweetDuck.Data.Serialization;
namespace TweetDuck.Configuration{
sealed class UserConfig{
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>();
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>{
HandleUnknownProperties = FileSerializer<UserConfig>.IgnoreProperties("AppLocale", "ShowDataCollectionNotification")
};
static UserConfig(){
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
@@ -36,7 +39,7 @@ namespace TweetDuck.Configuration{
public bool FirstRun { get; set; } = true;
public bool AllowDataCollection { get; set; } = false;
public bool ShowDataCollectionNotification { get; set; } = true;
public bool ShowFollowNotification { get; set; } = true;
public WindowState BrowserWindow { get; set; } = new WindowState();
public WindowState PluginsWindow { get; set; } = new WindowState();
@@ -44,13 +47,22 @@ namespace TweetDuck.Configuration{
public bool ExpandLinksOnHover { get; set; } = true;
public bool SwitchAccountSelectors { get; set; } = true;
public bool OpenSearchInFirstColumn { get; set; } = true;
public bool KeepLikeFollowDialogsOpen { get; set; } = true;
public bool BestImageQuality { get; set; } = true;
public bool EnableAnimatedImages { get; set; } = true;
public bool EnableSpellCheck { get; set; } = false;
public int VideoPlayerVolume { get; set; } = 50;
public bool IgnoreTrackingUrlWarning { get; set; } = false;
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";
public string TranslationTarget { get; set; } = "en";
private TrayIcon.Behavior _trayBehavior = TrayIcon.Behavior.Disabled;
public bool EnableTrayHighlight { get; set; } = true;
@@ -76,8 +88,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;
@@ -87,45 +99,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
@@ -133,6 +133,7 @@ namespace TweetDuck.Configuration{
public event EventHandler MuteToggled;
public event EventHandler ZoomLevelChanged;
public event EventHandler TrayBehaviorChanged;
public event EventHandler SoundNotificationChanged;
// END OF CONFIG
@@ -142,6 +143,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)){
@@ -171,6 +179,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

@@ -7,9 +7,8 @@ namespace TweetDuck.Core.Bridge{
}
public static string GenerateScript(Environment environment){
string Bool(bool value){
return value ? "true;" : "false;";
}
string Bool(bool value) => value ? "true;" : "false;";
string Str(string value) => '"'+value+"\";";
StringBuilder build = new StringBuilder().Append("(function(x){");
@@ -18,9 +17,10 @@ namespace TweetDuck.Core.Bridge{
if (environment == Environment.Browser){
build.Append("x.switchAccountSelectors=").Append(Bool(Program.UserConfig.SwitchAccountSelectors));
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));
}
if (environment == Environment.Notification){

View File

@@ -10,7 +10,7 @@ using TweetDuck.Core.Utils;
using TweetDuck.Resources;
namespace TweetDuck.Core.Bridge{
sealed class TweetDeckBridge{
class TweetDeckBridge{
public static string FontSize { get; private set; }
public static string NotificationHeadLayout { get; private set; }
@@ -45,11 +45,20 @@ namespace TweetDuck.Core.Bridge{
private readonly FormBrowser form;
private readonly FormNotificationMain notification;
public TweetDeckBridge(FormBrowser form, FormNotificationMain notification){
protected TweetDeckBridge(FormBrowser form, FormNotificationMain notification){
this.form = form;
this.notification = notification;
}
// Browser only
public sealed class Browser : TweetDeckBridge{
public Browser(FormBrowser form, FormNotificationMain notification) : base(form, notification){}
public void OpenContextMenu(){
form.InvokeAsyncSafe(form.OpenContextMenu);
}
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
form.InvokeAsyncSafe(() => {
form.OnIntroductionClosed(showGuide, allowDataCollection);
@@ -63,10 +72,6 @@ namespace TweetDuck.Core.Bridge{
});
}
public void SetLastRightClickInfo(string type, string link){
form.InvokeAsyncSafe(() => ContextMenuBase.SetContextInfo(type, link));
}
public void SetLastHighlightedTweet(string tweetUrl, string quoteUrl, string authors, string imageList){
form.InvokeAsyncSafe(() => {
LastHighlightedTweetUrl = tweetUrl;
@@ -76,8 +81,39 @@ namespace TweetDuck.Core.Bridge{
});
}
public void OpenContextMenu(){
form.InvokeAsyncSafe(form.OpenContextMenu);
public void DisplayTooltip(string text){
form.InvokeAsyncSafe(() => form.DisplayTooltip(text));
}
public void SetSessionData(string key, string value){
form.InvokeSafe(() => { // do not use InvokeAsyncSafe, return only after invocation
SessionData.Add(key, value);
});
}
}
// Notification only
public sealed class Notification : TweetDeckBridge{
public Notification(FormBrowser form, FormNotificationMain notification) : base(form, notification){}
public void DisplayTooltip(string text){
notification.InvokeAsyncSafe(() => notification.DisplayTooltip(text));
}
public void LoadNextNotification(){
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
}
public void ShowTweetDetail(){
notification.InvokeAsyncSafe(notification.ShowTweetDetail);
}
}
// Global
public void SetLastRightClickInfo(string type, string link){
form.InvokeAsyncSafe(() => ContextMenuBase.SetContextInfo(type, link));
}
public void OnTweetPopup(string columnId, string chirpId, string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){
@@ -90,29 +126,10 @@ namespace TweetDuck.Core.Bridge{
public void OnTweetSound(){
form.InvokeAsyncSafe(() => {
form.OnTweetNotification();
form.PlayNotificationSound();
form.OnTweetSound();
});
}
public void DisplayTooltip(string text, bool showInNotification){
if (showInNotification){
notification.InvokeAsyncSafe(() => notification.DisplayTooltip(text));
}
else{
form.InvokeAsyncSafe(() => form.DisplayTooltip(text));
}
}
public void SetSessionData(string key, string value){
form.InvokeSafe(() => { // do not use InvokeAsyncSafe, return only after invocation
SessionData.Add(key, value);
});
}
public void LoadNextNotification(){
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
}
public void ScreenshotTweet(string html, int width, int height){
form.InvokeAsyncSafe(() => form.OnTweetScreenshotReady(html, width, height));
}

View File

@@ -5,17 +5,15 @@ 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 +48,6 @@ namespace TweetDuck.Core{
private FormWindowState prevState;
private TweetScreenshotManager notificationScreenshotManager;
private SoundNotification soundNotification;
private VideoPlayer videoPlayer;
private AnalyticsManager analytics;
@@ -67,9 +64,7 @@ namespace TweetDuck.Core{
this.notification = new FormNotificationTweet(this, plugins);
this.notification.Show();
this.browser = new TweetDeckBrowser(this, plugins, new TweetDeckBridge(this, notification));
this.browser.PageLoaded += browser_PageLoaded;
this.browser = new TweetDeckBrowser(this, plugins, new TweetDeckBridge.Browser(this, notification));
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
@@ -82,7 +77,6 @@ namespace TweetDuck.Core{
contextMenu.Dispose();
notificationScreenshotManager?.Dispose();
soundNotification?.Dispose();
videoPlayer?.Dispose();
analytics?.Dispose();
};
@@ -99,6 +93,10 @@ namespace TweetDuck.Core{
this.updates.UpdateAccepted += updates_UpdateAccepted;
this.updates.UpdateDismissed += updates_UpdateDismissed;
if (Config.AllowDataCollection){
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
}
RestoreWindow();
}
@@ -118,10 +116,6 @@ namespace TweetDuck.Core{
Config.BrowserWindow.Restore(this, true);
prevState = WindowState;
isLoaded = true;
if (Config.AllowDataCollection){
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
}
}
private void UpdateTrayIcon(){
@@ -217,38 +211,6 @@ namespace TweetDuck.Core{
ForceClose();
}
private void browser_PageLoaded(object sender, EventArgs e){
if (Config.ShowDataCollectionNotification){
this.InvokeAsyncSafe(() => {
if (!Config.FirstRun && Config.AllowDataCollection){
FormMessage form = new FormMessage("Anonymous Data Update", "Hi! You can now review your anonymous data report, and opt-out if you've changed your mind. Collected data will be used to focus development on most commonly used features. If you want to opt-out but still support the project, any feedback and donations are appreciated.", MessageBoxIcon.Information);
form.AddButton("OK", ControlType.Accept | ControlType.Focused);
Button btnReviewSettings = new Button{
Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
Font = SystemFonts.MessageBoxFont,
Location = new Point(9, 12),
Margin = new Padding(0, 0, 48, 0),
Size = new Size(160, 26),
Text = "Review Feedback Options",
UseVisualStyleBackColor = true
};
btnReviewSettings.Click += (sender2, args2) => {
form.Close();
OpenSettings(typeof(TabSettingsFeedback));
};
form.AddActionControl(btnReviewSettings);
ShowChildForm(form);
}
Config.ShowDataCollectionNotification = false;
Config.Save();
});
}
}
private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
if (e.HasErrors){
FormMessage.Error("Error Loading Plugins", "The following plugins will not be available until the issues are resolved:\n\n"+string.Join("\n\n", e.Errors), FormMessage.OK);
@@ -291,41 +253,14 @@ 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){
if (m.Msg == Program.WindowRestoreMessage){
if (isLoaded && m.Msg == Program.WindowRestoreMessage){
if (WindowsUtils.CurrentProcessID == m.WParam.ToInt32()){
trayIcon_ClickRestore(trayIcon, EventArgs.Empty);
}
return;
}
else if (m.Msg == Program.SubProcessMessage){
int processId = m.WParam.ToInt32();
if (WindowsUtils.IsChildProcess(processId)){ // child process is checked in two places for safety
BrowserProcesses.Link(m.LParam.ToInt32(), processId);
}
return;
}
}
if (browser.Ready && m.Msg == NativeMethods.WM_PARENTNOTIFY && (m.WParam.ToInt32() & 0xFFFF) == NativeMethods.WM_XBUTTONDOWN){
if (videoPlayer != null && videoPlayer.Running){
@@ -368,6 +303,10 @@ namespace TweetDuck.Core{
browser.ReloadColumns();
}
public void PlaySoundNotification(){
browser.PlaySoundNotification();
}
public void ApplyROT13(){
browser.ApplyROT13();
}
@@ -381,14 +320,18 @@ namespace TweetDuck.Core{
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
if (Config.FirstRun){
Config.FirstRun = false;
Config.ShowFollowNotification = false;
Config.AllowDataCollection = allowDataCollection;
Config.ShowDataCollectionNotification = false;
Config.Save();
if (allowDataCollection && analytics == null){
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
}
}
else if (Config.ShowFollowNotification){
Config.ShowFollowNotification = false;
Config.Save();
}
if (showGuide){
FormGuide.Show();
@@ -421,8 +364,6 @@ namespace TweetDuck.Core{
trayIcon.HasNotifications = false;
}
browser.RefreshMemoryTracker();
if (Config.AllowDataCollection){
if (analytics == null){
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
@@ -433,6 +374,8 @@ namespace TweetDuck.Core{
analytics = null;
}
BrowserCache.RefreshTimer();
if (form.ShouldReloadBrowser){
FormManager.TryFind<FormPlugins>()?.Close();
plugins.Reload(); // also reloads the browser
@@ -470,19 +413,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,8 @@ using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils;
using System.Collections.Generic;
using System.Linq;
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Other;
namespace TweetDuck.Core.Handling{
@@ -80,7 +82,7 @@ namespace TweetDuck.Core.Handling{
model.AddItem(MenuSaveMedia, TextSave("video"));
model.AddSeparator();
}
else if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){
else if (((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage) && parameters.SourceUrl != TweetNotification.AppLogoLink){
model.AddItem(MenuViewImage, "View image in photo viewer");
model.AddItem(MenuOpenMediaUrl, TextOpen("image"));
model.AddItem(MenuCopyMediaUrl, TextCopy("image"));

View File

@@ -11,6 +11,7 @@ namespace TweetDuck.Core.Handling.General{
private static void UpdatePrefsInternal(){
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
ctx.SetPreference("browser.enable_spellchecking", Program.UserConfig.EnableSpellCheck, out string _);
ctx.SetPreference("spellcheck.dictionary", Program.UserConfig.SpellCheckLanguage, out string _);
ctx.SetPreference("settings.a11y.animation_policy", Program.UserConfig.EnableAnimatedImages ? "allowed" : "none", out string _);
}
}

View File

@@ -4,9 +4,7 @@ using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Handling.General{
sealed class LifeSpanHandler : ILifeSpanHandler{
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser){
newBrowser = null;
public static bool HandleLinkClick(IWebBrowser browserControl, WindowOpenDisposition targetDisposition, string targetUrl){
switch(targetDisposition){
case WindowOpenDisposition.NewBackgroundTab:
case WindowOpenDisposition.NewForegroundTab:
@@ -20,6 +18,11 @@ namespace TweetDuck.Core.Handling.General{
}
}
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser){
newBrowser = null;
return HandleLinkClick(browserControl, targetDisposition, targetUrl);
}
public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser){}
public bool DoClose(IWebBrowser browserControl, IBrowser browser){

View File

@@ -1,68 +0,0 @@
using System.Security.Cryptography.X509Certificates;
using CefSharp;
namespace TweetDuck.Core.Handling.General{
abstract class RequestHandlerBase : IRequestHandler{
// Browser
public virtual void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser){}
public virtual void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){}
public virtual bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect){
return false;
}
public virtual bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture){
return false;
}
public virtual bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url){
return false;
}
// Resources
public virtual CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){
return CefReturnValue.Continue;
}
public virtual void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl){}
public virtual bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
return false;
}
public virtual IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
return null;
}
public virtual void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength){}
// JavaScript & Plugins
public virtual bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback){
callback.Dispose();
return false;
}
public virtual void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath){}
// Auth
public virtual bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback){
callback.Dispose();
return false;
}
public virtual bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback){
callback.Dispose();
return false;
}
public virtual bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback){
callback.Dispose();
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
using CefSharp;
using CefSharp.Handler;
using TweetDuck.Core.Handling.General;
namespace TweetDuck.Core.Handling{
class RequestHandlerBase : DefaultRequestHandler{
public override bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture){
return LifeSpanHandler.HandleLinkClick(browserControl, targetDisposition, targetUrl);
}
}
}

View File

@@ -1,5 +1,4 @@
using CefSharp;
using TweetDuck.Core.Handling.General;
namespace TweetDuck.Core.Handling{
sealed class RequestHandlerBrowser : RequestHandlerBase{

View File

@@ -0,0 +1,72 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace TweetDuck.Core.Management{
static class BrowserCache{
public static string CacheFolder => Path.Combine(Program.StoragePath, "Cache");
private static bool ClearOnExit;
private static Timer AutoClearTimer;
private static long CalculateCacheSize(){
return new DirectoryInfo(CacheFolder).EnumerateFiles().Select(file => {
try{
return file.Length;
}catch{
return 0L;
}
}).Sum();
}
public static void GetCacheSize(Action<Task<long>> callbackBytes){
Task<long> task = new Task<long>(CalculateCacheSize);
task.ContinueWith(callbackBytes);
task.Start();
}
public static void RefreshTimer(){
bool shouldRun = Program.SystemConfig.ClearCacheAutomatically && !ClearOnExit;
if (!shouldRun && AutoClearTimer != null){
AutoClearTimer.Dispose();
AutoClearTimer = null;
}
else if (shouldRun && AutoClearTimer == null){
AutoClearTimer = new Timer(state => {
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));
}
}
public static void SetClearOnExit(){
ClearOnExit = true;
RefreshTimer();
}
public static void Exit(){
if (AutoClearTimer != null){
AutoClearTimer.Dispose();
AutoClearTimer = null;
}
if (ClearOnExit){
try{
Directory.Delete(CacheFolder, true);
}catch{
// welp, too bad
}
}
}
}
}

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{
@@ -56,10 +57,8 @@ namespace TweetDuck.Core.Other.Management{
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

@@ -1,4 +1,5 @@
using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Plugins;
using TweetDuck.Resources;
@@ -23,15 +24,21 @@ namespace TweetDuck.Core.Notification.Example{
private readonly TweetNotification exampleNotification;
public FormNotificationExample(FormBrowser owner, PluginManager pluginManager) : base(owner, pluginManager, false){
string exampleTweetHTML = ScriptLoader.LoadResource("pages/example.html", true);
string exampleTweetHTML = ScriptLoader.LoadResource("pages/example.html", true).Replace("{avatar}", TweetNotification.AppLogoLink);
#if DEBUG
exampleTweetHTML = exampleTweetHTML.Replace("</p>", @"</p><div style='margin-top:256px'>Scrollbar test padding...</div>");
#endif
exampleNotification = TweetNotification.Example(exampleTweetHTML, 95);
exampleNotification = TweetNotification.Example(exampleTweetHTML, 176);
}
public override void HideNotification(){
Location = ControlExtensions.InvisibleLocation;
}
public override void FinishCurrentNotification(){}
public void ShowExampleNotification(bool reset){
if (reset){
LoadTweet(exampleNotification);

View File

@@ -9,7 +9,6 @@ using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Other.Analytics;
using TweetDuck.Core.Other.Management;
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Notification{
@@ -126,7 +125,8 @@ namespace TweetDuck.Core.Notification{
this.browser = new ChromiumWebBrowser("about:blank"){
MenuHandler = new ContextMenuNotification(this, enableContextMenu),
JsDialogHandler = new JavaScriptDialogHandler(),
LifeSpanHandler = new LifeSpanHandler()
LifeSpanHandler = new LifeSpanHandler(),
RequestHandler = new RequestHandlerBase()
};
this.browser.Dock = DockStyle.None;
@@ -139,8 +139,8 @@ namespace TweetDuck.Core.Notification{
DpiScale = this.GetDPIScale();
DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
handlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
browser.SetupResourceHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
browser.SetupResourceHandler(TweetNotification.AppLogoLink, TweetNotification.AppLogoHandler);
Controls.Add(browser);
@@ -174,9 +174,6 @@ namespace TweetDuck.Core.Notification{
private void browser_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e){
if (e.IsBrowserInitialized){
Initialized?.Invoke(this, EventArgs.Empty);
int identifier = browser.GetBrowser().Identifier;
Disposed += (sender2, args2) => BrowserProcesses.Forget(identifier);
}
}
@@ -184,6 +181,8 @@ namespace TweetDuck.Core.Notification{
public virtual void HideNotification(){
browser.Load("about:blank");
DisplayTooltip(null);
Location = ControlExtensions.InvisibleLocation;
currentNotification = null;
}
@@ -209,7 +208,9 @@ namespace TweetDuck.Core.Notification{
protected virtual void LoadTweet(TweetNotification tweet){
currentNotification = tweet;
resourceHandler.SetHTML(GetTweetHTML(tweet));
browser.Load(TwitterUtils.TweetDeckURL);
DisplayTooltip(null);
}
protected virtual void SetNotificationSize(int width, int height){

View File

@@ -83,7 +83,7 @@ namespace TweetDuck.Core.Notification{
browser.KeyboardHandler = new KeyboardHandlerNotification(this);
browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge(owner, this));
browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge.Notification(owner, this));
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
browser.LoadingStateChanged += Browser_LoadingStateChanged;

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
private readonly AudioPlayer player;
public static IResourceHandler CreateFileHandler(string path){
string mimeType;
public SoundNotification(){
this.player = AudioPlayer.New();
this.player.PlaybackError += Player_PlaybackError;
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 void Play(string file){
player.Play(file);
try{
return ResourceHandler.FromFilePath(path, mimeType);
}catch{
TryShowError("Could not find custom notification sound file:\n"+path);
return null;
}
}
public bool SetVolume(int volume){
return player.SetVolume(volume);
}
private static void TryShowError(string message){
FormBrowser browser = FormManager.TryFind<FormBrowser>();
private void Player_PlaybackError(object sender, PlaybackErrorEventArgs e){
PlaybackError?.Invoke(this, e);
}
browser?.InvokeAsyncSafe(() => {
using(FormMessage form = new FormMessage("Sound Notification Error", message, MessageBoxIcon.Error)){
form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
public void Dispose(){
player.Dispose();
Button btnViewOptions = form.AddButton("View Options");
btnViewOptions.Width += 16;
btnViewOptions.Location = new Point(btnViewOptions.Location.X-16, btnViewOptions.Location.Y);
if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnViewOptions){
browser.OpenSettings(typeof(TabSettingsSounds));
}
}
});
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Text;
using CefSharp;
using TweetDuck.Core.Bridge;
using TweetDuck.Resources;
@@ -8,6 +9,9 @@ namespace TweetDuck.Core.Notification{
private const string DefaultHeadLayout = @"<html id='tduck' class='os-windows txt-size--14' data-td-font='medium' data-td-theme='dark'><head><meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='chrome=1'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/font.5ef884f9f9.css'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/app-dark.5631e0dd42.css'><style type='text/css'>body{background:#222426}</style>";
private static readonly string CustomCSS = ScriptLoader.LoadResource("styles/notification.css");
public const string AppLogoLink = "https://ton.twimg.com/tduck/avatar";
public static readonly IResourceHandler AppLogoHandler = ResourceHandler.FromByteArray(Properties.Resources.avatar, "image/png");
public static TweetNotification Example(string html, int characters){
return new TweetNotification(string.Empty, string.Empty, "Home", html, characters, string.Empty, string.Empty, true);
}

View File

@@ -3,7 +3,9 @@ using TweetDuck.Data.Serialization;
namespace TweetDuck.Core.Other.Analytics{
sealed class AnalyticsFile{
private static readonly FileSerializer<AnalyticsFile> Serializer = new FileSerializer<AnalyticsFile>();
private static readonly FileSerializer<AnalyticsFile> Serializer = new FileSerializer<AnalyticsFile>{
HandleUnknownProperties = FileSerializer<AnalyticsFile>.IgnoreProperties("CountGCReloads")
};
static AnalyticsFile(){
Serializer.RegisterTypeConverter(typeof(DateTime), new SingleTypeConverter<DateTime>{
@@ -17,7 +19,7 @@ namespace TweetDuck.Core.Other.Analytics{
DesktopNotification, SoundNotification, MuteNotification,
BrowserContextMenu, BrowserExtraMouseButton,
NotificationContextMenu, NotificationExtraMouseButton, NotificationKeyboardShortcut,
TweetScreenshot, TweetDetail, VideoPlay, GCReload
TweetScreenshot, TweetDetail, VideoPlay
}
// STATE PROPERTIES
@@ -46,7 +48,6 @@ namespace TweetDuck.Core.Other.Analytics{
public int CountTweetScreenshots { get; private set; } = 0;
public int CountTweetDetails { get; private set; } = 0;
public int CountVideoPlays { get; private set; } = 0;
public int CountGCReloads { get; private set; } = 0;
// END OF DATA
@@ -76,7 +77,6 @@ namespace TweetDuck.Core.Other.Analytics{
case Event.TweetScreenshot: ++CountTweetScreenshots; break;
case Event.TweetDetail: ++CountTweetDetails; break;
case Event.VideoPlay: ++CountVideoPlays; break;
case Event.GCReload: ++CountGCReloads; break;
}
}

View File

@@ -94,6 +94,11 @@ namespace TweetDuck.Core.Other.Analytics{
Task.Factory.StartNew(() => {
AnalyticsReport report = AnalyticsReportGenerator.Create(File, info, plugins);
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
BrowserUtils.CreateWebClient().UploadValues(CollectionUrl, "POST", report.ToNameValueCollection());
}).ContinueWith(task => browser.InvokeAsyncSafe(() => {
if (task.Status == TaskStatus.RanToCompletion){

View File

@@ -37,12 +37,11 @@ namespace TweetDuck.Core.Other.Analytics{
{ "Screen DPI" , info.DPI != null ? Exact(info.DPI.Value) : "(unknown)" },
0,
{ "Hardware Acceleration" , Bool(SysConfig.HardwareAcceleration) },
{ "Browser GC Reload" , Bool(SysConfig.EnableBrowserGCReload) },
{ "Browser GC Threshold" , Exact(SysConfig.BrowserMemoryThreshold) },
0,
{ "Expand Links" , Bool(UserConfig.ExpandLinksOnHover) },
{ "Switch Account Selectors" , Bool(UserConfig.SwitchAccountSelectors) },
{ "Search In First Column" , Bool(UserConfig.OpenSearchInFirstColumn) },
{ "Keep Like Follow Dialogs Open" , Bool(UserConfig.KeepLikeFollowDialogsOpen) },
{ "Best Image Quality" , Bool(UserConfig.BestImageQuality) },
{ "Spell Check" , Bool(UserConfig.EnableSpellCheck) },
{ "Zoom" , Exact(UserConfig.ZoomLevel) },
@@ -102,8 +101,7 @@ namespace TweetDuck.Core.Other.Analytics{
{ "Notification Keyboard Shortcuts" , LogRound(file.CountNotificationKeyboardShortcuts, 2) },
{ "Tweet Screenshots" , LogRound(file.CountTweetScreenshots, 2) },
{ "Tweet Details" , LogRound(file.CountTweetDetails, 2) },
{ "Video Plays" , LogRound(file.CountVideoPlays, 4) },
{ "GC Reloads" , LogRound(file.CountGCReloads, 4) }
{ "Video Plays" , LogRound(file.CountVideoPlays, 4) }
}.FinalizeReport();
}
@@ -283,7 +281,7 @@ namespace TweetDuck.Core.Other.Analytics{
return new ExternalInfo();
}
else{
Screen screen = Screen.FromControl(form);
Screen screen = Screen.FromControl(form); // works on multi-monitor setups even in tray
int dpi;
using(Graphics graphics = form.CreateGraphics()){

View File

@@ -38,7 +38,6 @@ namespace TweetDuck.Core.Other {
//
this.pictureLogo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.pictureLogo.ErrorImage = null;
this.pictureLogo.Image = ((System.Drawing.Image)(resources.GetObject("pictureLogo.Image")));
this.pictureLogo.InitialImage = null;
this.pictureLogo.Location = new System.Drawing.Point(12, 12);
this.pictureLogo.Name = "pictureLogo";

View File

@@ -1,4 +1,6 @@
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using TweetDuck.Core.Utils;
@@ -17,6 +19,10 @@ namespace TweetDuck.Core.Other{
labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website));
labelTips.Links.Add(new LinkLabel.Link(0, labelTips.Text.Length, TipsLink));
labelIssues.Links.Add(new LinkLabel.Link(0, labelIssues.Text.Length, IssuesLink));
MemoryStream logoStream = new MemoryStream(Properties.Resources.avatar);
pictureLogo.Image = Image.FromStream(logoStream);
Disposed += (sender, args) => logoStream.Dispose();
}
private void OnLinkClicked(object sender, LinkLabelLinkClickedEventArgs e){

View File

@@ -1,246 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="pictureLogo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
bGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZE
sRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTs
AIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4
JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR
3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQd
li7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtF
ehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGX
wzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNF
hImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH55
4SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJ
VgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB
5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyC
qbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiE
j6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I
1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9
rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhG
fDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFp
B+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJ
yeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJC
YVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQln
yfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48v
vacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0Cvp
vfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15L
Wytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AA
bWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0z
llmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHW
ztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5s
xybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6
eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPw
YyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmR
XVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNm
WS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wl
xqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2
dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8
V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33za
Eb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2v
Tqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqb
PhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/
0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h
/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavr
XTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxS
fNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+
tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/
6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAAuIgAALiIBquLdkgAAEVpJREFUeF7tXQl0VNd5
Thq3Tk7tc+qmiZMm7YmdJj1OT3Gd0kTMG3mJnZQEJzaSjXETx0lqNwt2jWscQGixBAJLSMhgA8YYbIyQ
hHYJI4lFGMwioQWxyewgMdoXtKFd4u/337lPjDRv9pk3g+A75zsMWv577/fd+9/l3Rl9johu0Y/U/OIt
6sfrLwIYT2de+SJ4F/j34LfB+8Ap4L9J8uvvgfy9b4DfBO8EPy9DBBwC3gCI93fgDHAuuA7cDVaDzWAX
OAAOgcNgP9gN8vc+A4vB9eBr4M/Be8GAMiPgDIBAXwVDwbXgEbAPJC+RDToGvgfOBr8mi/UbAsIACMFp
ZRaYC7aBWuL5gh3gdvBZ8C5ZHV3hVwPQaM7hS0ETqCWQnqwDE8Apsnq6wC8GoJEPgFtAzt9aYviTPJ9k
gkGyuj6FrgagUd8CeVIcBLUaH0gcATeD35XV9wl0MQCN4OXjn8EroFZjA5m8qooE/1o2x6vwuQGouAEs
A7UadyPxOPgj2SyvwacGoMILwRsh3ThLTksx4BdkEz2GTwxABb8C8pJSqxGTgTvAb8jmegSvG4CK/QvI
O1Wtik8mXgSnyma7Da8agAo9Auq5kfI3+Shkhmy+W/CaAajI42CvrNjNRJ7jZksZXIZXDEAFWPxA3FTp
xVHQLRM8NgAFPwTejD1/InkH/biUxWl4ZAAK5LP3mynnO+JV0KWJ2W0DUNCXwVOy4Fu8zhrQ6SWqJwbk
WxQa2Mxop6fSWyk0rYlCUhspZEs9zdxSJ8iv+WuhW5vpqYw27d93nXvB26RUduGWAQg+36KwwCULv7VF
iDx3Wx1tPNxCBy92UU17P7VdHaLWniE619JLu8900Nv7m+jFLBgCM9gs/l3NmCqlqU+nt+D/msYtk3LZ
hcsGIPB/gPaPF7jyKrW+rwNZnJCUBoraUU9H63po9No1NM8++odGac/ZDno5r45C2QitESGF59gv5dVT
clUHzc5gEyb8XOaVa6DDsyMU67wBCHg7WCULsEkezi9/jEptbfKLCdzrn0s30b5znWiS6xgeuUaby1so
NKVubDSwGZzCOG3NzTdRQXW7+NnM4+b2atUDPAPeIeXTBEK4ZMA8i+Ca5Ir+LrOOOvtHKGkfcit6kp4m
sBh/zDGRqaMfzfEMh5CuZiXXUOgWE72Ua6L1Jc10qqmXRkbNo4nT2PMw2sHcESvl0wTCOGcAAv0DyFtv
rULGyAKsO9SMUERD6EnRO+t1M4F76++zTNTUNSjK9wYutvVhzujTTGGrMG/wqNCqiwX5IsA/SxmtgDBO
G7DBIqhN8oR3suEqQpnRh7watcOcU31pAvfCWUgZ1Y3Xy/YlCk+Z28rlqrTTvkwpoxUQyrEBCPCvoONz
fVTg1xkm6hkYQajr4Mktdpd5uecrE9jg5IpWWaJvwRN1SHKtaA/PCfMLmyiq2DxPaNUN5KMKg5RzHBDO
KQNSLYLZJFfgVSz3tMBDeM0BrMNlr9H6fXfJ8V7AErK7f1iW5hsMjYxSSnkjPbnxLP1vbq2YE04399KV
vmGak9/kqF0FUs5xQFj7BuAXvwM6ddDGOfiNnQ0IYxvbTrYjVWDiwkrFW6OB83DaEd/3/obOfiq71Ekt
3YOkzgg8NUTxPOdgLpiV1TE6K7vzASnrGBDCoQF8b0cz6ESyqDG77BvAOI2VxJycy7bX2q4QJoYgDVxo
7ZPR9QVv4OzNb7OyOll8mpnWTNPXnlwnZR0DQtg2AAHuAPnCkmbwieQREFZQjzCOwfPChlJs/3mt7cFo
YAPn5NTRsFwa6on3kII05zUIjt4uXv9icx099u5pCn7rKBkSynoMC1K/LuUVQBi7BswcF9gBWYzfZ5vE
RsZZnG/powjsVsXc4IYR/DtLix2POm+C9wGrPjWfK1nWl3v6MxA+FB1xxgeX6OF3TpKSdASsIiMMMK48
TkpM4RwprwDC2TUgTw3uFFEZXgo2dA4glPNgu8pruyms0HxAJnaWThrBP7v2oHnfoQd48xWBelqmHe7t
Is2kNNJ/rj9HD648RsoKC+FVwgBj/MGDUl4BhNQ2AIH/FuTLq1aNtkfuFYWfXUEo18FGHKvrofg9DfRs
mknEcjQq2ABejeiFyEKTWXyUbU4z7fSLj0z06NpTELnKLLyl6BOZVDVgDM+8R8ps14AQy4Y6S1fmAXvg
npZ/oo0iiuro2VSYkdIgVhocX0zc0hQ2YDWWt3phIdrGp5+hW1vpZxsv0SOcZrR6uy1iFAQvLvqDlNmu
Ae9aCus0IQzn8/LL3QjnHbAZpZe6RE9fsL2O/jvTJFIdlzMz2URRhZflT/oer+fX0E/ePUXBttKMI3Ia
enNfhpRZ2wAI+XnQ4amnLXLamPdxHQ1i4+IL8AqqHvMMp6vdZ65Q8en2sXW5r/HbjZVYzVRoi+sMYZwx
saxWWbj1Swhn04B/BPkQSVNgu+TUAHKefB/LzMkE3s3PXgfxsbLRFNd5XlMWZT6AkDYN+JmVsE5QLEPz
WujXGY0iZ3N60GOHqheuDgzT4++U80SqJarz5DQUXfAcQlobACE5/fAb4jRFtkdOPatLWqmrf4RSKlvo
1fzL9MSGM7TuQJ04R7nR0dDRSw8mlGqL6gpXniDjkp2xyoKULyCslQH81MutCZgNWLz7+qaI83Jz9yAm
0A5q6/HeGb2/cPxyBxnivWEAT8T7c4Mjc+5EWCsD/gbkt4JqimyP6rGA+sRosqHgWD0Zlh/WFtUVsgHL
S44aI3O/hrBWBvCboN273cwTMJaHvEKZjEgsOkNKogcrIJViJVTeaIzefi/CWhnA7zJvGiesC+TVT85x
8wPryYYXNpl3upqiukQYsKKyR1my63sIa2UAv3WU3xelKbAj8k71lXz/nE76Em09A/Tjt5B+PF0BqUw6
MogN2RSEtjKAHz+6twdg8k6Yz4NOuXceFKgorm7yTv5XmXRkVIk78H2EtjLgfpBv+moL7AR5Mv5NRp1X
byf4GzH5n3kn/6vkkbS8dCpCWxnAnzrikQFMPiRbWFAnbkXc6OAN2BNreAPmjfwvyQbEH9I0gD/yxfM3
W/BxRFqTuBrYOzj+lsSNht0nG72bfphJVddgwL8jvJUBHk3C4yhNeCXfRJfaPL+p5i+8ln4Cq59KbSHd
ZVLloLJs7/0Ib2UAL0NbxgnpCWEC75Bnp5rog7IW6ujz7dURb+NsYxdvmswpQ0tItyiWod1KTJHmMpQ3
YvxhR9qCukiekGenN4tHjU9+VENPbzpLcbtq6GS9954X+BLLtp/y7uTLNG/EmozRBd9GEVYG8Gf37LEU
0RNy7/+o8gqdae6jQxc76eCFTqqo7aTGzsBPSRdbeuihRG/3fpANiC85qkTkaB5F8Adr8CeaaArqKsUj
yiJ9by14C2/keXnpqXIV5pTYPblB8zZ9BcVYGcDH0f9nKaJH5I1ZSgMduNCF8DcOjtS0k+L13C/JBize
EWeYn3wbihpvgHwgw+/71RbUDfIo+FNuvdWl3UAFn+a+KM59vLzyUWl+IPMbFHVd97EXZgPuAb3yKSfq
ZSUeBbFFNSgi8PHRwRrzut8Xvd/Ma8FR+XYfSf4FyJ+PoymqM1TvRIakNtP098/TQ5h4psWXUnzBaRQT
uDhZ1yknXi/uei0JHZTlpbVBr6z7IoqzNkAlRHR9Ira4E/lEcv31O5Hq9Q2Qe9bCrJPU3T+EYgILPajT
r96v8F3qYSL/G5bszuKOjiLHeP2FBETkj5G0FlmDapp5amsrzfiwhh5ZPeFOpCXxNSWxnGauKaed2OI7
8eZF3RCejXqjbj5MPWYDInJfZo1RpF0D+EOX7L4nbOzqdWqTSDN8J3Kst2sVbkF+sMGj4fmNlZR2uFas
uYflg3t/mLJy11lf530Q6/+3qoaw+vkOa4xibRvAgMj8oaYTRLe+eu3UnUgt8mhgIxLKKBhLvsdXltDc
zRV0qUXfXfKHBy7pID4ongUfKpfyOmXAf00U3ubVa0+IOCzAM+vKqOxCG6qhHzbziodvOvhq0rUk0k9Q
WPpLUl4BVMG2AbOyu+4CW1j8Jx1dvXaHLDx6/09XHabU0loaHNb32cG7n1zQT3w+fkgs75r6Pwl3S3kF
UA3bBjB+vvH8CnH1WqYLzeCukEcNVhnc459YXSaGf0evvk/O2OjovGqZdnQQn/l2NQVF5G2Qso4B1bFv
gCEs/X6kmhHNoCp5NHBDBPm1ShYbTKwQPZ1723T09tfTT4hnrL2D+h9N17Zdpd9uNI88UUet9viCGAFB
r29WpKxjQJXsG8AwLtv3sbhOpxUYjZi+5hg9s+E4zVpfRT9ZeZh+nFRKP11ZRqFry+mFD6soKreakg/V
iPzuz/V/TqVJ1E2s83UVX9yE2294baPV3y5AtRwboIRnT0OgUavAko++fZR++cFxKj7VQgPDI9Q3OCKE
HhgKjLOfc03d9ErqcX1TjiVhADLJdCnnOKB6jg1gGOP2pwsntQpAbxLzw/JSCsuqprNocCCgoaOPEgrP
0MOJJeZjZT17vUo++Vz6yU4poxVQTScNWJT5XfSefvNmQqMgJhuBhirxJTQ/4wRVXGqnUT9c0Drf3E3L
IfyPON2Ina0fer0gVoxJVcNBr31g9QZtFaiucwYwjEt2xdqcCywpRgRWOph0f7m+QuT/y+1XfbrD5Ztr
24/V05wtR8Wmzr/CS7JWscWrpHyaQNWdN0AJS7vDmFh2zmYqmkiZmnjF8WBCibhbuWbPeTqMyZiXnp4Y
wgdnfF2cl7Gc3x9Db+ccr/sEa4u87l9R3hAcnvllKZ8m0BTnDWAo4VmPGldyIXZSkRalGdwzeWTwaonP
gRZlV9O6vRcoq8JEu7E0LTnXSidMHSKNHK29Qofwf76Xw99/Dz8XiRXV7z48QjPeLkOqg+gwN2BEtyRv
WCNyQqRsNuGyAQxlya44p1KRPaqGQDxhCnrvGFlYlRZf558TcwxP+IEmuCXFI8eda6RcduGWAcaFaX9p
jD/0qdOp6GYia7K8pCp4UfqXpFx24ZYBDGVB6jeNKypMt0ywoPm8p9UYkW3zI8omwm0DGIbXN//AuKKy
VxSsVaGbiWYNhrBpdenPnHhkAAMTzUwUPnxTm6C2PWrbc1IWp+GxAQxDePavxlXkpiLazO2OKfqjlMMl
eMUABruPCt1kI4HbiuVm9PY/SRlchtcMYBjCMkJQMcwJN8HEzB0tqWrIGF3wvGy+W/CqAQwlLH2aknDY
xGthzYpPBnIHW1HRYozMeUw222143QDGtD8n3yP2CcKESZaSeAOaUFpuDM+8TzbXI/jEAIZxYepfGaIL
48yVngQpiVMO2qHEFq81Lkr32p819JkBKgyLMmeYD/Bu4NHAdU8sr1Ui85+SzfIafG4Aw7go4y5jbPEy
8TzhRpobxMitGjYu3fOOMWzrV2VzvApdDFDxw3mbpyhL92aL09RATkuibhitb35agIn2h7L6PoGuBqgw
hOc8Zow7UCQayyMiIPYOnONlmow7sEeJzPPoL+Q5C78YoAI76KBpMTtXK4nlLcZV6HVqz9MUyEfkMpkr
KnuMSz/ZpETkPCyrpwv8aoCKH8zdcPe0yG0vYum6X8wTLIivRoZczQgmVQ2izBIluvBVZeHWb8nq6IqA
MMASWDX9k+GN7X8wxO5JU5aXnjeLxoKxIVI4YYzKCQKrX7cUWpiJf/n7CWW1yrJ9WcaYwpeU8Cynj419
hYAzwBJB8zbdHhyVd78xpuA5ZfHOWEzgWeixFVgSNiBldGG0DICj4uE7PyEzvx4Q6YQ/ECm+5Cgm0jxl
8Y5lyhsfPw9zpyrzU3zyp8ndRUAbwFDrZViQdlvQ/NQ7kKPvNkYX3GuIKbpPWfrJFP7IFyXu4FQYM1V5
c//3lWV7p/A70JWobfcq4dlfN4Zn3WmYn3y7GseSgYCxulhW7Bb1p+YXb1Ev0uf+H9A3E1Z4VJUaAAAA
AElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -9,6 +9,7 @@ using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Other.Analytics;
using TweetDuck.Core.Utils;
using System.Text.RegularExpressions;
using TweetDuck.Resources;
namespace TweetDuck.Core.Other{
sealed partial class FormGuide : Form{
@@ -73,6 +74,7 @@ namespace TweetDuck.Core.Other{
browser.LoadingStateChanged += browser_LoadingStateChanged;
browser.FrameLoadStart += browser_FrameLoadStart;
browser.FrameLoadEnd += browser_FrameLoadEnd;
browser.BrowserSettings.BackgroundColor = (uint)BackColor.ToArgb();
browser.Dock = DockStyle.None;
@@ -110,6 +112,11 @@ namespace TweetDuck.Core.Other{
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
}
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
// idiot chromium
ScriptLoader.ExecuteScript(e.Frame, "Array.prototype.forEach.call(document.getElementsByTagName('A'), ele => ele.addEventListener('click', e => { e.preventDefault(); window.open(ele.getAttribute('href')); }))", "gen:links");
}
private void Config_ZoomLevelChanged(object sender, EventArgs e){
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
}

View File

@@ -133,7 +133,7 @@ namespace TweetDuck.Core.Other{
Font = SystemFonts.MessageBoxFont,
Location = new Point(0, 12),
Size = new Size(BrowserUtils.Scale(88, dpiScale), BrowserUtils.Scale(26, dpiScale)),
TabIndex = buttonCount,
TabIndex = 256-buttonCount,
Text = title,
UseVisualStyleBackColor = true
};

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

@@ -37,9 +37,10 @@ namespace TweetDuck.Core.Other{
this.buttonHeight = BrowserUtils.Scale(39, this.GetDPIScale()) | 1;
AddButton("General", () => new TabSettingsGeneral(this.browser, updates));
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,27 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
using CefSharp;
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Other.Management{
static class BrowserProcesses{
private static readonly Dictionary<int, int> PIDs = new Dictionary<int, int>();
public static void Link(int identifier, int pid){
PIDs[identifier] = pid;
}
public static void Forget(int identifier){
PIDs.Remove(identifier);
}
public static Process FindProcess(IBrowser browser){
if (PIDs.TryGetValue(browser.Identifier, out int pid) && WindowsUtils.IsChildProcess(pid)){ // child process is checked in two places for safety
return Process.GetProcessById(pid);
}
else{
return null;
}
}
}
}

View File

@@ -1,93 +0,0 @@
using System;
using System.Diagnostics;
using System.Timers;
using CefSharp;
using CefSharp.WinForms;
using TweetDuck.Core.Controls;
using Timer = System.Timers.Timer;
namespace TweetDuck.Core.Other.Management{
sealed class MemoryUsageTracker : IDisposable{
private const int IntervalMemoryCheck = 60000*30; // 30 minutes
private const int IntervalCleanupAttempt = 60000*5; // 5 minutes
private readonly string script;
private readonly Timer timer;
private FormBrowser owner;
private IBrowser browser;
private long threshold;
private bool needsCleanup;
public MemoryUsageTracker(string cleanupFunctionName){
this.script = $"window.{cleanupFunctionName} && window.{cleanupFunctionName}()";
this.timer = new Timer{ Interval = IntervalMemoryCheck };
this.timer.Elapsed += timer_Elapsed;
}
public void Start(ChromiumWebBrowser control, int thresholdMB){
Stop();
this.owner = (FormBrowser)control.Parent; // TODO ugly
this.browser = control.GetBrowser();
this.threshold = thresholdMB*1024L*1024L;
this.timer.SynchronizingObject = owner;
this.timer.Start();
}
public void Stop(){
timer.Stop();
timer.SynchronizingObject = null;
owner = null;
browser = null;
SetNeedsCleanup(false);
}
public void Dispose(){
timer.SynchronizingObject = null;
timer.Dispose();
owner = null;
browser = null;
}
private void SetNeedsCleanup(bool value){
if (needsCleanup != value){
needsCleanup = value;
timer.Interval = value ? IntervalCleanupAttempt : IntervalMemoryCheck; // restarts timer
}
}
private void timer_Elapsed(object sender, ElapsedEventArgs e){
if (owner == null || browser == null){
return;
}
if (needsCleanup){
if (!owner.ContainsFocus){
using(IFrame frame = browser.MainFrame){
frame.EvaluateScriptAsync(script).ContinueWith(task => {
JavascriptResponse response = task.Result;
if (response.Success && (response.Result as bool? ?? false)){
SetNeedsCleanup(false);
owner.InvokeAsyncSafe(() => owner.TriggerAnalyticsEvent(Analytics.AnalyticsFile.Event.GCReload));
}
});
}
}
}
else{
try{
using(Process process = BrowserProcesses.FindProcess(browser)){
if (process?.PrivateMemorySize64 > threshold){
SetNeedsCleanup(true);
}
}
}catch{
// ignore I guess?
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using TweetDuck.Configuration;
@@ -9,12 +8,21 @@ namespace TweetDuck.Core.Other.Settings{
public IEnumerable<Control> InteractiveControls{
get{
foreach(Panel panel in Controls.OfType<Panel>()){
foreach(Control control in panel.Controls){
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);
}
}
protected BaseTabSettings(){

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

@@ -29,10 +29,8 @@
this.cbLogging = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.cbDebugUpdates = new System.Windows.Forms.CheckBox();
this.comboLocale = new System.Windows.Forms.ComboBox();
this.tbDataFolder = new System.Windows.Forms.TextBox();
this.tbShortcutTarget = new System.Windows.Forms.TextBox();
this.labelLocale = new System.Windows.Forms.Label();
this.labelDataFolder = new System.Windows.Forms.Label();
this.labelShortcutTarget = new System.Windows.Forms.Label();
this.SuspendLayout();
@@ -40,7 +38,7 @@
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.Location = new System.Drawing.Point(216, 217);
this.btnCancel.Location = new System.Drawing.Point(215, 163);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnCancel.Size = new System.Drawing.Size(56, 23);
@@ -52,7 +50,7 @@
// btnRestart
//
this.btnRestart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnRestart.Location = new System.Drawing.Point(153, 217);
this.btnRestart.Location = new System.Drawing.Point(152, 163);
this.btnRestart.Name = "btnRestart";
this.btnRestart.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnRestart.Size = new System.Drawing.Size(57, 23);
@@ -83,54 +81,33 @@
this.toolTip.SetToolTip(this.cbDebugUpdates, "Allows updating to pre-releases.");
this.cbDebugUpdates.UseVisualStyleBackColor = true;
//
// comboLocale
//
this.comboLocale.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.comboLocale.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboLocale.FormattingEnabled = true;
this.comboLocale.Location = new System.Drawing.Point(15, 83);
this.comboLocale.Name = "comboLocale";
this.comboLocale.Size = new System.Drawing.Size(257, 21);
this.comboLocale.TabIndex = 3;
this.toolTip.SetToolTip(this.comboLocale, "Language used for spell checking.");
//
// tbDataFolder
//
this.tbDataFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tbDataFolder.Location = new System.Drawing.Point(15, 135);
this.tbDataFolder.Location = new System.Drawing.Point(15, 83);
this.tbDataFolder.Name = "tbDataFolder";
this.tbDataFolder.Size = new System.Drawing.Size(257, 20);
this.tbDataFolder.TabIndex = 5;
this.toolTip.SetToolTip(this.tbDataFolder, "Path to the data folder. Must be either an absolute path,\r\nor a simple folder name that will be created in LocalAppData.");
this.toolTip.SetToolTip(this.tbDataFolder, "Path to the data folder. Must be either an absolute path,\r\nor a simple folder nam" +
"e that will be created in LocalAppData.");
//
// tbShortcutTarget
//
this.tbShortcutTarget.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tbShortcutTarget.Cursor = System.Windows.Forms.Cursors.Hand;
this.tbShortcutTarget.Location = new System.Drawing.Point(15, 186);
this.tbShortcutTarget.Location = new System.Drawing.Point(15, 134);
this.tbShortcutTarget.Name = "tbShortcutTarget";
this.tbShortcutTarget.ReadOnly = true;
this.tbShortcutTarget.Size = new System.Drawing.Size(257, 20);
this.tbShortcutTarget.TabIndex = 7;
this.tbShortcutTarget.Click += new System.EventHandler(this.tbShortcutTarget_Click);
//
// labelLocale
//
this.labelLocale.AutoSize = true;
this.labelLocale.Location = new System.Drawing.Point(12, 67);
this.labelLocale.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelLocale.Name = "labelLocale";
this.labelLocale.Size = new System.Drawing.Size(39, 13);
this.labelLocale.TabIndex = 2;
this.labelLocale.Text = "Locale";
//
// labelDataFolder
//
this.labelDataFolder.AutoSize = true;
this.labelDataFolder.Location = new System.Drawing.Point(12, 119);
this.labelDataFolder.Location = new System.Drawing.Point(12, 67);
this.labelDataFolder.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelDataFolder.Name = "labelDataFolder";
this.labelDataFolder.Size = new System.Drawing.Size(62, 13);
@@ -140,7 +117,7 @@
// labelShortcutTarget
//
this.labelShortcutTarget.AutoSize = true;
this.labelShortcutTarget.Location = new System.Drawing.Point(12, 170);
this.labelShortcutTarget.Location = new System.Drawing.Point(12, 118);
this.labelShortcutTarget.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelShortcutTarget.Name = "labelShortcutTarget";
this.labelShortcutTarget.Size = new System.Drawing.Size(155, 13);
@@ -151,13 +128,11 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 252);
this.ClientSize = new System.Drawing.Size(284, 198);
this.Controls.Add(this.tbShortcutTarget);
this.Controls.Add(this.labelShortcutTarget);
this.Controls.Add(this.tbDataFolder);
this.Controls.Add(this.labelDataFolder);
this.Controls.Add(this.comboLocale);
this.Controls.Add(this.labelLocale);
this.Controls.Add(this.cbDebugUpdates);
this.Controls.Add(this.cbLogging);
this.Controls.Add(this.btnRestart);
@@ -180,8 +155,6 @@
private System.Windows.Forms.CheckBox cbLogging;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.CheckBox cbDebugUpdates;
private System.Windows.Forms.Label labelLocale;
private System.Windows.Forms.ComboBox comboLocale;
private System.Windows.Forms.Label labelDataFolder;
private System.Windows.Forms.TextBox tbDataFolder;
private System.Windows.Forms.TextBox tbShortcutTarget;

View File

@@ -1,33 +1,20 @@
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using TweetDuck.Configuration;
using TweetDuck.Data;
namespace TweetDuck.Core.Other.Settings.Dialogs{
sealed partial class DialogSettingsRestart : Form{
private const string DefaultLocale = "en-US";
public CommandLineArgs Args { get; private set; }
public DialogSettingsRestart(CommandLineArgs currentArgs){
InitializeComponent();
try{
object[] locales = Directory.EnumerateFiles(Path.Combine(Program.ProgramPath, "locales"), "*.pak", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToArray<object>();
comboLocale.Items.AddRange(locales);
}catch{
comboLocale.Items.Add(DefaultLocale);
}
cbLogging.Checked = currentArgs.HasFlag(Arguments.ArgLogging);
cbDebugUpdates.Checked = currentArgs.HasFlag(Arguments.ArgDebugUpdates);
comboLocale.SelectedItem = currentArgs.GetValue(Arguments.ArgLocale, DefaultLocale);
cbLogging.CheckedChanged += control_Change;
cbDebugUpdates.CheckedChanged += control_Change;
comboLocale.SelectedValueChanged += control_Change;
if (Program.IsPortable){
tbDataFolder.Text = "Not available in portable version";
@@ -54,12 +41,6 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Args.AddFlag(Arguments.ArgDebugUpdates);
}
string locale = comboLocale.SelectedItem as string;
if (!string.IsNullOrWhiteSpace(locale) && locale != DefaultLocale){
Args.SetValue(Arguments.ArgLocale, locale);
}
if (!string.IsNullOrWhiteSpace(tbDataFolder.Text) && tbDataFolder.Enabled){
Args.SetValue(Arguments.ArgDataFolder, tbDataFolder.Text);
}

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

@@ -33,42 +33,42 @@
this.btnRestart = new System.Windows.Forms.Button();
this.btnOpenAppFolder = new System.Windows.Forms.Button();
this.btnOpenDataFolder = new System.Windows.Forms.Button();
this.numMemoryThreshold = new TweetDuck.Core.Controls.NumericUpDownEx();
this.checkBrowserGCReload = new System.Windows.Forms.CheckBox();
this.numClearCacheThreshold = new TweetDuck.Core.Controls.NumericUpDownEx();
this.checkClearCacheAuto = new System.Windows.Forms.CheckBox();
this.labelApp = new System.Windows.Forms.Label();
this.panelApp = new System.Windows.Forms.Panel();
this.panelAppButtons = new System.Windows.Forms.Panel();
this.labelPerformance = new System.Windows.Forms.Label();
this.panelPerformance = new System.Windows.Forms.Panel();
this.labelMemoryUsage = new System.Windows.Forms.Label();
this.panelClearCacheAuto = new System.Windows.Forms.Panel();
this.labelCache = new System.Windows.Forms.Label();
this.panelConfiguration = new System.Windows.Forms.Panel();
this.labelConfiguration = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.numMemoryThreshold)).BeginInit();
this.panelApp.SuspendLayout();
this.panelPerformance.SuspendLayout();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
((System.ComponentModel.ISupportInitialize)(this.numClearCacheThreshold)).BeginInit();
this.panelAppButtons.SuspendLayout();
this.panelClearCacheAuto.SuspendLayout();
this.panelConfiguration.SuspendLayout();
this.flowPanel.SuspendLayout();
this.SuspendLayout();
//
// btnClearCache
//
this.btnClearCache.Location = new System.Drawing.Point(5, 28);
this.btnClearCache.Location = new System.Drawing.Point(5, 172);
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.toolTip.SetToolTip(this.btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
this.btnClearCache.UseVisualStyleBackColor = true;
//
// checkHardwareAcceleration
//
this.checkHardwareAcceleration.AutoSize = true;
this.checkHardwareAcceleration.Location = new System.Drawing.Point(6, 5);
this.checkHardwareAcceleration.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkHardwareAcceleration.Location = new System.Drawing.Point(6, 124);
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.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience\r\nvisual glitches. This option will not be exported in a profile.");
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
//
// btnEditCefArgs
@@ -79,7 +79,6 @@
this.btnEditCefArgs.Size = new System.Drawing.Size(144, 23);
this.btnEditCefArgs.TabIndex = 0;
this.btnEditCefArgs.Text = "Edit CEF Arguments";
this.toolTip.SetToolTip(this.btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
this.btnEditCefArgs.UseVisualStyleBackColor = true;
//
// btnEditCSS
@@ -89,7 +88,6 @@
this.btnEditCSS.Size = new System.Drawing.Size(144, 23);
this.btnEditCSS.TabIndex = 1;
this.btnEditCSS.Text = "Edit CSS";
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
this.btnEditCSS.UseVisualStyleBackColor = true;
//
// btnRestartArgs
@@ -99,7 +97,6 @@
this.btnRestartArgs.Size = new System.Drawing.Size(144, 23);
this.btnRestartArgs.TabIndex = 3;
this.btnRestartArgs.Text = "Restart with Arguments";
this.toolTip.SetToolTip(this.btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
this.btnRestartArgs.UseVisualStyleBackColor = true;
//
// btnRestart
@@ -109,7 +106,6 @@
this.btnRestart.Size = new System.Drawing.Size(144, 23);
this.btnRestart.TabIndex = 2;
this.btnRestart.Text = "Restart the Program";
this.toolTip.SetToolTip(this.btnRestart, "Restarts the program using the same command\r\nline arguments that were used at launch.");
this.btnRestart.UseVisualStyleBackColor = true;
//
// btnOpenAppFolder
@@ -120,7 +116,6 @@
this.btnOpenAppFolder.Size = new System.Drawing.Size(144, 23);
this.btnOpenAppFolder.TabIndex = 0;
this.btnOpenAppFolder.Text = "Open Program Folder";
this.toolTip.SetToolTip(this.btnOpenAppFolder, "Opens the folder where the app is located.");
this.btnOpenAppFolder.UseVisualStyleBackColor = true;
//
// btnOpenDataFolder
@@ -131,138 +126,145 @@
this.btnOpenDataFolder.Size = new System.Drawing.Size(144, 23);
this.btnOpenDataFolder.TabIndex = 1;
this.btnOpenDataFolder.Text = "Open Data Folder";
this.toolTip.SetToolTip(this.btnOpenDataFolder, "Opens the folder where your profile data is located.");
this.btnOpenDataFolder.UseVisualStyleBackColor = true;
//
// numMemoryThreshold
// numClearCacheThreshold
//
this.numMemoryThreshold.Increment = new decimal(new int[] {
50,
0,
0,
0});
this.numMemoryThreshold.Location = new System.Drawing.Point(202, 82);
this.numMemoryThreshold.Maximum = 2000;
this.numMemoryThreshold.Minimum = 200;
this.numMemoryThreshold.Name = "numMemoryThreshold";
this.numMemoryThreshold.Size = new System.Drawing.Size(97, 20);
this.numMemoryThreshold.TabIndex = 4;
this.numMemoryThreshold.TextSuffix = " MB";
this.toolTip.SetToolTip(this.numMemoryThreshold, "Minimum amount of memory usage by the browser process to trigger the cleanup.\r\nThis is not a limit, the usage is allowed to exceed this value.");
this.numMemoryThreshold.Value = 400;
this.numClearCacheThreshold.Increment = 50;
this.numClearCacheThreshold.Location = new System.Drawing.Point(227, 4);
this.numClearCacheThreshold.Maximum = 1000;
this.numClearCacheThreshold.Minimum = 100;
this.numClearCacheThreshold.Name = "numClearCacheThreshold";
this.numClearCacheThreshold.Size = new System.Drawing.Size(72, 20);
this.numClearCacheThreshold.TabIndex = 1;
this.numClearCacheThreshold.TextSuffix = " MB";
this.numClearCacheThreshold.Value = 250;
//
// checkBrowserGCReload
// checkClearCacheAuto
//
this.checkBrowserGCReload.AutoSize = true;
this.checkBrowserGCReload.Location = new System.Drawing.Point(6, 84);
this.checkBrowserGCReload.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkBrowserGCReload.Name = "checkBrowserGCReload";
this.checkBrowserGCReload.Size = new System.Drawing.Size(190, 17);
this.checkBrowserGCReload.TabIndex = 3;
this.checkBrowserGCReload.Text = "Enable Browser Memory Threshold";
this.toolTip.SetToolTip(this.checkBrowserGCReload, "Automatically reloads TweetDeck to save memory. This option only works if\r\nthe browser is in a \'default state\', i.e. all modals and drawers are closed, and\r\nall columns are scrolled to top. This option will not be exported in a profile.");
this.checkBrowserGCReload.UseVisualStyleBackColor = true;
this.checkClearCacheAuto.AutoSize = true;
this.checkClearCacheAuto.Location = new System.Drawing.Point(6, 6);
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 = 0;
this.checkClearCacheAuto.Text = "Clear Cache Automatically When Above";
this.checkClearCacheAuto.UseVisualStyleBackColor = true;
//
// labelApp
//
this.labelApp.AutoSize = true;
this.labelApp.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelApp.Location = new System.Drawing.Point(6, 8);
this.labelApp.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelApp.Location = new System.Drawing.Point(0, 0);
this.labelApp.Margin = new System.Windows.Forms.Padding(0);
this.labelApp.Name = "labelApp";
this.labelApp.Size = new System.Drawing.Size(38, 20);
this.labelApp.TabIndex = 0;
this.labelApp.Text = "App";
//
// panelApp
// panelAppButtons
//
this.panelApp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelApp.Controls.Add(this.btnOpenDataFolder);
this.panelApp.Controls.Add(this.btnOpenAppFolder);
this.panelApp.Controls.Add(this.btnRestart);
this.panelApp.Controls.Add(this.btnRestartArgs);
this.panelApp.Location = new System.Drawing.Point(9, 31);
this.panelApp.Name = "panelApp";
this.panelApp.Size = new System.Drawing.Size(322, 59);
this.panelApp.TabIndex = 1;
this.panelAppButtons.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelAppButtons.Controls.Add(this.btnOpenDataFolder);
this.panelAppButtons.Controls.Add(this.btnOpenAppFolder);
this.panelAppButtons.Controls.Add(this.btnRestart);
this.panelAppButtons.Controls.Add(this.btnRestartArgs);
this.panelAppButtons.Location = new System.Drawing.Point(0, 20);
this.panelAppButtons.Margin = new System.Windows.Forms.Padding(0);
this.panelAppButtons.Name = "panelAppButtons";
this.panelAppButtons.Size = new System.Drawing.Size(322, 58);
this.panelAppButtons.TabIndex = 1;
//
// labelPerformance
//
this.labelPerformance.AutoSize = true;
this.labelPerformance.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelPerformance.Location = new System.Drawing.Point(6, 114);
this.labelPerformance.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
this.labelPerformance.Location = new System.Drawing.Point(0, 98);
this.labelPerformance.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelPerformance.Name = "labelPerformance";
this.labelPerformance.Size = new System.Drawing.Size(100, 20);
this.labelPerformance.TabIndex = 2;
this.labelPerformance.Text = "Performance";
//
// panelPerformance
// panelClearCacheAuto
//
this.panelPerformance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelPerformance.Controls.Add(this.checkBrowserGCReload);
this.panelPerformance.Controls.Add(this.numMemoryThreshold);
this.panelPerformance.Controls.Add(this.labelMemoryUsage);
this.panelPerformance.Controls.Add(this.checkHardwareAcceleration);
this.panelPerformance.Controls.Add(this.btnClearCache);
this.panelPerformance.Location = new System.Drawing.Point(9, 137);
this.panelPerformance.Name = "panelPerformance";
this.panelPerformance.Size = new System.Drawing.Size(322, 105);
this.panelPerformance.TabIndex = 3;
this.panelClearCacheAuto.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelClearCacheAuto.Controls.Add(this.checkClearCacheAuto);
this.panelClearCacheAuto.Controls.Add(this.numClearCacheThreshold);
this.panelClearCacheAuto.Location = new System.Drawing.Point(0, 198);
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 = 6;
//
// labelMemoryUsage
// labelCache
//
this.labelMemoryUsage.AutoSize = true;
this.labelMemoryUsage.Location = new System.Drawing.Point(3, 66);
this.labelMemoryUsage.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelMemoryUsage.Name = "labelMemoryUsage";
this.labelMemoryUsage.Size = new System.Drawing.Size(78, 13);
this.labelMemoryUsage.TabIndex = 2;
this.labelMemoryUsage.Text = "Memory Usage";
this.labelCache.AutoSize = true;
this.labelCache.Location = new System.Drawing.Point(3, 156);
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 = 4;
this.labelCache.Text = "Cache";
//
// panelConfiguration
//
this.panelConfiguration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelConfiguration.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelConfiguration.Controls.Add(this.btnEditCSS);
this.panelConfiguration.Controls.Add(this.btnEditCefArgs);
this.panelConfiguration.Location = new System.Drawing.Point(9, 289);
this.panelConfiguration.Location = new System.Drawing.Point(0, 264);
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
//
this.labelConfiguration.AutoSize = true;
this.labelConfiguration.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelConfiguration.Location = new System.Drawing.Point(6, 266);
this.labelConfiguration.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
this.labelConfiguration.Location = new System.Drawing.Point(0, 244);
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
//
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelApp);
this.flowPanel.Controls.Add(this.panelAppButtons);
this.flowPanel.Controls.Add(this.labelPerformance);
this.flowPanel.Controls.Add(this.checkHardwareAcceleration);
this.flowPanel.Controls.Add(this.labelCache);
this.flowPanel.Controls.Add(this.btnClearCache);
this.flowPanel.Controls.Add(this.panelClearCacheAuto);
this.flowPanel.Controls.Add(this.labelConfiguration);
this.flowPanel.Controls.Add(this.panelConfiguration);
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, 295);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsAdvanced
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.labelConfiguration);
this.Controls.Add(this.panelConfiguration);
this.Controls.Add(this.panelPerformance);
this.Controls.Add(this.labelPerformance);
this.Controls.Add(this.panelApp);
this.Controls.Add(this.labelApp);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsAdvanced";
this.Size = new System.Drawing.Size(340, 328);
((System.ComponentModel.ISupportInitialize)(this.numMemoryThreshold)).EndInit();
this.panelApp.ResumeLayout(false);
this.panelPerformance.ResumeLayout(false);
this.panelPerformance.PerformLayout();
this.Size = new System.Drawing.Size(340, 313);
((System.ComponentModel.ISupportInitialize)(this.numClearCacheThreshold)).EndInit();
this.panelAppButtons.ResumeLayout(false);
this.panelClearCacheAuto.ResumeLayout(false);
this.panelClearCacheAuto.PerformLayout();
this.panelConfiguration.ResumeLayout(false);
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
@@ -278,13 +280,14 @@
private System.Windows.Forms.Button btnOpenAppFolder;
private System.Windows.Forms.Button btnOpenDataFolder;
private System.Windows.Forms.Label labelApp;
private System.Windows.Forms.Panel panelApp;
private System.Windows.Forms.Panel panelAppButtons;
private System.Windows.Forms.Label labelPerformance;
private System.Windows.Forms.Panel panelPerformance;
private System.Windows.Forms.Panel panelClearCacheAuto;
private System.Windows.Forms.Panel panelConfiguration;
private System.Windows.Forms.Label labelConfiguration;
private System.Windows.Forms.Label labelMemoryUsage;
private Controls.NumericUpDownEx numMemoryThreshold;
private System.Windows.Forms.CheckBox checkBrowserGCReload;
private System.Windows.Forms.Label labelCache;
private Controls.NumericUpDownEx numClearCacheThreshold;
private System.Windows.Forms.CheckBox checkClearCacheAuto;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
}
}

View File

@@ -1,8 +1,10 @@
using System;
using System.Diagnostics;
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;
@@ -17,6 +19,19 @@ namespace TweetDuck.Core.Other.Settings{
this.reinjectBrowserCSS = reinjectBrowserCSS;
toolTip.SetToolTip(btnOpenAppFolder, "Opens the folder where the app is located.");
toolTip.SetToolTip(btnOpenDataFolder, "Opens the folder where your profile data is located.");
toolTip.SetToolTip(btnRestart, "Restarts the program using the same command\r\nline arguments that were used at launch.");
toolTip.SetToolTip(btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
toolTip.SetToolTip(checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience\r\nvisual glitches. This option will not be exported in a profile.");
toolTip.SetToolTip(btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
toolTip.SetToolTip(checkClearCacheAuto, "Automatically clears cache when its size exceeds the set threshold. Note that cache can only be cleared when closing TweetDuck.");
toolTip.SetToolTip(btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
toolTip.SetToolTip(btnEditCSS, "Set custom CSS for browser and notification windows.");
if (SystemConfig.IsHardwareAccelerationSupported){
checkHardwareAcceleration.Checked = SysConfig.HardwareAcceleration;
}
@@ -25,33 +40,34 @@ namespace TweetDuck.Core.Other.Settings{
checkHardwareAcceleration.Checked = false;
}
checkBrowserGCReload.Checked = SysConfig.EnableBrowserGCReload;
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
numMemoryThreshold.SetValueSafe(SysConfig.BrowserMemoryThreshold);
checkClearCacheAuto.Checked = SysConfig.ClearCacheAutomatically;
numClearCacheThreshold.Enabled = checkClearCacheAuto.Checked;
numClearCacheThreshold.SetValueSafe(SysConfig.ClearCacheThreshold);
BrowserCache.CalculateCacheSize(task => {
string text = task.IsCompleted ? (int)Math.Ceiling(task.Result/(1024.0*1024.0))+" MB" : "(unknown size)";
BrowserCache.GetCacheSize(task => {
string text = task.Status == TaskStatus.RanToCompletion ? (int)Math.Ceiling(task.Result/(1024.0*1024.0))+" MB" : "unknown";
this.InvokeSafe(() => btnClearCache.Text = $"Clear Cache ({text})");
});
}
public override void OnReady(){
btnClearCache.Click += btnClearCache_Click;
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
checkBrowserGCReload.CheckedChanged += checkBrowserGCReload_CheckedChanged;
numMemoryThreshold.ValueChanged += numMemoryThreshold_ValueChanged;
btnEditCefArgs.Click += btnEditCefArgs_Click;
btnEditCSS.Click += btnEditCSS_Click;
btnOpenAppFolder.Click += btnOpenAppFolder_Click;
btnOpenDataFolder.Click += btnOpenDataFolder_Click;
btnRestart.Click += btnRestart_Click;
btnRestartArgs.Click += btnRestartArgs_Click;
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
btnClearCache.Click += btnClearCache_Click;
checkClearCacheAuto.CheckedChanged += checkClearCacheAuto_CheckedChanged;
btnEditCefArgs.Click += btnEditCefArgs_Click;
btnEditCSS.Click += btnEditCSS_Click;
}
public override void OnClosing(){
SysConfig.ClearCacheAutomatically = checkClearCacheAuto.Checked;
SysConfig.ClearCacheThreshold = (int)numClearCacheThreshold.Value;
SysConfig.Save();
}
@@ -61,20 +77,15 @@ namespace TweetDuck.Core.Other.Settings{
FormMessage.Information("Clear Cache", "Cache will be automatically cleared when TweetDuck exits.", FormMessage.OK);
}
private void checkClearCacheAuto_CheckedChanged(object sender, EventArgs e){
numClearCacheThreshold.Enabled = checkClearCacheAuto.Checked;
}
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
SysConfig.HardwareAcceleration = checkHardwareAcceleration.Checked;
PromptRestart(); // calls OnClosing
}
private void checkBrowserGCReload_CheckedChanged(object sender, EventArgs e){
SysConfig.EnableBrowserGCReload = checkBrowserGCReload.Checked;
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
}
private void numMemoryThreshold_ValueChanged(object sender, EventArgs e){
SysConfig.BrowserMemoryThreshold = (int)numMemoryThreshold.Value;
}
private void btnEditCefArgs_Click(object sender, EventArgs e){
DialogSettingsCefArgs form = new DialogSettingsCefArgs();

View File

@@ -24,36 +24,60 @@
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.panelFeedback = new System.Windows.Forms.Panel();
this.panelDataCollection = new System.Windows.Forms.Panel();
this.labelDataCollectionLink = new System.Windows.Forms.LinkLabel();
this.checkDataCollection = new System.Windows.Forms.CheckBox();
this.labelDataCollectionMessage = new System.Windows.Forms.Label();
this.btnViewReport = new System.Windows.Forms.Button();
this.btnSendFeedback = new System.Windows.Forms.Button();
this.labelDataCollectionLink = new System.Windows.Forms.LinkLabel();
this.checkDataCollection = new System.Windows.Forms.CheckBox();
this.labelDataCollection = new System.Windows.Forms.Label();
this.labelFeedback = new System.Windows.Forms.Label();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.panelFeedback.SuspendLayout();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.panelDataCollection.SuspendLayout();
this.flowPanel.SuspendLayout();
this.SuspendLayout();
//
// panelFeedback
// panelDataCollection
//
this.panelFeedback.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelFeedback.Controls.Add(this.labelDataCollectionMessage);
this.panelFeedback.Controls.Add(this.btnViewReport);
this.panelFeedback.Controls.Add(this.btnSendFeedback);
this.panelFeedback.Controls.Add(this.labelDataCollectionLink);
this.panelFeedback.Controls.Add(this.checkDataCollection);
this.panelFeedback.Controls.Add(this.labelDataCollection);
this.panelFeedback.Location = new System.Drawing.Point(9, 31);
this.panelFeedback.Name = "panelFeedback";
this.panelFeedback.Size = new System.Drawing.Size(322, 188);
this.panelFeedback.TabIndex = 1;
this.panelDataCollection.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelDataCollection.Controls.Add(this.labelDataCollectionLink);
this.panelDataCollection.Controls.Add(this.checkDataCollection);
this.panelDataCollection.Location = new System.Drawing.Point(0, 74);
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 = 3;
//
// labelDataCollectionLink
//
this.labelDataCollectionLink.AutoSize = true;
this.labelDataCollectionLink.LinkArea = new System.Windows.Forms.LinkArea(1, 10);
this.labelDataCollectionLink.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.labelDataCollectionLink.Location = new System.Drawing.Point(141, 6);
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 = 1;
this.labelDataCollectionLink.TabStop = true;
this.labelDataCollectionLink.Text = "(learn more)";
this.labelDataCollectionLink.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.labelDataCollectionLink.UseCompatibleTextRendering = true;
//
// checkDataCollection
//
this.checkDataCollection.AutoSize = true;
this.checkDataCollection.Location = new System.Drawing.Point(6, 6);
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 = 0;
this.checkDataCollection.Text = "Send Anonymous Data";
this.checkDataCollection.UseVisualStyleBackColor = true;
//
// labelDataCollectionMessage
//
this.labelDataCollectionMessage.Location = new System.Drawing.Point(6, 114);
this.labelDataCollectionMessage.Location = new System.Drawing.Point(6, 135);
this.labelDataCollectionMessage.Margin = new System.Windows.Forms.Padding(6);
this.labelDataCollectionMessage.Name = "labelDataCollectionMessage";
this.labelDataCollectionMessage.Size = new System.Drawing.Size(310, 67);
@@ -62,7 +86,7 @@
// btnViewReport
//
this.btnViewReport.AutoSize = true;
this.btnViewReport.Location = new System.Drawing.Point(6, 82);
this.btnViewReport.Location = new System.Drawing.Point(5, 103);
this.btnViewReport.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.btnViewReport.Name = "btnViewReport";
this.btnViewReport.Size = new System.Drawing.Size(144, 23);
@@ -73,79 +97,72 @@
// btnSendFeedback
//
this.btnSendFeedback.AutoSize = true;
this.btnSendFeedback.Location = new System.Drawing.Point(5, 3);
this.btnSendFeedback.Location = new System.Drawing.Point(5, 23);
this.btnSendFeedback.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
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;
//
// labelDataCollectionLink
//
this.labelDataCollectionLink.AutoSize = true;
this.labelDataCollectionLink.LinkArea = new System.Windows.Forms.LinkArea(1, 10);
this.labelDataCollectionLink.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.labelDataCollectionLink.Location = new System.Drawing.Point(141, 60);
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.TabStop = true;
this.labelDataCollectionLink.Text = "(learn more)";
this.labelDataCollectionLink.UseCompatibleTextRendering = true;
//
// checkDataCollection
//
this.checkDataCollection.AutoSize = true;
this.checkDataCollection.Location = new System.Drawing.Point(6, 59);
this.checkDataCollection.Margin = new System.Windows.Forms.Padding(6, 5, 0, 3);
this.checkDataCollection.Name = "checkDataCollection";
this.checkDataCollection.Size = new System.Drawing.Size(135, 17);
this.checkDataCollection.TabIndex = 2;
this.checkDataCollection.Text = "Send Anonymous Data";
this.checkDataCollection.UseVisualStyleBackColor = true;
//
// labelDataCollection
//
this.labelDataCollection.AutoSize = true;
this.labelDataCollection.Location = new System.Drawing.Point(3, 41);
this.labelDataCollection.Location = new System.Drawing.Point(3, 61);
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
//
this.labelFeedback.AutoSize = true;
this.labelFeedback.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelFeedback.Location = new System.Drawing.Point(6, 8);
this.labelFeedback.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelFeedback.Location = new System.Drawing.Point(0, 0);
this.labelFeedback.Margin = new System.Windows.Forms.Padding(0);
this.labelFeedback.Name = "labelFeedback";
this.labelFeedback.Size = new System.Drawing.Size(80, 20);
this.labelFeedback.TabIndex = 0;
this.labelFeedback.Text = "Feedback";
//
// flowPanel
//
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelFeedback);
this.flowPanel.Controls.Add(this.btnSendFeedback);
this.flowPanel.Controls.Add(this.labelDataCollection);
this.flowPanel.Controls.Add(this.panelDataCollection);
this.flowPanel.Controls.Add(this.btnViewReport);
this.flowPanel.Controls.Add(this.labelDataCollectionMessage);
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, 209);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsFeedback
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.panelFeedback);
this.Controls.Add(this.labelFeedback);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsFeedback";
this.Size = new System.Drawing.Size(340, 230);
this.panelFeedback.ResumeLayout(false);
this.panelFeedback.PerformLayout();
this.Size = new System.Drawing.Size(340, 227);
this.panelDataCollection.ResumeLayout(false);
this.panelDataCollection.PerformLayout();
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelFeedback;
private System.Windows.Forms.Panel panelDataCollection;
private System.Windows.Forms.CheckBox checkDataCollection;
private System.Windows.Forms.Label labelDataCollection;
private System.Windows.Forms.Label labelFeedback;
@@ -154,5 +171,6 @@
private System.Windows.Forms.Button btnSendFeedback;
private System.Windows.Forms.Button btnViewReport;
private System.Windows.Forms.Label labelDataCollectionMessage;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
}
}

View File

@@ -26,7 +26,6 @@
this.components = new System.ComponentModel.Container();
this.checkExpandLinks = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
this.btnCheckUpdates = new System.Windows.Forms.Button();
this.labelZoomValue = new System.Windows.Forms.Label();
@@ -37,108 +36,94 @@
this.labelZoom = new System.Windows.Forms.Label();
this.zoomUpdateTimer = new System.Windows.Forms.Timer(this.components);
this.labelUI = new System.Windows.Forms.Label();
this.panelUI = new System.Windows.Forms.Panel();
this.panelUpdates = new System.Windows.Forms.Panel();
this.labelUpdates = new System.Windows.Forms.Label();
this.panelZoom = new System.Windows.Forms.Panel();
this.checkAnimatedAvatars = new System.Windows.Forms.CheckBox();
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.panelUI.SuspendLayout();
this.panelUpdates.SuspendLayout();
this.panelZoom.SuspendLayout();
this.flowPanel.SuspendLayout();
this.SuspendLayout();
//
// checkExpandLinks
//
this.checkExpandLinks.AutoSize = true;
this.checkExpandLinks.Location = new System.Drawing.Point(6, 5);
this.checkExpandLinks.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkExpandLinks.Location = new System.Drawing.Point(6, 26);
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.toolTip.SetToolTip(this.checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a tooltip instead.");
this.checkExpandLinks.UseVisualStyleBackColor = true;
//
// checkSpellCheck
//
this.checkSpellCheck.AutoSize = true;
this.checkSpellCheck.Location = new System.Drawing.Point(6, 120);
this.checkSpellCheck.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.checkSpellCheck.Name = "checkSpellCheck";
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
this.checkSpellCheck.TabIndex = 5;
this.checkSpellCheck.Text = "Enable Spell Check";
this.toolTip.SetToolTip(this.checkSpellCheck, "Underlines words that are spelled incorrectly.");
this.checkSpellCheck.UseVisualStyleBackColor = true;
//
// checkUpdateNotifications
//
this.checkUpdateNotifications.AutoSize = true;
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 5);
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
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.toolTip.SetToolTip(this.checkUpdateNotifications, "Checks for updates every hour.\r\nIf an update is dismissed, it will not appear again.");
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
//
// btnCheckUpdates
//
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 28);
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.toolTip.SetToolTip(this.btnCheckUpdates, "Forces an update check, even for updates that had been dismissed.");
this.btnCheckUpdates.UseVisualStyleBackColor = true;
//
// labelZoomValue
//
this.labelZoomValue.BackColor = System.Drawing.Color.Transparent;
this.labelZoomValue.Location = new System.Drawing.Point(147, 169);
this.labelZoomValue.Location = new System.Drawing.Point(147, 4);
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;
this.toolTip.SetToolTip(this.labelZoomValue, "Changes the zoom level.\r\nAlso affects notifications and screenshots.");
//
// checkSwitchAccountSelectors
//
this.checkSwitchAccountSelectors.AutoSize = true;
this.checkSwitchAccountSelectors.Location = new System.Drawing.Point(6, 28);
this.checkSwitchAccountSelectors.Location = new System.Drawing.Point(6, 49);
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.toolTip.SetToolTip(this.checkSwitchAccountSelectors, "When (re)tweeting, click to select a single account or hold Shift to\r\nselect multiple accounts, instead of TweetDeck\'s default behavior.");
this.checkSwitchAccountSelectors.UseVisualStyleBackColor = true;
//
// checkBestImageQuality
//
this.checkBestImageQuality.AutoSize = true;
this.checkBestImageQuality.Location = new System.Drawing.Point(6, 74);
this.checkBestImageQuality.Location = new System.Drawing.Point(6, 118);
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.toolTip.SetToolTip(this.checkBestImageQuality, "When right-clicking a tweet image, the context menu options\r\nwill use links to the original image size (:orig in the URL).");
this.checkBestImageQuality.UseVisualStyleBackColor = true;
//
// checkOpenSearchInFirstColumn
//
this.checkOpenSearchInFirstColumn.AutoSize = true;
this.checkOpenSearchInFirstColumn.Location = new System.Drawing.Point(6, 51);
this.checkOpenSearchInFirstColumn.Location = new System.Drawing.Point(6, 72);
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.toolTip.SetToolTip(this.checkOpenSearchInFirstColumn, "By default, TweetDeck adds Search columns at the end.\r\nThis option makes them appear before the first column instead.");
this.checkOpenSearchInFirstColumn.UseVisualStyleBackColor = true;
//
// trackBarZoom
@@ -146,24 +131,24 @@
this.trackBarZoom.AutoSize = false;
this.trackBarZoom.BackColor = System.Drawing.SystemColors.Control;
this.trackBarZoom.LargeChange = 25;
this.trackBarZoom.Location = new System.Drawing.Point(3, 168);
this.trackBarZoom.Location = new System.Drawing.Point(3, 3);
this.trackBarZoom.Maximum = 200;
this.trackBarZoom.Minimum = 50;
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, 152);
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
@@ -175,82 +160,139 @@
//
this.labelUI.AutoSize = true;
this.labelUI.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelUI.Location = new System.Drawing.Point(6, 8);
this.labelUI.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelUI.Location = new System.Drawing.Point(0, 0);
this.labelUI.Margin = new System.Windows.Forms.Padding(0);
this.labelUI.Name = "labelUI";
this.labelUI.Size = new System.Drawing.Size(111, 20);
this.labelUI.TabIndex = 0;
this.labelUI.Text = "User Interface";
//
// panelUI
// panelZoom
//
this.panelUI.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelUI.Controls.Add(this.checkAnimatedAvatars);
this.panelUI.Controls.Add(this.checkOpenSearchInFirstColumn);
this.panelUI.Controls.Add(this.checkBestImageQuality);
this.panelUI.Controls.Add(this.checkExpandLinks);
this.panelUI.Controls.Add(this.checkSwitchAccountSelectors);
this.panelUI.Controls.Add(this.checkSpellCheck);
this.panelUI.Controls.Add(this.labelZoom);
this.panelUI.Controls.Add(this.trackBarZoom);
this.panelUI.Controls.Add(this.labelZoomValue);
this.panelUI.Location = new System.Drawing.Point(9, 31);
this.panelUI.Name = "panelUI";
this.panelUI.Size = new System.Drawing.Size(322, 205);
this.panelUI.TabIndex = 1;
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, 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 = 12;
//
// panelUpdates
// checkAnimatedAvatars
//
this.panelUpdates.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelUpdates.Controls.Add(this.checkUpdateNotifications);
this.panelUpdates.Controls.Add(this.btnCheckUpdates);
this.panelUpdates.Location = new System.Drawing.Point(8, 283);
this.panelUpdates.Name = "panelUpdates";
this.panelUpdates.Size = new System.Drawing.Size(322, 55);
this.panelUpdates.TabIndex = 3;
this.checkAnimatedAvatars.AutoSize = true;
this.checkAnimatedAvatars.Location = new System.Drawing.Point(6, 141);
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 = 6;
this.checkAnimatedAvatars.Text = "Enable Animated Avatars";
this.checkAnimatedAvatars.UseVisualStyleBackColor = true;
//
// labelUpdates
//
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(5, 260);
this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
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";
//
// checkAnimatedAvatars
// flowPanel
//
this.checkAnimatedAvatars.AutoSize = true;
this.checkAnimatedAvatars.Location = new System.Drawing.Point(6, 97);
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.Text = "Enable Animated Avatars";
this.toolTip.SetToolTip(this.checkAnimatedAvatars, "Some old Twitter avatars could be uploaded as animated GIFs.");
this.checkAnimatedAvatars.UseVisualStyleBackColor = true;
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelUI);
this.flowPanel.Controls.Add(this.checkExpandLinks);
this.flowPanel.Controls.Add(this.checkSwitchAccountSelectors);
this.flowPanel.Controls.Add(this.checkOpenSearchInFirstColumn);
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);
this.flowPanel.Controls.Add(this.checkUpdateNotifications);
this.flowPanel.Controls.Add(this.btnCheckUpdates);
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, 438);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// checkKeepLikeFollowDialogsOpen
//
this.checkKeepLikeFollowDialogsOpen.AutoSize = true;
this.checkKeepLikeFollowDialogsOpen.Location = new System.Drawing.Point(6, 95);
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 = 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.labelUpdates);
this.Controls.Add(this.panelUpdates);
this.Controls.Add(this.panelUI);
this.Controls.Add(this.labelUI);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsGeneral";
this.Size = new System.Drawing.Size(340, 348);
this.Size = new System.Drawing.Size(340, 456);
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).EndInit();
this.panelUI.ResumeLayout(false);
this.panelUI.PerformLayout();
this.panelUpdates.ResumeLayout(false);
this.panelUpdates.PerformLayout();
this.panelZoom.ResumeLayout(false);
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
@@ -258,7 +300,6 @@
private System.Windows.Forms.CheckBox checkExpandLinks;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.CheckBox checkSpellCheck;
private System.Windows.Forms.CheckBox checkUpdateNotifications;
private System.Windows.Forms.Button btnCheckUpdates;
private System.Windows.Forms.Label labelZoom;
@@ -267,11 +308,16 @@
private System.Windows.Forms.Timer zoomUpdateTimer;
private System.Windows.Forms.CheckBox checkSwitchAccountSelectors;
private System.Windows.Forms.Label labelUI;
private System.Windows.Forms.Panel panelUI;
private System.Windows.Forms.Panel panelUpdates;
private System.Windows.Forms.Panel panelZoom;
private System.Windows.Forms.Label labelUpdates;
private System.Windows.Forms.CheckBox checkBestImageQuality;
private System.Windows.Forms.CheckBox checkOpenSearchInFirstColumn;
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();
@@ -18,16 +25,40 @@ namespace TweetDuck.Core.Other.Settings{
this.updates.CheckFinished += updates_CheckFinished;
Disposed += (sender, args) => this.updates.CheckFinished -= updates_CheckFinished;
toolTip.SetToolTip(checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a tooltip instead.");
toolTip.SetToolTip(checkSwitchAccountSelectors, "When (re)tweeting, click to select a single account or hold Shift to\r\nselect multiple accounts, instead of TweetDeck\'s default behavior.");
toolTip.SetToolTip(checkOpenSearchInFirstColumn, "By default, TweetDeck adds Search columns at the end.\r\nThis option makes them appear before the first column instead.");
toolTip.SetToolTip(checkKeepLikeFollowDialogsOpen, "Allows liking and following from multiple accounts at once,\r\ninstead of automatically closing the dialog after taking an action.");
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));
trackBarZoom.SetValueSafe(Config.ZoomLevel);
labelZoomValue.Text = trackBarZoom.Value+"%";
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.");
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
checkSwitchAccountSelectors.Checked = Config.SwitchAccountSelectors;
checkOpenSearchInFirstColumn.Checked = Config.OpenSearchInFirstColumn;
checkKeepLikeFollowDialogsOpen.Checked = Config.KeepLikeFollowDialogsOpen;
checkBestImageQuality.Checked = Config.BestImageQuality;
checkAnimatedAvatars.Checked = Config.EnableAnimatedImages;
checkSpellCheck.Checked = Config.EnableSpellCheck;
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;
}
@@ -36,9 +67,12 @@ namespace TweetDuck.Core.Other.Settings{
checkExpandLinks.CheckedChanged += checkExpandLinks_CheckedChanged;
checkSwitchAccountSelectors.CheckedChanged += checkSwitchAccountSelectors_CheckedChanged;
checkOpenSearchInFirstColumn.CheckedChanged += checkOpenSearchInFirstColumn_CheckedChanged;
checkKeepLikeFollowDialogsOpen.CheckedChanged += checkKeepLikeFollowDialogsOpen_CheckedChanged;
checkBestImageQuality.CheckedChanged += checkBestImageQuality_CheckedChanged;
checkAnimatedAvatars.CheckedChanged += checkAnimatedAvatars_CheckedChanged;
checkSpellCheck.CheckedChanged += checkSpellCheck_CheckedChanged;
checkSmoothScrolling.CheckedChanged += checkSmoothScrolling_CheckedChanged;
comboBoxBrowserPath.SelectedIndexChanged += comboBoxBrowserPath_SelectedIndexChanged;
trackBarZoom.ValueChanged += trackBarZoom_ValueChanged;
checkUpdateNotifications.CheckedChanged += checkUpdateNotifications_CheckedChanged;
@@ -61,6 +95,10 @@ namespace TweetDuck.Core.Other.Settings{
Config.OpenSearchInFirstColumn = checkOpenSearchInFirstColumn.Checked;
}
private void checkKeepLikeFollowDialogsOpen_CheckedChanged(object sender, EventArgs e){
Config.KeepLikeFollowDialogsOpen = checkKeepLikeFollowDialogsOpen.Checked;
}
private void checkBestImageQuality_CheckedChanged(object sender, EventArgs e){
Config.BestImageQuality = checkBestImageQuality.Checked;
}
@@ -70,9 +108,49 @@ namespace TweetDuck.Core.Other.Settings{
BrowserProcessHandler.UpdatePrefs().ContinueWith(task => browser.ReloadColumns());
}
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
Config.EnableSpellCheck = checkSpellCheck.Checked;
BrowserProcessHandler.UpdatePrefs();
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){

View File

@@ -0,0 +1,155 @@
namespace TweetDuck.Core.Other.Settings {
partial class TabSettingsLocales {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
this.labelLocales = new System.Windows.Forms.Label();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.labelSpellCheckLanguage = new System.Windows.Forms.Label();
this.comboBoxSpellCheckLanguage = new System.Windows.Forms.ComboBox();
this.labelTranslations = new System.Windows.Forms.Label();
this.labelTranslationTarget = new System.Windows.Forms.Label();
this.comboBoxTranslationTarget = new System.Windows.Forms.ComboBox();
this.flowPanel.SuspendLayout();
this.SuspendLayout();
//
// checkSpellCheck
//
this.checkSpellCheck.AutoSize = true;
this.checkSpellCheck.Location = new System.Drawing.Point(6, 26);
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 = 1;
this.checkSpellCheck.Text = "Enable Spell Check";
this.checkSpellCheck.UseVisualStyleBackColor = true;
//
// labelLocales
//
this.labelLocales.AutoSize = true;
this.labelLocales.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelLocales.Location = new System.Drawing.Point(0, 0);
this.labelLocales.Margin = new System.Windows.Forms.Padding(0);
this.labelLocales.Name = "labelLocales";
this.labelLocales.Size = new System.Drawing.Size(64, 20);
this.labelLocales.TabIndex = 0;
this.labelLocales.Text = "Locales";
//
// flowPanel
//
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelLocales);
this.flowPanel.Controls.Add(this.checkSpellCheck);
this.flowPanel.Controls.Add(this.labelSpellCheckLanguage);
this.flowPanel.Controls.Add(this.comboBoxSpellCheckLanguage);
this.flowPanel.Controls.Add(this.labelTranslations);
this.flowPanel.Controls.Add(this.labelTranslationTarget);
this.flowPanel.Controls.Add(this.comboBoxTranslationTarget);
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, 193);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// labelSpellCheckLanguage
//
this.labelSpellCheckLanguage.AutoSize = true;
this.labelSpellCheckLanguage.Location = new System.Drawing.Point(3, 58);
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 = 2;
this.labelSpellCheckLanguage.Text = "Spell Check Language";
//
// comboBoxSpellCheckLanguage
//
this.comboBoxSpellCheckLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxSpellCheckLanguage.FormattingEnabled = true;
this.comboBoxSpellCheckLanguage.Location = new System.Drawing.Point(5, 74);
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 = 3;
//
// labelTranslations
//
this.labelTranslations.AutoSize = true;
this.labelTranslations.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelTranslations.Location = new System.Drawing.Point(0, 118);
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 = 4;
this.labelTranslations.Text = "Bing Translator";
//
// labelTranslationTarget
//
this.labelTranslationTarget.AutoSize = true;
this.labelTranslationTarget.Location = new System.Drawing.Point(3, 150);
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 = 5;
this.labelTranslationTarget.Text = "Target Language";
//
// comboBoxTranslationTarget
//
this.comboBoxTranslationTarget.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxTranslationTarget.FormattingEnabled = true;
this.comboBoxTranslationTarget.Location = new System.Drawing.Point(5, 166);
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 = 6;
//
// TabSettingsLocales
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsLocales";
this.Size = new System.Drawing.Size(340, 211);
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.CheckBox checkSpellCheck;
private System.Windows.Forms.Label labelLocales;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
private System.Windows.Forms.ComboBox comboBoxTranslationTarget;
private System.Windows.Forms.Label labelTranslationTarget;
private System.Windows.Forms.ComboBox comboBoxSpellCheckLanguage;
private System.Windows.Forms.Label labelTranslations;
private System.Windows.Forms.Label labelSpellCheckLanguage;
}
}

View File

@@ -0,0 +1,53 @@
using System;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Other.Settings{
sealed partial class TabSettingsLocales : BaseTabSettings{
public TabSettingsLocales(){
InitializeComponent();
toolTip.SetToolTip(checkSpellCheck, "Underlines words that are spelled incorrectly.");
toolTip.SetToolTip(comboBoxSpellCheckLanguage, "Language used for spell check.");
toolTip.SetToolTip(comboBoxTranslationTarget, "Language tweets are translated into.");
checkSpellCheck.Checked = Config.EnableSpellCheck;
try{
foreach(LocaleUtils.Item item in LocaleUtils.SpellCheckLanguages){
comboBoxSpellCheckLanguage.Items.Add(item);
}
}catch{
comboBoxSpellCheckLanguage.Items.Add(new LocaleUtils.Item("en-US"));
}
comboBoxSpellCheckLanguage.SelectedItem = new LocaleUtils.Item(Config.SpellCheckLanguage);
foreach(LocaleUtils.Item item in LocaleUtils.TweetDeckTranslationLocales){
comboBoxTranslationTarget.Items.Add(item);
}
comboBoxTranslationTarget.SelectedItem = new LocaleUtils.Item(Config.TranslationTarget);
}
public override void OnReady(){
checkSpellCheck.CheckedChanged += checkSpellCheck_CheckedChanged;
comboBoxSpellCheckLanguage.SelectedValueChanged += comboBoxSpellCheckLanguage_SelectedValueChanged;
comboBoxTranslationTarget.SelectedValueChanged += comboBoxTranslationTarget_SelectedValueChanged;
}
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
Config.EnableSpellCheck = checkSpellCheck.Checked;
BrowserProcessHandler.UpdatePrefs();
}
private void comboBoxSpellCheckLanguage_SelectedValueChanged(object sender, EventArgs e){
Config.SpellCheckLanguage = (comboBoxSpellCheckLanguage.SelectedItem as LocaleUtils.Item)?.Code;
PromptRestart();
}
private void comboBoxTranslationTarget_SelectedValueChanged(object sender, EventArgs e){
Config.TranslationTarget = (comboBoxTranslationTarget.SelectedItem as LocaleUtils.Item)?.Code;
}
}
}

View File

@@ -51,7 +51,8 @@
this.radioSizeAuto = new System.Windows.Forms.RadioButton();
this.radioSizeCustom = new System.Windows.Forms.RadioButton();
this.labelGeneral = new System.Windows.Forms.Label();
this.panelGeneral = new System.Windows.Forms.Panel();
this.panelEdgeDistance = new System.Windows.Forms.Panel();
this.checkMediaPreviews = new System.Windows.Forms.CheckBox();
this.labelScrollSpeedValue = new System.Windows.Forms.Label();
this.trackBarScrollSpeed = new System.Windows.Forms.TrackBar();
this.labelScrollSpeed = new System.Windows.Forms.Label();
@@ -61,59 +62,60 @@
this.labelDuration = new System.Windows.Forms.Label();
this.labelTimer = new System.Windows.Forms.Label();
this.labelSize = new System.Windows.Forms.Label();
this.panelMiscellaneous = new System.Windows.Forms.Panel();
this.panelSize = new System.Windows.Forms.Panel();
this.durationUpdateTimer = new System.Windows.Forms.Timer(this.components);
this.checkMediaPreviews = new System.Windows.Forms.CheckBox();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.panelScrollSpeed = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
this.tableLayoutDurationButtons.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).BeginInit();
this.panelGeneral.SuspendLayout();
this.panelEdgeDistance.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).BeginInit();
this.panelLocation.SuspendLayout();
this.panelTimer.SuspendLayout();
this.panelMiscellaneous.SuspendLayout();
this.panelSize.SuspendLayout();
this.flowPanel.SuspendLayout();
this.panelScrollSpeed.SuspendLayout();
this.SuspendLayout();
//
// labelEdgeDistanceValue
//
this.labelEdgeDistanceValue.Location = new System.Drawing.Point(147, 129);
this.labelEdgeDistanceValue.Location = new System.Drawing.Point(145, 4);
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;
//
// labelDisplay
//
this.labelDisplay.AutoSize = true;
this.labelDisplay.Location = new System.Drawing.Point(3, 60);
this.labelDisplay.Location = new System.Drawing.Point(3, 451);
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
//
this.comboBoxDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.comboBoxDisplay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxDisplay.FormattingEnabled = true;
this.comboBoxDisplay.Location = new System.Drawing.Point(5, 76);
this.comboBoxDisplay.Location = new System.Drawing.Point(5, 467);
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
//
this.labelEdgeDistance.AutoSize = true;
this.labelEdgeDistance.Location = new System.Drawing.Point(3, 112);
this.labelEdgeDistance.Location = new System.Drawing.Point(3, 503);
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
@@ -125,7 +127,6 @@
this.radioLocCustom.TabIndex = 4;
this.radioLocCustom.TabStop = true;
this.radioLocCustom.Text = "Custom";
this.toolTip.SetToolTip(this.radioLocCustom, "Drag the example notification window to the desired location.");
this.radioLocCustom.UseVisualStyleBackColor = true;
//
// radioLocBR
@@ -176,13 +177,13 @@
//
this.trackBarEdgeDistance.AutoSize = false;
this.trackBarEdgeDistance.LargeChange = 8;
this.trackBarEdgeDistance.Location = new System.Drawing.Point(5, 128);
this.trackBarEdgeDistance.Location = new System.Drawing.Point(3, 3);
this.trackBarEdgeDistance.Maximum = 40;
this.trackBarEdgeDistance.Minimum = 8;
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;
//
@@ -195,12 +196,12 @@
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationMedium, 0, 0);
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationLong, 1, 0);
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationShort, 0, 0);
this.tableLayoutDurationButtons.Location = new System.Drawing.Point(3, 113);
this.tableLayoutDurationButtons.Location = new System.Drawing.Point(3, 320);
this.tableLayoutDurationButtons.Name = "tableLayoutDurationButtons";
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
//
@@ -250,164 +251,163 @@
// labelDurationValue
//
this.labelDurationValue.BackColor = System.Drawing.Color.Transparent;
this.labelDurationValue.Location = new System.Drawing.Point(147, 77);
this.labelDurationValue.Location = new System.Drawing.Point(147, 4);
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;
this.toolTip.SetToolTip(this.labelDurationValue, "Milliseconds per character.");
//
// trackBarDuration
//
this.trackBarDuration.AutoSize = false;
this.trackBarDuration.Location = new System.Drawing.Point(3, 76);
this.trackBarDuration.Location = new System.Drawing.Point(3, 3);
this.trackBarDuration.Maximum = 60;
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;
//
// checkSkipOnLinkClick
//
this.checkSkipOnLinkClick.AutoSize = true;
this.checkSkipOnLinkClick.Location = new System.Drawing.Point(6, 51);
this.checkSkipOnLinkClick.Location = new System.Drawing.Point(6, 72);
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.toolTip.SetToolTip(this.checkSkipOnLinkClick, "Skips current notification when a link\r\ninside the notification is clicked.");
this.checkSkipOnLinkClick.UseVisualStyleBackColor = true;
//
// checkColumnName
//
this.checkColumnName.AutoSize = true;
this.checkColumnName.Location = new System.Drawing.Point(6, 5);
this.checkColumnName.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkColumnName.Location = new System.Drawing.Point(6, 26);
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.toolTip.SetToolTip(this.checkColumnName, "Shows column name each notification originated\r\nfrom in the notification window title.");
this.checkColumnName.UseVisualStyleBackColor = true;
//
// labelIdlePause
//
this.labelIdlePause.AutoSize = true;
this.labelIdlePause.Location = new System.Drawing.Point(3, 106);
this.labelIdlePause.Location = new System.Drawing.Point(3, 127);
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
//
this.comboBoxIdlePause.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxIdlePause.FormattingEnabled = true;
this.comboBoxIdlePause.Location = new System.Drawing.Point(5, 122);
this.comboBoxIdlePause.Location = new System.Drawing.Point(5, 143);
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.toolTip.SetToolTip(this.comboBoxIdlePause, "Pauses new notifications after going idle for a set amount of time.");
this.comboBoxIdlePause.TabIndex = 6;
//
// checkNonIntrusive
//
this.checkNonIntrusive.AutoSize = true;
this.checkNonIntrusive.Location = new System.Drawing.Point(6, 74);
this.checkNonIntrusive.Location = new System.Drawing.Point(6, 95);
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.toolTip.SetToolTip(this.checkNonIntrusive, "When not idle and the cursor is within the notification window area,\r\nit will be delayed until the cursor moves away to prevent accidental clicks.");
this.checkNonIntrusive.UseVisualStyleBackColor = true;
//
// checkTimerCountDown
//
this.checkTimerCountDown.AutoSize = true;
this.checkTimerCountDown.Location = new System.Drawing.Point(6, 28);
this.checkTimerCountDown.Location = new System.Drawing.Point(6, 236);
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.toolTip.SetToolTip(this.checkTimerCountDown, "The notification timer counts down instead of up.");
this.checkTimerCountDown.UseVisualStyleBackColor = true;
//
// checkNotificationTimer
//
this.checkNotificationTimer.AutoSize = true;
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 5);
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 213);
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;
//
// radioSizeAuto
//
this.radioSizeAuto.Location = new System.Drawing.Point(6, 4);
this.radioSizeAuto.Location = new System.Drawing.Point(5, 4);
this.radioSizeAuto.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
this.radioSizeAuto.Name = "radioSizeAuto";
this.radioSizeAuto.Size = new System.Drawing.Size(92, 17);
this.radioSizeAuto.TabIndex = 0;
this.radioSizeAuto.TabStop = true;
this.radioSizeAuto.Text = "Auto";
this.toolTip.SetToolTip(this.radioSizeAuto, "Notification size is based on the font size and browser zoom level.");
this.radioSizeAuto.UseVisualStyleBackColor = true;
//
// radioSizeCustom
//
this.radioSizeCustom.Location = new System.Drawing.Point(106, 4);
this.radioSizeCustom.Location = new System.Drawing.Point(105, 4);
this.radioSizeCustom.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
this.radioSizeCustom.Name = "radioSizeCustom";
this.radioSizeCustom.Size = new System.Drawing.Size(92, 17);
this.radioSizeCustom.TabIndex = 1;
this.radioSizeCustom.TabStop = true;
this.radioSizeCustom.Text = "Custom";
this.toolTip.SetToolTip(this.radioSizeCustom, "Resize the example notification window to the desired size.");
this.radioSizeCustom.UseVisualStyleBackColor = true;
//
// labelGeneral
//
this.labelGeneral.AutoSize = true;
this.labelGeneral.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelGeneral.Location = new System.Drawing.Point(6, 8);
this.labelGeneral.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelGeneral.Location = new System.Drawing.Point(0, 0);
this.labelGeneral.Margin = new System.Windows.Forms.Padding(0);
this.labelGeneral.Name = "labelGeneral";
this.labelGeneral.Size = new System.Drawing.Size(66, 20);
this.labelGeneral.TabIndex = 0;
this.labelGeneral.Text = "General";
//
// panelGeneral
// panelEdgeDistance
//
this.panelGeneral.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelGeneral.Controls.Add(this.checkMediaPreviews);
this.panelGeneral.Controls.Add(this.checkColumnName);
this.panelGeneral.Controls.Add(this.checkSkipOnLinkClick);
this.panelGeneral.Controls.Add(this.checkNonIntrusive);
this.panelGeneral.Controls.Add(this.labelIdlePause);
this.panelGeneral.Controls.Add(this.comboBoxIdlePause);
this.panelGeneral.Location = new System.Drawing.Point(9, 31);
this.panelGeneral.Name = "panelGeneral";
this.panelGeneral.Size = new System.Drawing.Size(322, 149);
this.panelGeneral.TabIndex = 1;
this.panelEdgeDistance.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelEdgeDistance.Controls.Add(this.trackBarEdgeDistance);
this.panelEdgeDistance.Controls.Add(this.labelEdgeDistanceValue);
this.panelEdgeDistance.Location = new System.Drawing.Point(0, 516);
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 = 18;
//
// checkMediaPreviews
//
this.checkMediaPreviews.AutoSize = true;
this.checkMediaPreviews.Location = new System.Drawing.Point(6, 49);
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 = 2;
this.checkMediaPreviews.Text = "Show Media Previews";
this.checkMediaPreviews.UseVisualStyleBackColor = true;
//
// labelScrollSpeedValue
//
this.labelScrollSpeedValue.Location = new System.Drawing.Point(147, 53);
this.labelScrollSpeedValue.Location = new System.Drawing.Point(145, 4);
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;
//
@@ -415,163 +415,177 @@
//
this.trackBarScrollSpeed.AutoSize = false;
this.trackBarScrollSpeed.LargeChange = 25;
this.trackBarScrollSpeed.Location = new System.Drawing.Point(5, 52);
this.trackBarScrollSpeed.Location = new System.Drawing.Point(3, 3);
this.trackBarScrollSpeed.Maximum = 200;
this.trackBarScrollSpeed.Minimum = 25;
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;
//
// labelScrollSpeed
//
this.labelScrollSpeed.AutoSize = true;
this.labelScrollSpeed.Location = new System.Drawing.Point(3, 36);
this.labelScrollSpeed.Location = new System.Drawing.Point(3, 629);
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
//
this.labelLocation.AutoSize = true;
this.labelLocation.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelLocation.Location = new System.Drawing.Point(6, 395);
this.labelLocation.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
this.labelLocation.Location = new System.Drawing.Point(0, 370);
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
//
this.panelLocation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelLocation.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelLocation.Controls.Add(this.radioLocTL);
this.panelLocation.Controls.Add(this.labelDisplay);
this.panelLocation.Controls.Add(this.trackBarEdgeDistance);
this.panelLocation.Controls.Add(this.comboBoxDisplay);
this.panelLocation.Controls.Add(this.radioLocTR);
this.panelLocation.Controls.Add(this.labelEdgeDistance);
this.panelLocation.Controls.Add(this.radioLocBL);
this.panelLocation.Controls.Add(this.radioLocCustom);
this.panelLocation.Controls.Add(this.radioLocBR);
this.panelLocation.Controls.Add(this.labelEdgeDistanceValue);
this.panelLocation.Location = new System.Drawing.Point(9, 418);
this.panelLocation.Location = new System.Drawing.Point(0, 390);
this.panelLocation.Margin = new System.Windows.Forms.Padding(0);
this.panelLocation.Name = "panelLocation";
this.panelLocation.Size = new System.Drawing.Size(322, 165);
this.panelLocation.TabIndex = 5;
this.panelLocation.Size = new System.Drawing.Size(322, 49);
this.panelLocation.TabIndex = 14;
//
// panelTimer
//
this.panelTimer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelTimer.Controls.Add(this.labelDuration);
this.panelTimer.Controls.Add(this.checkNotificationTimer);
this.panelTimer.Controls.Add(this.tableLayoutDurationButtons);
this.panelTimer.Controls.Add(this.checkTimerCountDown);
this.panelTimer.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelTimer.Controls.Add(this.labelDurationValue);
this.panelTimer.Controls.Add(this.trackBarDuration);
this.panelTimer.Location = new System.Drawing.Point(9, 227);
this.panelTimer.Location = new System.Drawing.Point(0, 281);
this.panelTimer.Margin = new System.Windows.Forms.Padding(0);
this.panelTimer.Name = "panelTimer";
this.panelTimer.Size = new System.Drawing.Size(322, 144);
this.panelTimer.TabIndex = 3;
this.panelTimer.Size = new System.Drawing.Size(322, 36);
this.panelTimer.TabIndex = 11;
//
// labelDuration
//
this.labelDuration.AutoSize = true;
this.labelDuration.Location = new System.Drawing.Point(3, 60);
this.labelDuration.Location = new System.Drawing.Point(3, 268);
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
//
this.labelTimer.AutoSize = true;
this.labelTimer.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelTimer.Location = new System.Drawing.Point(6, 204);
this.labelTimer.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
this.labelTimer.Location = new System.Drawing.Point(0, 187);
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
//
this.labelSize.AutoSize = true;
this.labelSize.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelSize.Location = new System.Drawing.Point(6, 607);
this.labelSize.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
this.labelSize.Location = new System.Drawing.Point(0, 572);
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";
//
// panelMiscellaneous
// panelSize
//
this.panelMiscellaneous.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
this.panelSize.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelMiscellaneous.Controls.Add(this.radioSizeCustom);
this.panelMiscellaneous.Controls.Add(this.radioSizeAuto);
this.panelMiscellaneous.Controls.Add(this.labelScrollSpeedValue);
this.panelMiscellaneous.Controls.Add(this.trackBarScrollSpeed);
this.panelMiscellaneous.Controls.Add(this.labelScrollSpeed);
this.panelMiscellaneous.Location = new System.Drawing.Point(9, 630);
this.panelMiscellaneous.Name = "panelMiscellaneous";
this.panelMiscellaneous.Size = new System.Drawing.Size(322, 92);
this.panelMiscellaneous.TabIndex = 7;
this.panelSize.Controls.Add(this.radioSizeCustom);
this.panelSize.Controls.Add(this.radioSizeAuto);
this.panelSize.Location = new System.Drawing.Point(0, 592);
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 = 20;
//
// durationUpdateTimer
//
this.durationUpdateTimer.Interval = 200;
this.durationUpdateTimer.Tick += new System.EventHandler(this.durationUpdateTimer_Tick);
//
// checkMediaPreviews
// flowPanel
//
this.checkMediaPreviews.AutoSize = true;
this.checkMediaPreviews.Location = new System.Drawing.Point(6, 28);
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.Text = "Show Media Previews";
this.toolTip.SetToolTip(this.checkMediaPreviews, "Shows image and video thumbnails in the notification window.");
this.checkMediaPreviews.UseVisualStyleBackColor = true;
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelGeneral);
this.flowPanel.Controls.Add(this.checkColumnName);
this.flowPanel.Controls.Add(this.checkMediaPreviews);
this.flowPanel.Controls.Add(this.checkSkipOnLinkClick);
this.flowPanel.Controls.Add(this.checkNonIntrusive);
this.flowPanel.Controls.Add(this.labelIdlePause);
this.flowPanel.Controls.Add(this.comboBoxIdlePause);
this.flowPanel.Controls.Add(this.labelTimer);
this.flowPanel.Controls.Add(this.checkNotificationTimer);
this.flowPanel.Controls.Add(this.checkTimerCountDown);
this.flowPanel.Controls.Add(this.labelDuration);
this.flowPanel.Controls.Add(this.panelTimer);
this.flowPanel.Controls.Add(this.tableLayoutDurationButtons);
this.flowPanel.Controls.Add(this.labelLocation);
this.flowPanel.Controls.Add(this.panelLocation);
this.flowPanel.Controls.Add(this.labelDisplay);
this.flowPanel.Controls.Add(this.comboBoxDisplay);
this.flowPanel.Controls.Add(this.labelEdgeDistance);
this.flowPanel.Controls.Add(this.panelEdgeDistance);
this.flowPanel.Controls.Add(this.labelSize);
this.flowPanel.Controls.Add(this.panelSize);
this.flowPanel.Controls.Add(this.labelScrollSpeed);
this.flowPanel.Controls.Add(this.panelScrollSpeed);
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, 678);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// panelScrollSpeed
//
this.panelScrollSpeed.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelScrollSpeed.Controls.Add(this.trackBarScrollSpeed);
this.panelScrollSpeed.Controls.Add(this.labelScrollSpeedValue);
this.panelScrollSpeed.Location = new System.Drawing.Point(0, 642);
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 = 22;
//
// TabSettingsNotifications
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.panelMiscellaneous);
this.Controls.Add(this.labelSize);
this.Controls.Add(this.labelTimer);
this.Controls.Add(this.panelLocation);
this.Controls.Add(this.labelLocation);
this.Controls.Add(this.panelGeneral);
this.Controls.Add(this.labelGeneral);
this.Controls.Add(this.panelTimer);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsNotifications";
this.Size = new System.Drawing.Size(340, 731);
this.Size = new System.Drawing.Size(340, 697);
this.ParentChanged += new System.EventHandler(this.TabSettingsNotifications_ParentChanged);
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
this.tableLayoutDurationButtons.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).EndInit();
this.panelGeneral.ResumeLayout(false);
this.panelGeneral.PerformLayout();
this.panelEdgeDistance.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).EndInit();
this.panelLocation.ResumeLayout(false);
this.panelLocation.PerformLayout();
this.panelTimer.ResumeLayout(false);
this.panelTimer.PerformLayout();
this.panelMiscellaneous.ResumeLayout(false);
this.panelMiscellaneous.PerformLayout();
this.panelSize.ResumeLayout(false);
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.panelScrollSpeed.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
@@ -601,7 +615,7 @@
private System.Windows.Forms.CheckBox checkTimerCountDown;
private System.Windows.Forms.CheckBox checkNotificationTimer;
private System.Windows.Forms.Label labelGeneral;
private System.Windows.Forms.Panel panelGeneral;
private System.Windows.Forms.Panel panelEdgeDistance;
private System.Windows.Forms.Label labelLocation;
private System.Windows.Forms.Panel panelLocation;
private System.Windows.Forms.Panel panelTimer;
@@ -610,11 +624,13 @@
private System.Windows.Forms.TrackBar trackBarScrollSpeed;
private System.Windows.Forms.Label labelScrollSpeed;
private System.Windows.Forms.Label labelSize;
private System.Windows.Forms.Panel panelMiscellaneous;
private System.Windows.Forms.Panel panelSize;
private System.Windows.Forms.Label labelDuration;
private System.Windows.Forms.Timer durationUpdateTimer;
private System.Windows.Forms.RadioButton radioSizeCustom;
private System.Windows.Forms.RadioButton radioSizeAuto;
private System.Windows.Forms.CheckBox checkMediaPreviews;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
private System.Windows.Forms.Panel panelScrollSpeed;
}
}

View File

@@ -26,6 +26,41 @@ namespace TweetDuck.Core.Other.Settings{
this.notification.Activated += notification_Activated;
this.notification.Show();
toolTip.SetToolTip(checkColumnName, "Shows column name each notification originated\r\nfrom in the notification window title.");
toolTip.SetToolTip(checkMediaPreviews, "Shows image and video thumbnails in the notification window.");
toolTip.SetToolTip(checkSkipOnLinkClick, "Skips current notification when a link\r\ninside the notification is clicked.");
toolTip.SetToolTip(checkNonIntrusive, "When not idle and the cursor is within the notification window area,\r\nit will be delayed until the cursor moves away to prevent accidental clicks.");
toolTip.SetToolTip(comboBoxIdlePause, "Pauses new notifications after going idle for a set amount of time.");
toolTip.SetToolTip(checkTimerCountDown, "The notification timer counts down instead of up.");
toolTip.SetToolTip(labelDurationValue, "Milliseconds per character.");
toolTip.SetToolTip(trackBarDuration, toolTip.GetToolTip(labelDurationValue));
toolTip.SetToolTip(radioLocCustom, "Drag the example notification window to the desired location.");
toolTip.SetToolTip(radioSizeAuto, "Notification size is based on the font size and browser zoom level.");
toolTip.SetToolTip(radioSizeCustom, "Resize the example notification window to the desired size.");
checkColumnName.Checked = Config.DisplayNotificationColumn;
checkMediaPreviews.Checked = Config.NotificationMediaPreviews;
checkSkipOnLinkClick.Checked = Config.NotificationSkipOnLinkClick;
checkNonIntrusive.Checked = Config.NotificationNonIntrusiveMode;
comboBoxIdlePause.Items.Add("Disabled");
comboBoxIdlePause.Items.Add("30 seconds");
comboBoxIdlePause.Items.Add("1 minute");
comboBoxIdlePause.Items.Add("2 minutes");
comboBoxIdlePause.Items.Add("5 minutes");
comboBoxIdlePause.SelectedIndex = Math.Max(0, Array.FindIndex(IdlePauseSeconds, val => val == Config.NotificationIdlePauseSeconds));
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
checkTimerCountDown.Checked = Config.NotificationTimerCountDown;
trackBarDuration.SetValueSafe(Config.NotificationDurationValue);
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
switch(Config.NotificationPosition){
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
case TweetNotification.Position.TopRight: radioLocTR.Checked = true; break;
@@ -35,23 +70,6 @@ namespace TweetDuck.Core.Other.Settings{
}
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
switch(Config.NotificationSize){
case TweetNotification.Size.Auto: radioSizeAuto.Checked = true; break;
case TweetNotification.Size.Custom: radioSizeCustom.Checked = true; break;
}
toolTip.SetToolTip(trackBarDuration, toolTip.GetToolTip(labelDurationValue));
trackBarDuration.SetValueSafe(Config.NotificationDurationValue);
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
comboBoxIdlePause.Items.Add("Disabled");
comboBoxIdlePause.Items.Add("30 seconds");
comboBoxIdlePause.Items.Add("1 minute");
comboBoxIdlePause.Items.Add("2 minutes");
comboBoxIdlePause.Items.Add("5 minutes");
comboBoxIdlePause.SelectedIndex = Math.Max(0, Array.FindIndex(IdlePauseSeconds, val => val == Config.NotificationIdlePauseSeconds));
comboBoxDisplay.Items.Add("(Same as TweetDuck)");
foreach(Screen screen in Screen.AllScreens){
@@ -60,50 +78,49 @@ namespace TweetDuck.Core.Other.Settings{
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1, Config.NotificationDisplay);
checkColumnName.Checked = Config.DisplayNotificationColumn;
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
checkTimerCountDown.Checked = Config.NotificationTimerCountDown;
checkMediaPreviews.Checked = Config.NotificationMediaPreviews;
checkSkipOnLinkClick.Checked = Config.NotificationSkipOnLinkClick;
checkNonIntrusive.Checked = Config.NotificationNonIntrusiveMode;
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value+" px";
switch(Config.NotificationSize){
case TweetNotification.Size.Auto: radioSizeAuto.Checked = true; break;
case TweetNotification.Size.Custom: radioSizeCustom.Checked = true; break;
}
trackBarScrollSpeed.SetValueSafe(Config.NotificationScrollSpeed);
labelScrollSpeedValue.Text = trackBarScrollSpeed.Value+"%";
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value+" px";
Disposed += (sender, args) => this.notification.Dispose();
}
public override void OnReady(){
radioLocTL.CheckedChanged += radioLoc_CheckedChanged;
radioLocTR.CheckedChanged += radioLoc_CheckedChanged;
radioLocBL.CheckedChanged += radioLoc_CheckedChanged;
radioLocBR.CheckedChanged += radioLoc_CheckedChanged;
radioLocCustom.Click += radioLocCustom_Click;
checkColumnName.CheckedChanged += checkColumnName_CheckedChanged;
checkMediaPreviews.CheckedChanged += checkMediaPreviews_CheckedChanged;
checkSkipOnLinkClick.CheckedChanged += checkSkipOnLinkClick_CheckedChanged;
checkNonIntrusive.CheckedChanged += checkNonIntrusive_CheckedChanged;
radioSizeAuto.CheckedChanged += radioSize_CheckedChanged;
radioSizeCustom.Click += radioSizeCustom_Click;
comboBoxIdlePause.SelectedValueChanged += comboBoxIdlePause_SelectedValueChanged;
checkNotificationTimer.CheckedChanged += checkNotificationTimer_CheckedChanged;
checkTimerCountDown.CheckedChanged += checkTimerCountDown_CheckedChanged;
trackBarDuration.ValueChanged += trackBarDuration_ValueChanged;
btnDurationShort.Click += btnDurationShort_Click;
btnDurationMedium.Click += btnDurationMedium_Click;
btnDurationLong.Click += btnDurationLong_Click;
checkColumnName.CheckedChanged += checkColumnName_CheckedChanged;
checkNotificationTimer.CheckedChanged += checkNotificationTimer_CheckedChanged;
checkTimerCountDown.CheckedChanged += checkTimerCountDown_CheckedChanged;
checkMediaPreviews.CheckedChanged += checkMediaPreviews_CheckedChanged;
checkSkipOnLinkClick.CheckedChanged += checkSkipOnLinkClick_CheckedChanged;
checkNonIntrusive.CheckedChanged += checkNonIntrusive_CheckedChanged;
comboBoxIdlePause.SelectedValueChanged += comboBoxIdlePause_SelectedValueChanged;
trackBarScrollSpeed.ValueChanged += trackBarScrollSpeed_ValueChanged;
radioLocTL.CheckedChanged += radioLoc_CheckedChanged;
radioLocTR.CheckedChanged += radioLoc_CheckedChanged;
radioLocBL.CheckedChanged += radioLoc_CheckedChanged;
radioLocBR.CheckedChanged += radioLoc_CheckedChanged;
radioLocCustom.Click += radioLocCustom_Click;
comboBoxDisplay.SelectedValueChanged += comboBoxDisplay_SelectedValueChanged;
trackBarEdgeDistance.ValueChanged += trackBarEdgeDistance_ValueChanged;
radioSizeAuto.CheckedChanged += radioSize_CheckedChanged;
radioSizeCustom.Click += radioSizeCustom_Click;
trackBarScrollSpeed.ValueChanged += trackBarScrollSpeed_ValueChanged;
}
private void TabSettingsNotifications_ParentChanged(object sender, EventArgs e){
@@ -153,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

@@ -34,8 +34,13 @@
this.panelSoundNotification = new System.Windows.Forms.Panel();
this.labelVolume = new System.Windows.Forms.Label();
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();
this.panelVolume.SuspendLayout();
this.SuspendLayout();
//
// tbCustomSound
@@ -46,16 +51,15 @@
this.tbCustomSound.Name = "tbCustomSound";
this.tbCustomSound.Size = new System.Drawing.Size(316, 20);
this.tbCustomSound.TabIndex = 0;
this.toolTip.SetToolTip(this.tbCustomSound, "When empty, the default TweetDeck sound notification is used.");
//
// labelVolumeValue
//
this.labelVolumeValue.BackColor = System.Drawing.Color.Transparent;
this.labelVolumeValue.Location = new System.Drawing.Point(147, 84);
this.labelVolumeValue.Location = new System.Drawing.Point(147, 4);
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;
//
@@ -98,66 +102,94 @@
//
this.labelSoundNotification.AutoSize = true;
this.labelSoundNotification.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelSoundNotification.Location = new System.Drawing.Point(6, 8);
this.labelSoundNotification.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelSoundNotification.Location = new System.Drawing.Point(0, 0);
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
//
this.panelSoundNotification.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelSoundNotification.Controls.Add(this.labelVolume);
this.panelSoundNotification.Controls.Add(this.trackBarVolume);
this.panelSoundNotification.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelSoundNotification.Controls.Add(this.btnPlaySound);
this.panelSoundNotification.Controls.Add(this.tbCustomSound);
this.panelSoundNotification.Controls.Add(this.btnResetSound);
this.panelSoundNotification.Controls.Add(this.btnBrowseSound);
this.panelSoundNotification.Controls.Add(this.labelVolumeValue);
this.panelSoundNotification.Location = new System.Drawing.Point(9, 31);
this.panelSoundNotification.Location = new System.Drawing.Point(0, 20);
this.panelSoundNotification.Margin = new System.Windows.Forms.Padding(0);
this.panelSoundNotification.Name = "panelSoundNotification";
this.panelSoundNotification.Size = new System.Drawing.Size(322, 119);
this.panelSoundNotification.TabIndex = 2;
this.panelSoundNotification.Size = new System.Drawing.Size(322, 55);
this.panelSoundNotification.TabIndex = 1;
//
// labelVolume
//
this.labelVolume.AutoSize = true;
this.labelVolume.Location = new System.Drawing.Point(3, 67);
this.labelVolume.Location = new System.Drawing.Point(3, 87);
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
//
this.trackBarVolume.AutoSize = false;
this.trackBarVolume.BackColor = System.Drawing.SystemColors.Control;
this.trackBarVolume.Location = new System.Drawing.Point(3, 83);
this.trackBarVolume.Location = new System.Drawing.Point(3, 3);
this.trackBarVolume.Maximum = 100;
this.trackBarVolume.Name = "trackBarVolume";
this.trackBarVolume.Size = new System.Drawing.Size(148, 30);
this.trackBarVolume.SmallChange = 1;
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);
//
// flowPanel
//
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelSoundNotification);
this.flowPanel.Controls.Add(this.panelSoundNotification);
this.flowPanel.Controls.Add(this.labelVolume);
this.flowPanel.Controls.Add(this.panelVolume);
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, 136);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// panelVolume
//
this.panelVolume.Controls.Add(this.trackBarVolume);
this.panelVolume.Controls.Add(this.labelVolumeValue);
this.panelVolume.Location = new System.Drawing.Point(0, 100);
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 = 3;
//
// volumeUpdateTimer
//
this.volumeUpdateTimer.Interval = 250;
this.volumeUpdateTimer.Tick += new System.EventHandler(this.volumeUpdateTimer_Tick);
//
// TabSettingsSounds
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.panelSoundNotification);
this.Controls.Add(this.labelSoundNotification);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsSounds";
this.Size = new System.Drawing.Size(340, 160);
this.Size = new System.Drawing.Size(340, 154);
this.panelSoundNotification.ResumeLayout(false);
this.panelSoundNotification.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit();
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.panelVolume.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
@@ -173,5 +205,8 @@
private System.Windows.Forms.Label labelVolume;
private System.Windows.Forms.Label labelVolumeValue;
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,29 +4,23 @@ 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;
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+"%";
tbCustomSound.Text = Config.NotificationSoundPath;
tbCustomSound_TextChanged(tbCustomSound, EventArgs.Empty);
Disposed += (sender, args) => soundNotification.Dispose();
}
public override void OnReady(){
@@ -38,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);
if (RefreshCanPlay()){
Config.NotificationSoundPath = tbCustomSound.Text;
Config.NotificationSoundVolume = trackBarVolume.Value;
playSoundNotification();
}
private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){
FormMessage.Error("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, FormMessage.OK);
}
private void btnBrowseSound_Click(object sender, EventArgs e){
@@ -61,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;
@@ -74,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

@@ -24,93 +24,92 @@
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.panelTray = new System.Windows.Forms.Panel();
this.checkTrayHighlight = new System.Windows.Forms.CheckBox();
this.comboBoxTrayType = new System.Windows.Forms.ComboBox();
this.labelTrayIcon = new System.Windows.Forms.Label();
this.labelTray = new System.Windows.Forms.Label();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.panelTray.SuspendLayout();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.flowPanel.SuspendLayout();
this.SuspendLayout();
//
// panelTray
//
this.panelTray.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelTray.Controls.Add(this.checkTrayHighlight);
this.panelTray.Controls.Add(this.comboBoxTrayType);
this.panelTray.Controls.Add(this.labelTrayIcon);
this.panelTray.Location = new System.Drawing.Point(9, 31);
this.panelTray.Name = "panelTray";
this.panelTray.Size = new System.Drawing.Size(322, 76);
this.panelTray.TabIndex = 1;
//
// checkTrayHighlight
//
this.checkTrayHighlight.AutoSize = true;
this.checkTrayHighlight.Location = new System.Drawing.Point(6, 56);
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
this.checkTrayHighlight.Location = new System.Drawing.Point(6, 77);
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.toolTip.SetToolTip(this.checkTrayHighlight, "Highlights the tray icon if there are new tweets.\r\nOnly works for columns with popup or audio notifications.\r\nThe icon resets when the main window is restored.");
this.checkTrayHighlight.UseVisualStyleBackColor = true;
//
// comboBoxTrayType
//
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxTrayType.FormattingEnabled = true;
this.comboBoxTrayType.Location = new System.Drawing.Point(5, 5);
this.comboBoxTrayType.Location = new System.Drawing.Point(5, 25);
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.toolTip.SetToolTip(this.comboBoxTrayType, "Changes behavior of the Tray icon.\r\nRight-click the icon for an action menu.");
this.comboBoxTrayType.TabIndex = 1;
//
// labelTrayIcon
//
this.labelTrayIcon.AutoSize = true;
this.labelTrayIcon.Location = new System.Drawing.Point(3, 38);
this.labelTrayIcon.Location = new System.Drawing.Point(3, 58);
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
//
this.labelTray.AutoSize = true;
this.labelTray.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelTray.Location = new System.Drawing.Point(6, 8);
this.labelTray.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.labelTray.Location = new System.Drawing.Point(0, 0);
this.labelTray.Margin = new System.Windows.Forms.Padding(0);
this.labelTray.Name = "labelTray";
this.labelTray.Size = new System.Drawing.Size(96, 20);
this.labelTray.TabIndex = 0;
this.labelTray.Text = "System Tray";
//
// flowPanel
//
this.flowPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowPanel.Controls.Add(this.labelTray);
this.flowPanel.Controls.Add(this.comboBoxTrayType);
this.flowPanel.Controls.Add(this.labelTrayIcon);
this.flowPanel.Controls.Add(this.checkTrayHighlight);
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, 97);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// TabSettingsTray
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.panelTray);
this.Controls.Add(this.labelTray);
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsTray";
this.Size = new System.Drawing.Size(340, 119);
this.panelTray.ResumeLayout(false);
this.panelTray.PerformLayout();
this.Size = new System.Drawing.Size(340, 115);
this.flowPanel.ResumeLayout(false);
this.flowPanel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelTray;
private System.Windows.Forms.CheckBox checkTrayHighlight;
private System.Windows.Forms.ComboBox comboBoxTrayType;
private System.Windows.Forms.Label labelTrayIcon;
private System.Windows.Forms.Label labelTray;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
}
}

View File

@@ -5,6 +5,9 @@ namespace TweetDuck.Core.Other.Settings{
public TabSettingsTray(){
InitializeComponent();
toolTip.SetToolTip(comboBoxTrayType, "Changes behavior of the Tray icon.\r\nRight-click the icon for an action menu.");
toolTip.SetToolTip(checkTrayHighlight, "Highlights the tray icon if there are new tweets.\r\nOnly works for columns with popup or audio notifications.\r\nThe icon resets when the main window is restored.");
comboBoxTrayType.Items.Add("Disabled");
comboBoxTrayType.Items.Add("Display Icon Only");
comboBoxTrayType.Items.Add("Minimize to Tray");

View File

@@ -7,7 +7,7 @@ using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Other.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Utils;
using TweetDuck.Plugins;
using TweetDuck.Plugins.Enums;
@@ -32,11 +32,10 @@ namespace TweetDuck.Core{
}
}
public event EventHandler PageLoaded;
private readonly ChromiumWebBrowser browser;
private readonly PluginManager plugins;
private readonly MemoryUsageTracker memoryUsageTracker;
private string prevSoundNotificationPath = null;
public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge bridge){
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
@@ -65,15 +64,16 @@ namespace TweetDuck.Core{
this.browser.Dock = DockStyle.None;
this.browser.Location = ControlExtensions.InvisibleLocation;
this.browser.SetupResourceHandler(TweetNotification.AppLogoLink, TweetNotification.AppLogoHandler);
owner.Controls.Add(browser);
this.plugins = plugins;
this.plugins.PluginChangedState += plugins_PluginChangedState;
this.memoryUsageTracker = new MemoryUsageTracker("TDGF_tryRunCleanup");
Program.UserConfig.MuteToggled += UserConfig_MuteToggled;
Program.UserConfig.ZoomLevelChanged += UserConfig_ZoomLevelChanged;
Program.UserConfig.SoundNotificationChanged += UserConfig_SoundNotificationInfoChanged;
}
// setup and management
@@ -95,8 +95,8 @@ namespace TweetDuck.Core{
Program.UserConfig.MuteToggled -= UserConfig_MuteToggled;
Program.UserConfig.ZoomLevelChanged -= UserConfig_ZoomLevelChanged;
Program.UserConfig.SoundNotificationChanged -= UserConfig_SoundNotificationInfoChanged;
memoryUsageTracker.Dispose();
browser.Dispose();
}
@@ -115,8 +115,6 @@ namespace TweetDuck.Core{
private void browser_FrameLoadStart(object sender, FrameLoadStartEventArgs e){
if (e.Frame.IsMain){
memoryUsageTracker.Stop();
if (Program.UserConfig.ZoomLevel != 100){
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
}
@@ -136,19 +134,17 @@ 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();
if (Program.SystemConfig.EnableBrowserGCReload){
memoryUsageTracker.Start(browser, Program.SystemConfig.BrowserMemoryThreshold);
}
if (Program.UserConfig.FirstRun){
ScriptLoader.ExecuteFile(e.Frame, "introduction.js");
}
PageLoaded?.Invoke(this, EventArgs.Empty);
else if (Program.UserConfig.ShowFollowNotification){
ScriptLoader.ExecuteFile(e.Frame, "introduction.follow.js");
}
}
}
@@ -178,21 +174,24 @@ 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){
browser.SetupResourceHandler(soundUrl, hasCustomSound ? SoundNotification.CreateFileHandler(Program.UserConfig.NotificationSoundPath) : null);
prevSoundNotificationPath = Program.UserConfig.NotificationSoundPath;
}
browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Program.UserConfig.NotificationSoundVolume);
}
// external handling
public UpdateHandler CreateUpdateHandler(UpdaterSettings settings){
return new UpdateHandler(browser, settings);
}
public void RefreshMemoryTracker(){
if (Program.SystemConfig.EnableBrowserGCReload){
memoryUsageTracker.Start(browser, Program.SystemConfig.BrowserMemoryThreshold);
}
else{
memoryUsageTracker.Stop();
}
}
public void HideVideoOverlay(bool focus){
if (focus){
browser.GetBrowser().GetHost().SendFocusEvent(true);
@@ -235,6 +234,10 @@ namespace TweetDuck.Core{
browser.ExecuteScriptAsync("TDGF_reloadColumns()");
}
public void PlaySoundNotification(){
browser.ExecuteScriptAsync("TDGF_playSoundNotification()");
}
public void ApplyROT13(){
browser.ExecuteScriptAsync("TDGF_applyROT13()");
}

View File

@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
namespace TweetDuck.Core.Utils{
static class BrowserCache{
private static bool ClearOnExit { get; set; }
public static readonly string CacheFolder = Path.Combine(Program.StoragePath, "Cache");
private static IEnumerable<string> CacheFiles => Directory.EnumerateFiles(CacheFolder);
public static void CalculateCacheSize(Action<Task<long>> callbackBytes){
Task<long> task = new Task<long>(() => {
return CacheFiles.Select(file => {
try{
return new FileInfo(file).Length;
}catch{
return 0L;
}
}).Sum();
});
task.ContinueWith(callbackBytes);
task.Start();
}
public static void SetClearOnExit(){
ClearOnExit = true;
}
public static void Exit(){
if (ClearOnExit){
foreach(string file in CacheFiles){
try{
File.Delete(file);
}catch{
// welp, too bad
}
}
}
}
}
}

View File

@@ -10,19 +10,6 @@ using TweetDuck.Core.Other;
namespace TweetDuck.Core.Utils{
static class BrowserUtils{
public static string HeaderAcceptLanguage{
get{
string culture = Program.Culture.Name;
if (culture == "en"){
return "en-us,en";
}
else{
return culture.ToLower()+",en;q=0.9";
}
}
}
public static string HeaderUserAgent => Program.BrandName+" "+Application.ProductVersion;
public static void SetupCefArgs(IDictionary<string, string> args){
@@ -31,6 +18,10 @@ namespace TweetDuck.Core.Utils{
args["disable-gpu-vsync"] = "1";
}
if (!Program.UserConfig.EnableSmoothScrolling){
args["disable-smooth-scrolling"] = "1";
}
args["disable-pdf-extension"] = "1";
args["disable-plugins-discovery"] = "1";
args["enable-system-flash"] = "0";
@@ -47,6 +38,17 @@ namespace TweetDuck.Core.Utils{
return (ChromiumWebBrowser)browserControl;
}
public static void SetupResourceHandler(this ChromiumWebBrowser browser, string url, IResourceHandler handler){
DefaultResourceHandlerFactory factory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
if (handler == null){
factory.UnregisterHandler(url);
}
else{
factory.RegisterHandler(url, handler);
}
}
private const string TwitterTrackingUrl = "t.co";
public enum UrlCheckResult{
@@ -74,14 +76,42 @@ namespace TweetDuck.Core.Utils{
FormGuide.Show(hash);
}
else{
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);
if (Program.UserConfig.IgnoreTrackingUrlWarning){
goto case UrlCheckResult.Fine;
}
using(FormMessage form = new FormMessage("Blocked URL", "TweetDuck has blocked a tracking url due to privacy concerns. Do you want to visit it anyway?\n"+url, MessageBoxIcon.Warning)){
form.AddButton(FormMessage.No, DialogResult.No, ControlType.Cancel | ControlType.Focused);
form.AddButton(FormMessage.Yes, DialogResult.Yes, ControlType.Accept);
form.AddButton("Always Visit", DialogResult.Ignore);
DialogResult result = form.ShowDialog();
if (result == DialogResult.Ignore){
Program.UserConfig.IgnoreTrackingUrlWarning = true;
Program.UserConfig.Save();
}
if (result == DialogResult.Ignore || result == DialogResult.Yes){
goto case UrlCheckResult.Fine;
}
}
break;

58
Core/Utils/LocaleUtils.cs Normal file
View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace TweetDuck.Core.Utils{
static class LocaleUtils{
// https://cs.chromium.org/chromium/src/third_party/hunspell_dictionaries/
public static IEnumerable<Item> SpellCheckLanguages { get; } = new List<string>{
"af-ZA", "bg-BG", "ca-ES", "cs-CZ", "da-DK", "de-DE",
"el-GR", "en-AU", "en-CA", "en-GB", "en-US", "es-ES",
"et-EE", "fa-IR", "fo-FO", "fr-FR", "he-IL", "hi-IN",
"hr-HR", "hu-HU", "id-ID", "it-IT", "ko" , "lt-LT",
"lv-LV", "nb-NO", "nl-NL", "pl-PL", "pt-BR", "pt-PT",
"ro-RO", "ru-RU", "sk-SK", "sl-SI", "sq" , "sr",
"sv-SE", "ta-IN", "tg-TG", "tr" , "uk-UA", "vi-VN"
}.Select(code => {
string lang = StringUtils.ExtractBefore(code, '-', 2);
return lang == "en" || lang == "pt" ? new Item(code) : new Item(code, lang);
}).OrderBy(code => code).ToList();
// TD.languages.getSupportedTranslationDestinationLanguages() except for "ht", "in", "iw" which are missing/duplicates
public static IEnumerable<Item> TweetDeckTranslationLocales { get; } = new List<string>{
"bg", "ca", "zh-cn", "zh-tw", "cs", "da", "nl",
"en", "et", "fi", "fr", "de", "el", "he", "hi",
"hu", "id", "it", "ja", "ko", "lv", "lt", "no",
"pl", "pt", "ro", "ru", "sk", "sl", "es", "sv",
"th", "tr", "uk", "vi", "ar", "fa"
}.Select(code => new Item(code)).OrderBy(code => code).ToList();
public sealed class Item : IComparable<Item>{
public string Code { get; }
public CultureInfo Info { get; }
public Item(string code, string alt = null){
this.Code = code;
this.Info = CultureInfo.GetCultureInfo(alt ?? code);
}
public override bool Equals(object obj){
return obj is Item other && Code.Equals(other.Code, StringComparison.OrdinalIgnoreCase);
}
public override int GetHashCode(){
return Code.GetHashCode();
}
public override string ToString(){
string capitalizedName = Info.TextInfo.ToTitleCase(Info.NativeName);
return Info.DisplayName == Info.NativeName ? capitalizedName : $"{capitalizedName}, {Info.DisplayName}";
}
public int CompareTo(Item other){
return string.Compare(Info.NativeName, other.Info.NativeName, false, CultureInfo.InvariantCulture);
}
}
}
}

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,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Management;
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{
@@ -63,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;
}
}
@@ -95,20 +96,6 @@ namespace TweetDuck.Core.Utils{
}).Start();
}
public static bool IsChildProcess(int pid){
try{
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = "+pid)){
foreach(ManagementBaseObject obj in searcher.Get()){
return (uint)obj["ParentProcessId"] == CurrentProcessID;
}
}
return false;
}catch{
return false;
}
}
public static void ClipboardStripHtmlStyles(){
if (!Clipboard.ContainsText(TextDataFormat.Html) || !Clipboard.ContainsText(TextDataFormat.UnicodeText)){
return;
@@ -145,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);
@@ -42,7 +81,7 @@ namespace TweetDuck.Data.Serialization{
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)) {
@@ -109,6 +148,14 @@ namespace TweetDuck.Data.Serialization{
}catch(DirectoryNotFoundException){}
}
public static HandleUnknownPropertiesHandler IgnoreProperties(params string[] properties){
return (obj, data) => {
foreach(string property in properties){
data.Remove(property);
}
};
}
private sealed class BasicTypeConverter : ITypeConverter{
bool ITypeConverter.TryWriteType(Type type, object value, out string converted){
switch(Type.GetTypeCode(type)){

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.11.1";
public const string VersionTag = "1.12.4";
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");
@@ -42,7 +43,6 @@ namespace TweetDuck{
private static string ConsoleLogFilePath => Path.Combine(StoragePath, "TD_Console.txt");
public static uint WindowRestoreMessage;
public static uint SubProcessMessage;
private static readonly LockManager LockManager = new LockManager(Path.Combine(StoragePath, ".lock"));
private static bool HasCleanedUp;
@@ -72,7 +72,6 @@ namespace TweetDuck{
Cef.EnableHighDPISupport();
WindowRestoreMessage = NativeMethods.RegisterWindowMessage("TweetDuckRestore");
SubProcessMessage = NativeMethods.RegisterWindowMessage("TweetDuckSubProcess");
if (!WindowsUtils.CheckFolderWritePermission(StoragePath)){
FormMessage.Warning("Permission Error", "TweetDuck does not have write permissions to the storage folder: "+StoragePath, FormMessage.OK);
@@ -119,24 +118,24 @@ 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)){
WindowsUtils.TryDeleteFolderWhenAble(InstallerPath, 8000);
}
BrowserCache.RefreshTimer();
CefSharpSettings.WcfEnabled = false;
CefSettings settings = new CefSettings{
AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage,
UserAgent = BrowserUtils.HeaderUserAgent,
Locale = Arguments.GetValue(Arguments.ArgLocale, string.Empty),
BrowserSubprocessPath = BrandName+".Browser.exe",
CachePath = StoragePath,
UserDataPath = CefDataPath,
LogFile = ConsoleLogFilePath,
#if !DEBUG
LogSeverity = Arguments.HasFlag(Arguments.ArgLogging) ? LogSeverity.Info : LogSeverity.Disable
@@ -193,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);
@@ -212,14 +199,15 @@ namespace TweetDuck{
}
public static void RestartWithArgs(CommandLineArgs args){
FormBrowser browserForm = Application.OpenForms.OfType<FormBrowser>().FirstOrDefault();
if (browserForm == null)return;
FormBrowser browserForm = FormManager.TryFind<FormBrowser>();
if (browserForm != null){
browserForm.ForceClose();
ExitCleanup();
RestartWithArgsInternal(args);
}
}
private static void RestartWithArgsInternal(CommandLineArgs args){
args.AddFlag(Arguments.ArgRestart);

View File

@@ -19,7 +19,7 @@ namespace TweetDuck.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -60,6 +60,16 @@ namespace TweetDuck.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] avatar {
get {
object obj = ResourceManager.GetObject("avatar", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>

View File

@@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="avatar" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\avatar.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

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 TweetDuck on Twitter](https://twitter.com/TryMyAwesomeApp) &nbsp;|&nbsp; [Support via PayPal](https://paypal.me/chylex) &nbsp;|&nbsp; [Support via Patreon](https://www.patreon.com/chylex)
# Build Instructions
@@ -14,10 +14,12 @@ The program was built using Visual Studio 2017. Before opening the solution, ple
After opening the solution, download the following NuGet packages by right-clicking on the solution and selecting **Restore NuGet Packages**, or manually running these commands in the **Package Manager Console**:
```
PM> Install-Package CefSharp.WinForms -Version 57.0.0
PM> Install-Package CefSharp.WinForms -Version 63.0.0-pre01 -Source https://www.myget.org/F/cefsharp/api/v3/index.json
PM> Install-Package Microsoft.VC120.CRT.JetBrains
```
Note that some pre-release builds of CefSharp are not available on NuGet. To correctly restore packages in that case, open **Package Manager Settings**, and add `https://www.myget.org/F/cefsharp/api/v3/index.json` to the list of package sources.
### Debug
It is recommended to create a separate data folder for debugging, otherwise you will not be able to run TweetDuck while debugging the solution.

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

@@ -9,7 +9,7 @@ Emoji keyboard
chylex
[version]
1.4.1
1.4.2
[website]
https://tweetduck.chylex.com

View File

@@ -349,7 +349,7 @@ enabled(){
lastEmojiLength = foundEmoji.length;
}
}
else if (foundNames.length > 1){
else if (foundNames.length > 1 && $(".js-app-content").is(".is-open")){
e.preventDefault();
ele.val(val.substring(0, firstColon)+val.substring(ele[0].selectionStart));
ele[0].selectionEnd = ele[0].selectionStart = firstColon;
@@ -399,6 +399,7 @@ enabled(){
ready(){
this.composeDrawer = $("[data-drawer='compose']");
this.composeInput = $(".js-compose-text", ".js-docked-compose");
this.composeSelector = ".js-compose-text,.js-reply-tweetbox";
this.composePanelScroller = $(".js-compose-scroller", ".js-docked-compose").first().children().first();
this.composePanelScroller.on("scroll", this.composerScrollEvent);
@@ -407,11 +408,12 @@ ready(){
$(document).on("click", this.documentClickEvent);
$(document).on("keydown", this.documentKeyEvent);
$(document).on("uiComposeImageAdded", this.uploadFilesEvent);
this.composeInput.on("keydown", this.composeInputKeyDownEvent);
this.composeInput.on("keypress", this.composeInputKeyPressEvent);
this.composeInput.on("focus", this.composeInputFocusEvent);
this.composeDrawer.on("uiComposeTweetSending", this.composerSendingEvent);
$(document).on("keydown", this.composeSelector, this.composeInputKeyDownEvent);
$(document).on("keypress", this.composeSelector, this.composeInputKeyPressEvent);
$(document).on("focus", this.composeSelector, this.composeInputFocusEvent);
// HTML generation
var convUnicode = function(codePt){
@@ -533,10 +535,11 @@ disabled(){
$(document).off("click", this.documentClickEvent);
$(document).off("keydown", this.documentKeyEvent);
$(document).off("uiComposeImageAdded", this.uploadFilesEvent);
this.composeInput.off("keydown", this.composeInputKeyDownEvent);
this.composeInput.off("keypress", this.composeInputKeyPressEvent);
this.composeInput.off("focus", this.composeInputFocusEvent);
this.composeDrawer.off("uiComposeTweetSending", this.composerSendingEvent);
$(document).off("keydown", this.composeSelector, this.composeInputKeyDownEvent);
$(document).off("keypress", this.composeSelector, this.composeInputKeyPressEvent);
$(document).off("focus", this.composeSelector, this.composeInputFocusEvent);
TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
}

View File

@@ -182,6 +182,12 @@
this.outerHTML = this.innerHTML;
});
html.find("p.link-complex-target").filter(function(){
return $(this).text() === "Show this thread";
}).first().each(function(){
this.id = "tduck-show-thread";
});
let type = tweet.getChirpType();
if (type === "follow"){
@@ -274,7 +280,7 @@
"<html "+Array.prototype.map.call(document.documentElement.attributes, ele => `${ele.name}="${ele.value}"`).join(" ")+"><head>"
];
$(document.head).children("link[href*='css/font.']:first,link[href*='css/app-"+themeName+".']:first,meta[charset],meta[http-equiv]").each(function(){
$(document.head).children("link[rel='stylesheet'],meta[charset]").each(function(){
tags.push($(this)[0].outerHTML);
});
@@ -286,6 +292,7 @@
tags.push(".tweet-context .nbfc { text-overflow: ellipsis !important; white-space: nowrap !important }"); // force ellipsis on long usernames
tags.push(".activity-header { align-items: center !important; margin-bottom: 4px !important }"); // tweak alignment of avatar and text in notifications
tags.push(".activity-header .tweet-timestamp { line-height: unset !important }"); // fix timestamp position in notifications
tags.push("#tduck-show-thread { display: inline-block !important; cursor: pointer }");
if (fontSizeName === "smallest"){
tags.push(".badge-verified:before { width: 13px !important; height: 13px !important; background-position: -223px -98px !important }"); // fix cut off badge icon
@@ -388,7 +395,7 @@
}
else{
tooltipTimer = window.setTimeout(function(){
$TD.displayTooltip(me.attr("data-full-url"), false);
$TD.displayTooltip(me.attr("data-full-url"));
tooltipDisplayed = true;
}, 400);
}
@@ -405,13 +412,13 @@
if (tooltipDisplayed){
tooltipDisplayed = false;
$TD.displayTooltip(null, false);
$TD.displayTooltip(null);
}
},
mousemove: function(e){
if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
$TD.displayTooltip($(this).attr("data-full-url"), false);
$TD.displayTooltip($(this).attr("data-full-url"));
prevMouseX = e.clientX;
prevMouseY = e.clientY;
}
@@ -420,7 +427,7 @@
})();
//
// Block: Bypass t.co when clicking links and media.
// Block: Bypass t.co when clicking/dragging links and media.
//
$(document.body).delegate("a[data-full-url]", "click auxclick", function(e){
if (e.button === 0 || e.button === 1){ // event.which seems to be borked in auxclick
@@ -429,20 +436,15 @@
}
});
if (ensurePropertyExists(TD, "services", "TwitterUser", "prototype", "fromJSONObject")){
const prevFunc = TD.services.TwitterUser.prototype.fromJSONObject;
$(document.body).delegate("a[data-full-url]", "dragstart", function(e){
let url = $(this).attr("data-full-url");
let data = e.originalEvent.dataTransfer;
TD.services.TwitterUser.prototype.fromJSONObject = function(){
let obj = prevFunc.apply(this, arguments);
let e = arguments[0].entities;
if (e && e.url && e.url.urls && e.url.urls.length && e.url.urls[0].expanded_url){
obj.url = e.url.urls[0].expanded_url;
}
return obj;
};
}
data.clearData();
data.setData("text/uri-list", url);
data.setData("text/plain", url);
data.setData("text/html", `<a href="${url}">${url}</a>`);
});
if (ensurePropertyExists(TD, "services", "TwitterMedia", "prototype", "fromMediaEntity")){
const prevFunc = TD.services.TwitterMedia.prototype.fromMediaEntity;
@@ -463,6 +465,66 @@
};
}
//
// Block: Bypass t.co in user profiles and setup a top tier account bamboozle scheme.
//
(function(){
const realDisplayName = "TweetDuck";
const realAvatar = "https://ton.twimg.com/tduck/avatar";
const accountId = "957608948189880320";
if (ensurePropertyExists(TD, "services", "TwitterUser", "prototype", "fromJSONObject")){
const prevFunc = TD.services.TwitterUser.prototype.fromJSONObject;
TD.services.TwitterUser.prototype.fromJSONObject = function(){
let obj = prevFunc.apply(this, arguments);
let e = arguments[0].entities;
if (obj.id === accountId){
obj.name = realDisplayName;
obj.emojifiedName = realDisplayName;
obj.profileImageURL = realAvatar;
obj.url = "https://tweetduck.chylex.com";
obj.entities.url.urls = [{
url: obj.url,
expanded_url: obj.url,
display_url: "tweetduck.chylex.com",
indices: [ 0, 23 ]
}];
}
else if (e && e.url && e.url.urls && e.url.urls.length && e.url.urls[0].expanded_url){
obj.url = e.url.urls[0].expanded_url;
}
return obj;
};
}
if (ensurePropertyExists(TD, "services", "TwitterClient", "prototype", "typeaheadSearch")){
const prevFunc = TD.services.TwitterClient.prototype.typeaheadSearch;
TD.services.TwitterClient.prototype.typeaheadSearch = function(data, onSuccess, onError){
if (data.query && data.query.toLowerCase().endsWith("tweetduck")){
data.query = "TryMyAwesomeApp";
}
return prevFunc.call(this, data, function(result){
for(let user of result.users){
if (user.id_str === accountId){
user.name = realDisplayName;
user.profile_image_url = realAvatar;
user.profile_image_url_https = realAvatar;
break;
}
}
onSuccess.apply(this, arguments);
}, onError);
};
}
})();
//
// Block: Include additional information in context menus.
//
@@ -491,9 +553,33 @@
// 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.
//
@@ -584,7 +670,11 @@
let isReply = !isDetail && (parent.hasClass("js-replies-to") || parent.hasClass("js-replies-before"));
selectedTweet = selectedTweet.clone();
selectedTweet.children().first().addClass($(document.documentElement).attr("class")).css("padding-bottom", "0");
let container = selectedTweet.children().first();
container.addClass($(document.documentElement).attr("class"));
container.addClass($(document.body).attr("class"));
container.css("padding-bottom", "0");
setImportantProperty(selectedTweet.find(".js-tweet-text"), "margin-bottom", "8px");
setImportantProperty(selectedTweet.find(".js-quote-detail"), "margin-bottom", "10px");
@@ -604,7 +694,10 @@
selectedTweet.find("footer").last().prevUntil(":not(.txt-mute)").addBack().remove(); // footer, date, location
}
else{
setImportantProperty(selectedTweet.find(".js-media-preview-container"), "margin-bottom", "10px");
setImportantProperty(selectedTweet.find(".js-media-preview-container").filter(function(){
return $(this).closest(".js-quote-detail").length === 0;
}), "margin-bottom", "10px");
selectedTweet.find("footer").last().remove();
}
@@ -613,6 +706,10 @@
selectedTweet.find(".thread").remove();
}
selectedTweet.find("p.link-complex-target").filter(function(){
return $(this).text() === "Show this thread";
}).first().remove();
selectedTweet.find(".js-poll-link").remove();
selectedTweet.find(".td-screenshot-remove").remove();
@@ -622,9 +719,13 @@
width: tweetWidth+"px"
}).appendTo(document.body);
let realHeight = Math.floor(testTweet.height());
let testTweetAvatar = testTweet.find(".tweet-avatar").first();
let avatarBottom = testTweetAvatar.offset().top+testTweetAvatar.height();
let realHeight = Math.floor(Math.max(testTweet.height(), avatarBottom+10));
testTweet.remove();
selectedTweet.find(".js-stream-item-content").first().css("height", "100vh");
$TD.screenshotTweet(selectedTweet.html(), tweetWidth, realHeight);
}
};
@@ -717,16 +818,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();
},
@@ -750,7 +849,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);
}
};
})();
//
@@ -1119,6 +1228,17 @@
});
});
//
// Block: Override language used for translations.
//
if (ensurePropertyExists(TD, "languages", "getSystemLanguageCode")){
const prevFunc = TD.languages.getSystemLanguageCode;
TD.languages.getSystemLanguageCode = function(returnShortCode){
return returnShortCode ? ($TDX.translationTarget || "en") : prevFunc.apply(this, arguments);
};
}
//
// Block: Setup global function to refresh all columns.
//
@@ -1143,6 +1263,56 @@
}));
};
//
// Block: Revert Like/Follow dialogs being closed after clicking an action.
//
(function(){
const prevSetTimeout = window.setTimeout;
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.
//
@@ -1167,6 +1337,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.
//
@@ -1219,35 +1398,6 @@
});
};
(function(){
var lastActivity = Date.now();
$(document).click(function(e){
lastActivity = Date.now();
});
window.TDGF_tryRunCleanup = function(){
// no recent activity
return false if Date.now()-lastActivity < 15e3;
// no modals are visible
return false if $(".js-modal").is(":visible") || !$(".js-modals-container").is(":empty");
// all columns are in a default state
return false if $("section.js-column").is(".is-shifted-1,.is-shifted-2");
// all textareas are empty
return false if Array.prototype.some.call(document.getElementsByTagName("textarea"), ele => ele.value.length > 0);
// all columns are scrolled to top
return false if Array.prototype.some.call(document.getElementsByClassName("js-column-scroller"), ele => ele.scrollTop > 0);
// cleanup
window.TDGF_reload();
return true;
};
})();
if (window.TD_SESSION && window.TD_SESSION.gc){
var state;
@@ -1301,7 +1451,7 @@
}
//
// Block: Disable default TweetDeck update notification, as the app usually reloads automatically every so often.
// Block: Disable default TweetDeck update notification.
//
onAppReady.push(function(){
let events = $._data(document, "events");

View File

@@ -0,0 +1,91 @@
(function($, $TD){
$(document).one("TD.ready", function(){
let css = $(`
<style>
#td-introduction-modal {
display: block;
}
#td-introduction-modal .mdl {
width: 90%;
max-width: 626px;
height: 244px;
}
#td-introduction-modal .mdl-header-title {
cursor: default;
}
#td-introduction-modal .mdl-content {
padding: 4px 16px 0;
overflow-y: auto;
}
#td-introduction-modal p {
margin: 12px 0;
font-size: 1.4rem;
}
#td-introduction-modal p strong {
font-weight: normal;
text-shadow: 0 0 #000;
}
#td-introduction-modal footer {
padding: 10px 0;
}
</style>`).appendTo(document.head);
let ele = $(`
<div id="td-introduction-modal" class="ovl">
<div class="mdl is-inverted-dark">
<header class="mdl-header">
<h3 class="mdl-header-title">Quick message</h3>
<a href="#" class="mdl-dismiss link-normal-dark"><i class="icon icon-close"></i></a>
</header>
<div class="mdl-inner">
<div class="mdl-content">
<p>Hi! Unfortunately the old <strong>@TryTweetDuck</strong> account was suspended.</p>
<p>If you were following it before, or if you want to keep up with the latest news and updates about TweetDuck, please <a id="td-introduction-follow" href="#">follow @TryMyAwesomeApp</a>.</p>
<p>Thanks for your support!</p>
</div>
<footer class="txt-right">
<button class="btn btn-positive"><span class="label">Close</span</button>
</footer>
</div>
</div>
</div>`).appendTo(".js-app");
let tdUser = null;
let loadTweetDuckUser = (onSuccess, onError) => {
if (tdUser !== null){
onSuccess(tdUser);
}
else{
TD.controller.clients.getPreferredClient().getUsersByIds([ "957608948189880320" ], users => onSuccess(users[0]), onError);
}
};
loadTweetDuckUser(user => tdUser = user);
ele.find("#td-introduction-follow").click(function(){
loadTweetDuckUser(user => {
$(document).trigger("uiShowFollowFromOptions", { userToFollow: user });
$(".js-modals-container").find("header a[rel='user']").each(function(){
this.outerHTML = "TweetDuck";
});
}, () => {
alert("An error occurred when retrieving the account information.");
});
});
ele.find("button, a.mdl-dismiss").click(function(){
ele.fadeOut(200, function(){
$TD.onIntroductionClosed(false, false);
ele.remove();
css.remove();
});
});
});
})($, $TD);

View File

@@ -78,7 +78,7 @@
<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>
<p><a id="td-introduction-follow" href="#">Follow @TryMyAwesomeApp</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>
@@ -102,7 +102,7 @@
onSuccess(tdUser);
}
else{
TD.controller.clients.getPreferredClient().getUsersByIds([ "731137856052269056" ], users => onSuccess(users[0]), onError);
TD.controller.clients.getPreferredClient().getUsersByIds([ "957608948189880320" ], users => onSuccess(users[0]), onError);
}
};
@@ -113,7 +113,7 @@
$(document).trigger("uiShowFollowFromOptions", { userToFollow: user });
$(".js-modals-container").find("header a[rel='user']").each(function(){
this.outerHTML = this.innerText;
this.outerHTML = "TweetDuck";
});
}, () => {
alert("An error occurred when retrieving the account information.");

View File

@@ -62,7 +62,7 @@
}
else{
tooltipTimer = window.setTimeout(function(){
$TD.displayTooltip(url, true);
$TD.displayTooltip(url);
tooltipDisplayed = true;
}, 400);
}
@@ -83,7 +83,7 @@
if (tooltipDisplayed){
tooltipDisplayed = false;
$TD.displayTooltip(null, true);
$TD.displayTooltip(null);
}
});
@@ -92,13 +92,32 @@
var url = e.currentTarget.getAttribute("data-full-url");
return if !url;
$TD.displayTooltip(url, true);
$TD.displayTooltip(url);
prevMouseX = e.clientX;
prevMouseY = e.clientY;
}
});
})();
//
// Block: Work around clipboard HTML formatting.
//
document.addEventListener("copy", function(e){
window.setTimeout($TD.fixClipboard, 0);
});
//
// Block: Setup a handler for 'Show this thread'.
//
(function(){
var btn = document.getElementById("tduck-show-thread");
return if !btn;
btn.addEventListener("click", function(){
$TD.showTweetDetail();
});
})();
//
// Block: Setup a skip button.
//

View File

@@ -3,22 +3,22 @@
<div class="js-tweet tweet">
<header class="tweet-header">
<time class="tweet-timestamp js-timestamp pull-right txt-mute">
<a target="_blank" rel="url" href="https://twitter.com/chylexmc" class="txt-size-variable--12">0s</a>
<a target="_blank" rel="url" href="https://twitter.com/TryMyAwesomeApp" class="txt-size-variable--12">now</a>
</time>
<a target="_blank" rel="user" href="https://twitter.com/chylexmc" class="account-link link-complex block">
<a target="_blank" rel="user" href="https://twitter.com/TryMyAwesomeApp" class="account-link link-complex block">
<div class="obj-left item-img tweet-img">
<img width="48" height="48" alt="chylexmc's avatar" src="https://pbs.twimg.com/profile_images/765161905312980992/AhDP9iY-_normal.jpg" class="tweet-avatar avatar pull-right">
<img width="48" height="48" alt="TryMyAwesomeApp's avatar" src="{avatar}" class="tweet-avatar avatar pull-right">
</div>
<div class="nbfc">
<span class="account-inline txt-ellipsis">
<b class="fullname link-complex-target">chylex</b>
<span class="username txt-mute">@chylexmc</span>
<b class="fullname link-complex-target">TweetDuck</b>
<span class="username txt-mute">@TryMyAwesomeApp</span>
</span>
</div>
</a>
</header>
<div class="tweet-body">
<p class="js-tweet-text tweet-text with-linebreaks">This is an example tweet, which lets you test the location and duration of popup notifications.</p>
<p class="js-tweet-text tweet-text with-linebreaks">Here you can see the position and appearance of desktop notifications.<br><br>For location and size, you can pick a preset, or select <strong>Custom</strong> and then freely move or resize the window.</p>
</div>
</div>
</div>

View File

@@ -268,3 +268,22 @@ html[data-td-font='smallest'] .tweet-detail-wrapper .badge-verified:before {
.is-options-open .column-type-icon {
bottom: 27px !important;
}
/********************************************/
/* Fix cut off usernames in Messages column */
/********************************************/
.column-type-message.is-shifted-1 .column-title-container {
height: 100%;
border-bottom-color: transparent;
}
#tduck .column-type-message.is-shifted-1 .column-title-items {
height: 100%;
margin-left: 4px !important;
padding-top: 1px;
}
.column-type-message.is-shifted-1 .username {
vertical-align: bottom;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

BIN
Resources/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.props')" />
<Import Project="packages\CefSharp.Common.57.0.0\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.57.0.0\build\CefSharp.Common.props')" />
<Import Project="packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.props')" />
<Import Project="packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -102,8 +102,8 @@
<Compile Include="Core\Handling\General\FileDialogHandler.cs" />
<Compile Include="Core\Handling\KeyboardHandlerBrowser.cs" />
<Compile Include="Core\Handling\KeyboardHandlerNotification.cs" />
<Compile Include="Core\Handling\RequestHandlerBase.cs" />
<Compile Include="Core\Handling\RequestHandlerBrowser.cs" />
<Compile Include="Core\Handling\General\RequestHandlerBase.cs" />
<Compile Include="Core\Handling\ResourceHandlerNotification.cs" />
<Compile Include="Core\Notification\Example\FormNotificationExample.cs">
<SubType>Form</SubType>
@@ -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>
@@ -190,13 +190,18 @@
<Compile Include="Core\Other\Settings\Dialogs\DialogSettingsRestart.Designer.cs">
<DependentUpon>DialogSettingsRestart.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\Management\BrowserProcesses.cs" />
<Compile Include="Core\Other\Settings\TabSettingsFeedback.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Core\Other\Settings\TabSettingsFeedback.Designer.cs">
<DependentUpon>TabSettingsFeedback.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\Settings\TabSettingsLocales.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Core\Other\Settings\TabSettingsLocales.Designer.cs">
<DependentUpon>TabSettingsLocales.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\Settings\TabSettingsTray.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -204,11 +209,11 @@
<DependentUpon>TabSettingsTray.cs</DependentUpon>
</Compile>
<Compile Include="Core\TweetDeckBrowser.cs" />
<Compile Include="Core\Utils\LocaleUtils.cs" />
<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>
@@ -248,7 +253,6 @@
<Compile Include="Data\Serialization\SingleTypeConverter.cs" />
<Compile Include="Data\TwoKeyDictionary.cs" />
<Compile Include="Data\WindowState.cs" />
<Compile Include="Core\Other\Management\MemoryUsageTracker.cs" />
<Compile Include="Core\Utils\WindowsUtils.cs" />
<Compile Include="Core\Bridge\TweetDeckBridge.cs" />
<Compile Include="Core\Other\FormSettings.cs">
@@ -276,6 +280,11 @@
<Compile Include="Plugins\Events\PluginErrorEventArgs.cs" />
<Compile Include="Plugins\PluginManager.cs" />
<Compile Include="Plugins\PluginScriptGenerator.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Reporter.cs" />
<Compile Include="Updates\FormUpdateDownload.cs">
<SubType>Form</SubType>
@@ -289,7 +298,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" />
@@ -297,11 +306,6 @@
<Compile Include="Updates\UpdateInfo.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Resources\ScriptLoader.cs" />
<Compile Include="Updates\UpdateEventArgs.cs" />
<Compile Include="Updates\UpdaterSettings.cs" />
@@ -333,14 +337,10 @@
<DependentUpon>FormBrowser.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Core\Other\FormAbout.resx">
<DependentUpon>FormAbout.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
@@ -359,7 +359,9 @@
<Folder Include="Resources\Plugins\" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\avatar.png" />
<Content Include="Resources\Scripts\code.js" />
<Content Include="Resources\Scripts\introduction.follow.js" />
<Content Include="Resources\Scripts\introduction.js" />
<Content Include="Resources\Scripts\notification.js" />
<Content Include="Resources\Scripts\pages\error.html" />
@@ -373,10 +375,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>
@@ -398,19 +396,25 @@ ren "$(TargetDir)LICENSE.md" "LICENSE.txt"
xcopy "$(ProjectDir)bld\Resources\CEFSHARP-LICENSE.txt" "$(TargetDir)" /Y
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcp120.dll" "$(TargetDir)" /Y
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcr120.dll" "$(TargetDir)" /Y
rmdir "$(TargetDir)scripts" /S /Q
mkdir "$(TargetDir)scripts"
xcopy "$(ProjectDir)Resources\Scripts\*" "$(TargetDir)scripts\" /E /Y
rmdir "$(TargetDir)plugins" /S /Q
mkdir "$(TargetDir)plugins"
mkdir "$(TargetDir)plugins\official"
mkdir "$(TargetDir)plugins\user"
xcopy "$(ProjectDir)Resources\Plugins\*" "$(TargetDir)plugins\official\" /E /Y
rmdir "$(TargetDir)plugins\official\.debug" /S /Q
del "$(TargetDir)plugins\official\emoji-keyboard\emoji-instructions.txt"
rmdir "$(ProjectDir)bin\Debug"
rmdir "$(ProjectDir)bin\Release"
rmdir "$(TargetDir)plugins\official\.debug" /S /Q
del "$(TargetDir)plugins\official\emoji-keyboard\emoji-instructions.txt"
attrib +R "$(TargetDir)locales\en-US.pak"
del /Q /A:-R "$(TargetDir)locales\*.pak"
attrib -R "$(TargetDir)locales\en-US.pak"
if $(ConfigurationName) == Debug (
rmdir "$(TargetDir)plugins\official\.debug" /S /Q
@@ -420,21 +424,6 @@ if $(ConfigurationName) == Debug (
powershell -ExecutionPolicy Unrestricted -File "$(ProjectDir)Resources\PostBuild.ps1" "$(TargetDir)\"</PostBuildEvent>
</PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\cef.redist.x64.3.2987.1601\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2987.1601\build\cef.redist.x64.targets'))" />
<Error Condition="!Exists('packages\cef.redist.x86.3.2987.1601\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2987.1601\build\cef.redist.x86.targets'))" />
<Error Condition="!Exists('packages\CefSharp.Common.57.0.0\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.57.0.0\build\CefSharp.Common.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.57.0.0\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.57.0.0\build\CefSharp.Common.targets'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.props'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.targets'))" />
</Target>
<Import Project="packages\cef.redist.x64.3.2987.1601\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2987.1601\build\cef.redist.x64.targets')" />
<Import Project="packages\cef.redist.x86.3.2987.1601\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2987.1601\build\cef.redist.x86.targets')" />
<Import Project="packages\CefSharp.Common.57.0.0\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.57.0.0\build\CefSharp.Common.targets')" />
<Import Project="packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.57.0.0\build\CefSharp.WinForms.targets')" />
<Target Name="AfterBuild" Condition="$(ConfigurationName) == Release">
<Exec Command="del &quot;$(TargetDir)*.pdb&quot;" />
<Exec Command="del &quot;$(TargetDir)*.xml&quot;" />
@@ -445,4 +434,19 @@ powershell -ExecutionPolicy Unrestricted -File "$(ProjectDir)Resources\PostBuild
<PropertyGroup>
<PreBuildEvent>powershell Get-Process TweetDuck.Browser -ErrorAction SilentlyContinue ^| Where-Object {$_.Path -eq '$(TargetDir)TweetDuck.Browser.exe'} ^| Stop-Process; Exit 0</PreBuildEvent>
</PropertyGroup>
<Import Project="packages\cef.redist.x64.3.3239.1716\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.3239.1716\build\cef.redist.x64.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\cef.redist.x64.3.3239.1716\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.3239.1716\build\cef.redist.x64.targets'))" />
<Error Condition="!Exists('packages\cef.redist.x86.3.3239.1716\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.3239.1716\build\cef.redist.x86.targets'))" />
<Error Condition="!Exists('packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.targets'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.props'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.targets'))" />
</Target>
<Import Project="packages\cef.redist.x86.3.3239.1716\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.3239.1716\build\cef.redist.x86.targets')" />
<Import Project="packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.63.0.0-pre01\build\CefSharp.Common.targets')" />
<Import Project="packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.63.0.0-pre01\build\CefSharp.WinForms.targets')" />
</Project>

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

Binary file not shown.

View File

@@ -59,7 +59,60 @@ Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\Cache"
Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\GPUCache"
[InstallDelete]
Type: files; Name: "{app}\plugins\official\emoji-keyboard\emoji-instructions.txt"
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"
Type: files; Name: "{app}\locales\bg.pak"
Type: files; Name: "{app}\locales\bn.pak"
Type: files; Name: "{app}\locales\ca.pak"
Type: files; Name: "{app}\locales\cs.pak"
Type: files; Name: "{app}\locales\da.pak"
Type: files; Name: "{app}\locales\de.pak"
Type: files; Name: "{app}\locales\el.pak"
Type: files; Name: "{app}\locales\en-GB.pak"
Type: files; Name: "{app}\locales\es-419.pak"
Type: files; Name: "{app}\locales\es.pak"
Type: files; Name: "{app}\locales\et.pak"
Type: files; Name: "{app}\locales\fa.pak"
Type: files; Name: "{app}\locales\fi.pak"
Type: files; Name: "{app}\locales\fil.pak"
Type: files; Name: "{app}\locales\fr.pak"
Type: files; Name: "{app}\locales\gu.pak"
Type: files; Name: "{app}\locales\he.pak"
Type: files; Name: "{app}\locales\hi.pak"
Type: files; Name: "{app}\locales\hr.pak"
Type: files; Name: "{app}\locales\hu.pak"
Type: files; Name: "{app}\locales\id.pak"
Type: files; Name: "{app}\locales\it.pak"
Type: files; Name: "{app}\locales\ja.pak"
Type: files; Name: "{app}\locales\kn.pak"
Type: files; Name: "{app}\locales\ko.pak"
Type: files; Name: "{app}\locales\lt.pak"
Type: files; Name: "{app}\locales\lv.pak"
Type: files; Name: "{app}\locales\ml.pak"
Type: files; Name: "{app}\locales\mr.pak"
Type: files; Name: "{app}\locales\ms.pak"
Type: files; Name: "{app}\locales\nb.pak"
Type: files; Name: "{app}\locales\nl.pak"
Type: files; Name: "{app}\locales\pl.pak"
Type: files; Name: "{app}\locales\pt-BR.pak"
Type: files; Name: "{app}\locales\pt-PT.pak"
Type: files; Name: "{app}\locales\ro.pak"
Type: files; Name: "{app}\locales\ru.pak"
Type: files; Name: "{app}\locales\sk.pak"
Type: files; Name: "{app}\locales\sl.pak"
Type: files; Name: "{app}\locales\sr.pak"
Type: files; Name: "{app}\locales\sv.pak"
Type: files; Name: "{app}\locales\sw.pak"
Type: files; Name: "{app}\locales\ta.pak"
Type: files; Name: "{app}\locales\te.pak"
Type: files; Name: "{app}\locales\th.pak"
Type: files; Name: "{app}\locales\tr.pak"
Type: files; Name: "{app}\locales\uk.pak"
Type: files; Name: "{app}\locales\vi.pak"
Type: files; Name: "{app}\locales\zh-CN.pak"
Type: files; Name: "{app}\locales\zh-TW.pak"
[Code]
function TDIsUninstallable: Boolean; forward;

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)' == '' ">AnyCPU</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

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<?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)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{72473763-4B9D-4FB6-A923-9364B2680F06}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="cef.redist.x64" version="3.2987.1601" targetFramework="net452" xmlns="" />
<package id="cef.redist.x86" version="3.2987.1601" targetFramework="net452" xmlns="" />
<package id="CefSharp.Common" version="57.0.0" targetFramework="net452" xmlns="" />
<package id="CefSharp.WinForms" version="57.0.0" targetFramework="net452" xmlns="" />
<package id="cef.redist.x64" version="3.3239.1716" targetFramework="net452" xmlns="" />
<package id="cef.redist.x86" version="3.3239.1716" targetFramework="net452" xmlns="" />
<package id="CefSharp.Common" version="63.0.0-pre01" targetFramework="net452" xmlns="" />
<package id="CefSharp.WinForms" version="63.0.0-pre01" targetFramework="net452" xmlns="" />
<package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net452" xmlns="" />
</packages>

View File

@@ -1,12 +1,9 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using CefSharp;
using CefSharp.BrowserSubprocess;
namespace TweetDuck.Browser{
static class Program{
internal const string Version = "1.2.1.0";
internal const string Version = "1.4.0.0";
private static int Main(string[] args){
SubProcess.EnableHighDPISupport();
@@ -15,32 +12,13 @@ namespace TweetDuck.Browser{
string type = Array.Find(args, arg => arg.StartsWith(typePrefix, StringComparison.OrdinalIgnoreCase)).Substring(typePrefix.Length);
if (type == "renderer"){
using(RendererProcess subProcess = new RendererProcess(args)){
using(SubProcess subProcess = new SubProcess(args)){
return subProcess.Run();
}
}
else return SubProcess.ExecuteProcess();
}
private sealed class RendererProcess : SubProcess{
// ReSharper disable once ParameterTypeCanBeEnumerable.Local
public RendererProcess(string[] args) : base(args){}
public override void OnBrowserCreated(CefBrowserWrapper wrapper){
base.OnBrowserCreated(wrapper);
using(Process me = Process.GetCurrentProcess()){
PostMessage(HWND_BROADCAST, RegisterWindowMessage("TweetDuckSubProcess"), new UIntPtr((uint)me.Id), new IntPtr(wrapper.BrowserId));
else{
return SubProcess.ExecuteProcess();
}
}
}
private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xFFFF);
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern uint RegisterWindowMessage(string messageName);
}
}

View File

@@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{B10B0017-819E-4F71-870F-8256B36A26AA}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>TweetDuck.Browser</RootNamespace>
@@ -24,9 +24,9 @@
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="CefSharp, Version=57.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138" />
<Reference Include="CefSharp.BrowserSubprocess.Core">
<HintPath>..\packages\CefSharp.Common.57.0.0\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath>
<Reference Include="CefSharp.BrowserSubprocess.Core, Version=63.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CefSharp.Common.63.0.0-pre01\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>

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

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{A958FA7A-4A2C-42A7-BFA0-159343483F4E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>

View File

@@ -75,6 +75,7 @@ namespace TweetDuck.Video{
}
private void pipe_DataIn(object sender, DuplexPipe.PipeReadEventArgs e){
Invoke(new Action(() => {
switch(e.Key){
case "key":
HandleKey((Keys)int.Parse(e.Data, NumberStyles.Integer));
@@ -84,6 +85,7 @@ namespace TweetDuck.Video{
StopVideo();
break;
}
}));
}
private void player_PlayStateChange(int newState){
@@ -102,8 +104,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.1";
// 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;
}

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<?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)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{278B2D11-402D-44B6-B6A1-8FA67DB65565}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>TweetDuck.Video</RootNamespace>