From 4bd43705c2831bd9f003a52b09a05e6a6ed14fbf Mon Sep 17 00:00:00 2001 From: briandunnington Date: Wed, 29 Jul 2009 05:29:21 +0000 Subject: [PATCH] Beta19 release --- .../Javascript/GrowlFlashConnector.swf | Bin 29069 -> 30507 bytes .../NET/libraries/Growl.Connector.dll | Bin 61440 -> 61440 bytes .../NET/libraries/Growl.CoreLibrary.dll | Bin 24576 -> 24576 bytes .../libraries/Growl.CoreLibrary.dll | Bin 24576 -> 24576 bytes .../libraries/Growl.DisplayStyle.dll | Bin 49152 -> 49152 bytes .../Properties/AssemblyInfo.cs | 2 +- Growl/Growl.CoreLibrary/ImageConverter.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- Growl/Growl.Daemon/Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- Growl/Growl/AddComputer.cs | 3 +- Growl/Growl/ChooseForwarding.cs | 8 +- Growl/Growl/Growl.csproj | 3 + Growl/Growl/MainForm.cs | 19 +- Growl/Growl/Properties/AssemblyInfo.cs | 4 +- Growl/Growl/Properties/Resources.Designer.cs | 126 +++++++++++++ Growl/Growl/Properties/Resources.resx | 56 ++++++ Growl/Growl/UI/EmailForwardInputs.Designer.cs | 177 ++++++++++++++++++ Growl/Growl/UI/EmailForwardInputs.cs | 73 ++++++-- Growl/Growl/UI/ForwardDestinationInputs.cs | 5 +- Growl/Growl/UI/ForwardListBox.cs | 34 ++-- Growl/Growl/UI/ForwardListView.cs | 76 +++++--- Growl/Growl/UI/ProwlForwardInputs.cs | 2 + .../Growl/UI/TwitterForwardInputs.Designer.cs | 2 +- Growl/Growl/UI/TwitterForwardInputs.cs | 8 +- Growl/Growl/_source/ActivityMonitor.cs | 2 +- Growl/Growl/_source/ApplicationMain.cs | 12 +- Growl/Growl/_source/AutoUpdate/Updater.cs | 6 +- Growl/Growl/_source/Controller.cs | 60 +----- Growl/Growl/_source/Display.cs | 3 +- Growl/Growl/_source/DisplayStyleManager.cs | 78 +++++--- .../Growl/_source/EmailForwardDestination.cs | 27 ++- Growl/Growl/_source/ForwardDestination.cs | 4 + .../_source/ForwardDestinationManager.cs | 2 +- .../_source/Installation/InstallDisplay.cs | 4 +- .../Growl/_source/ProwlForwardDestination.cs | 127 ++++++------- Growl/Growl/_source/Subscription.cs | 42 +++-- .../_source/TwitterForwardDestination.cs | 59 +++++- Growl/Growl/_source/Utility.cs | 20 +- Growl/Growl/_source/WebClientEx.cs | 24 +++ Growl/Growl/release_notes.txt | 14 ++ Growl/Growl/update.manifest | 4 +- Growl/Test App/Form1.cs | 8 +- .../Windows Deployment.vdproj | 6 +- 50 files changed, 830 insertions(+), 290 deletions(-) create mode 100644 Growl/Growl/_source/WebClientEx.cs diff --git a/Growl Connectors/Javascript/GrowlFlashConnector.swf b/Growl Connectors/Javascript/GrowlFlashConnector.swf index 122217622107644d0c5a87b18f9e47e76bd4cc94..e4d8ed74701753e692ce0f03ca2750c873051df0 100644 GIT binary patch literal 30507 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 mRW-f7zP5h8 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 S@9DNrh<$@!U~$hNCjSRUdZBs% diff --git a/Growl Connectors/NET/libraries/Growl.Connector.dll b/Growl Connectors/NET/libraries/Growl.Connector.dll index d45297f3170754283a7cfff9d245cbb56cf94891..fe7c900a3a1434b3fc455f09294a64418f4fdd78 100644 GIT binary patch delta 249 zcmVCO}_Nk*%4EQRniEZAR_3nH2nJT?@e6%LSAy`+u9tawNiBd^1*v)1SxNw`!RqAo$c#sSvv#^i_ceAo=ORwOI$*qf2ngY- zhygCM&=6di5b@z9ee!ODOrIhAqHVi3KC?Wk2O7GG;$fgdEfy{asR)qUvAenM(%dHT&-yiM$QVOhj7Jl*KG zWPu81%L_#3qEd}G&5>oL6k~xbU*z-n-O*ejdh5#Xi=l21#;aNaX2050cbOR|qccZ< z#sLVk&=6di5Cbn;xAnQfK%U(%J07C?%da!5Ud<+2+vyISc0RcF(_t6O+t~qe| diff --git a/Growl Connectors/NET/libraries/Growl.CoreLibrary.dll b/Growl Connectors/NET/libraries/Growl.CoreLibrary.dll index 758e8182094bef389fe25cdfb682a295a1aeedbd..e765829818cc9cbfd609928603fcba42624d0613 100644 GIT binary patch delta 250 zcmVxTwt1$(E#R(1?q6ZoOR>6wek+&f^B^ubN&mWXNnwC=z<0b@*;D;flK@6 z@D3nXhjfmteJO@HOYJU|iJTLq8w^I*A&#&K_!>YXV$130&di>msg2_jrq0oz7oPKr zq74DLv(OMo9S|xH5*IlGyGyM>9%oy^L=m$nE=L6cIg@ZR#4L+iZb|?E00062003(M z002xx002xh002@`L{p}n?h`_BzE8BNTJZXaL%y?MG%O4O6SIv#Z29&%A@ A`v3p{ delta 250 zcmV{4On%*;5rvT8WTPfQi#c6-0{K#aKh2gs<}(P#pPGZ=7ofaY=H`5m`9n`mPtv-Y z02u)rv(OMo9T0R(p?PF2Wk!XBzS%0|y$rJ`E=L6cIFoQQ#4LcgU`hZ000062003(M z002xx002xh002@`L{nR?$axwLEH4!^G%O4O60?m!Z29?>yq AegFUf diff --git a/Growl Extras/Growl Display SDK/libraries/Growl.CoreLibrary.dll b/Growl Extras/Growl Display SDK/libraries/Growl.CoreLibrary.dll index 758e8182094bef389fe25cdfb682a295a1aeedbd..e765829818cc9cbfd609928603fcba42624d0613 100644 GIT binary patch delta 250 zcmVxTwt1$(E#R(1?q6ZoOR>6wek+&f^B^ubN&mWXNnwC=z<0b@*;D;flK@6 z@D3nXhjfmteJO@HOYJU|iJTLq8w^I*A&#&K_!>YXV$130&di>msg2_jrq0oz7oPKr zq74DLv(OMo9S|xH5*IlGyGyM>9%oy^L=m$nE=L6cIg@ZR#4L+iZb|?E00062003(M z002xx002xh002@`L{p}n?h`_BzE8BNTJZXaL%y?MG%O4O6SIv#Z29&%A@ A`v3p{ delta 250 zcmV{4On%*;5rvT8WTPfQi#c6-0{K#aKh2gs<}(P#pPGZ=7ofaY=H`5m`9n`mPtv-Y z02u)rv(OMo9T0R(p?PF2Wk!XBzS%0|y$rJ`E=L6cIFoQQ#4LcgU`hZ000062003(M z002xx002xh002@`L{nR?$axwLEH4!^G%O4O60?m!Z29?>yq AegFUf diff --git a/Growl Extras/Growl Display SDK/libraries/Growl.DisplayStyle.dll b/Growl Extras/Growl Display SDK/libraries/Growl.DisplayStyle.dll index acaeaaa6f57053d93e85e8e87d1e8b59100b8ba5..8efde736f14027235567473d517774f2c7b229c6 100644 GIT binary patch delta 108 zcmZo@U~Xt&p3uSE9hJAS`){X!jZ@%Gi!&L{8;@DW?w|1E<>nb(^EnwUCtFN8p#xOo z#Q+3MK%5K25=()2Dg#4MuuHIur%K}QyHnjKMsj?TmQV=atTQ!%n^Aak?}9=`M$66r I7c$BL0LfG)yZ`_I delta 108 zcmZo@U~Xt&p3uSExFca>_uo!|;D6?Koqc?Lr?hBn&ECKC@8%g@^EnwUCR3p*$Z!?$eMk%+vlPBNbtTQ!%n^9 0) @@ -38,9 +39,10 @@ private void ChooseForwarding_Load(object sender, EventArgs e) Dictionary computers = new Dictionary(); foreach (ForwardDestination fc in this.controller.ForwardDestinations.Values) { - bool enabled = this.prefs.PrefForwardCustomList.Contains(fc.Description); + bool enabled = this.prefs.PrefForwardCustomList.Contains(fc.Key); ForwardDestination clone = fc.Clone(); - fc.Enabled = enabled; + clone.Key = fc.Key; + clone.Enabled = enabled; computers.Add(clone.Description, clone); } this.forwardListView1.Computers = computers; @@ -80,7 +82,7 @@ private void buttonSave_Click(object sender, EventArgs e) List computers = new List(); foreach (ForwardDestination fc in this.forwardListView1.Computers.Values) { - if (fc.Enabled) computers.Add(fc.Description); + if (fc.Enabled) computers.Add(fc.Key); } this.prefs.PrefForwardCustomList = computers; diff --git a/Growl/Growl/Growl.csproj b/Growl/Growl/Growl.csproj index 478d5a8..6741872 100644 --- a/Growl/Growl/Growl.csproj +++ b/Growl/Growl/Growl.csproj @@ -332,6 +332,9 @@ + + Component + diff --git a/Growl/Growl/MainForm.cs b/Growl/Growl/MainForm.cs index abec0ca..f9d95d6 100644 --- a/Growl/Growl/MainForm.cs +++ b/Growl/Growl/MainForm.cs @@ -796,6 +796,10 @@ private void checkBoxEnableForwarding_CheckedChanged(object sender, EventArgs e) { Properties.Settings.Default.AllowForwarding = this.checkBoxEnableForwarding.Checked; Properties.Settings.Default.Save(); + + this.forwardListView.AllDisabled = !Properties.Settings.Default.AllowForwarding; + this.forwardListView.Refresh(); + //this.forwardListView.SelectedIndices.Clear(); //this.forwardListView.Enabled = this.checkBoxEnableForwarding.Checked; //this.buttonAddComputer.Enabled = this.checkBoxEnableForwarding.Checked; @@ -1059,14 +1063,21 @@ private void checkBoxEnableSubscriptions_CheckedChanged(object sender, EventArgs { Properties.Settings.Default.EnableSubscriptions = this.checkBoxEnableSubscriptions.Checked; Properties.Settings.Default.Save(); - //this.subscribedListView.SelectedIndices.Clear(); - //this.subscribedListView.Enabled = this.checkBoxEnableSubscriptions.Checked; - //this.buttonSubscribe.Enabled = this.checkBoxEnableSubscriptions.Checked; - this.buttonUnsubscribe.Enabled = false; + foreach (Subscription subscription in this.controller.Subscriptions.Values) { subscription.Allowed = this.checkBoxEnableSubscriptions.Checked; } + + this.subscribedListView.AllDisabled = !Properties.Settings.Default.EnableSubscriptions; + this.subscribedListView.Refresh(); + + if (!this.checkBoxEnableSubscriptions.Checked) + this.buttonUnsubscribe.Enabled = false; + else + { + if (this.subscribedListView.SelectedIndices != null && this.subscribedListView.SelectedIndices.Count > 0) this.buttonUnsubscribe.Enabled = true; + } } private void subscribedListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) diff --git a/Growl/Growl/Properties/AssemblyInfo.cs b/Growl/Growl/Properties/AssemblyInfo.cs index 7f36707..a8de195 100644 --- a/Growl/Growl/Properties/AssemblyInfo.cs +++ b/Growl/Growl/Properties/AssemblyInfo.cs @@ -33,6 +33,6 @@ // Revision // [assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.0.18")] -[assembly: AssemblyInformationalVersion("2.0b18")] +[assembly: AssemblyFileVersion("2.0.0.19")] +[assembly: AssemblyInformationalVersion("2.0b19")] [assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Growl/Growl/Properties/Resources.Designer.cs b/Growl/Growl/Properties/Resources.Designer.cs index 49549c6..6e56732 100644 --- a/Growl/Growl/Properties/Resources.Designer.cs +++ b/Growl/Growl/Properties/Resources.Designer.cs @@ -226,6 +226,132 @@ internal static string AddComputer_PortLabel { } } + /// + /// Looks up a localized string similar to [Any Priority]. + /// + internal static string AddEmail_AnyPriority { + get { + return ResourceManager.GetString("AddEmail_AnyPriority", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to edit. + /// + internal static string AddEmail_EditSMTP { + get { + return ResourceManager.GetString("AddEmail_EditSMTP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Email Address:. + /// + internal static string AddEmail_EmailAddressLabel { + get { + return ResourceManager.GetString("AddEmail_EmailAddressLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only forward when priority is at least:. + /// + internal static string AddEmail_MinimumPriorityLabel { + get { + return ResourceManager.GetString("AddEmail_MinimumPriorityLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description:. + /// + internal static string AddEmail_NameLabel { + get { + return ResourceManager.GetString("AddEmail_NameLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only forward when idle or away. + /// + internal static string AddEmail_OnlyWhenIdle { + get { + return ResourceManager.GetString("AddEmail_OnlyWhenIdle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to done. + /// + internal static string AddEmail_SMTPDone { + get { + return ResourceManager.GetString("AddEmail_SMTPDone", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password:. + /// + internal static string AddEmail_SMTPPasswordLabel { + get { + return ResourceManager.GetString("AddEmail_SMTPPasswordLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Port:. + /// + internal static string AddEmail_SMTPPortLabel { + get { + return ResourceManager.GetString("AddEmail_SMTPPortLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server:. + /// + internal static string AddEmail_SMTPServerLabel { + get { + return ResourceManager.GetString("AddEmail_SMTPServerLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SMTP Settings:. + /// + internal static string AddEmail_SMTPSettingsLabel { + get { + return ResourceManager.GetString("AddEmail_SMTPSettingsLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use Authentication. + /// + internal static string AddEmail_SMTPUseAuthentication { + get { + return ResourceManager.GetString("AddEmail_SMTPUseAuthentication", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Username:. + /// + internal static string AddEmail_SMTPUsernameLabel { + get { + return ResourceManager.GetString("AddEmail_SMTPUsernameLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use SSL. + /// + internal static string AddEmail_SMTPUseSSL { + get { + return ResourceManager.GetString("AddEmail_SMTPUseSSL", resourceCulture); + } + } + /// /// Looks up a localized string similar to [Any Priority]. /// diff --git a/Growl/Growl/Properties/Resources.resx b/Growl/Growl/Properties/Resources.resx index ca6e613..ec83660 100644 --- a/Growl/Growl/Properties/Resources.resx +++ b/Growl/Growl/Properties/Resources.resx @@ -892,4 +892,60 @@ to Twitter Prowl Test Title of Prowl confirmation notification sent to confirm successful configuration + + [Any Priority] + Configure Email Forwarding: label for combobox choice for forwarding all notification priorities + + + Only forward when priority is at least: + Configure Email Forwarding: label for minimum priority + + + Description: + Configure Email Forwarding: 'Description' label + + + Email Address: + Configure Email Forwarding: 'Email Address' label + + + SMTP Settings: + Configure Email Forwarding: 'SMTP Settings' label + + + edit + Configure Email Forwarding: 'edit' link + + + Only forward when idle or away + Configure Email forwarding: 'only forward when idle' checkbox text + + + Server: + Configure Email forwarding SMTP Settings: 'Server' label + + + Port: + Configure Email forwarding SMTP Settings: 'Port' label + + + Use Authentication + Configure Email forwarding SMTP Settings: 'Use Authentication' checkbox text + + + Use SSL + Configure Email forwarding SMTP Settings: 'Use SSL' checkbox text + + + Username: + Configure Email forwarding SMTP Settings: 'Username' label + + + Password: + Configure Email forwarding SMTP Settings: 'Password' label + + + done + Configure Email forwarding SMTP Settings: 'done' link + \ No newline at end of file diff --git a/Growl/Growl/UI/EmailForwardInputs.Designer.cs b/Growl/Growl/UI/EmailForwardInputs.Designer.cs index cf94c7f..69d748b 100644 --- a/Growl/Growl/UI/EmailForwardInputs.Designer.cs +++ b/Growl/Growl/UI/EmailForwardInputs.Designer.cs @@ -35,9 +35,24 @@ private void InitializeComponent() this.textBoxDescription = new Growl.UI.HighlightTextBox(); this.labelDescription = new System.Windows.Forms.Label(); this.panelDetails = new System.Windows.Forms.Panel(); + this.linkLabelEditSMTPValues = new System.Windows.Forms.LinkLabel(); + this.labelSMTPValues = new System.Windows.Forms.Label(); this.checkBoxOnlyWhenIdle = new System.Windows.Forms.CheckBox(); this.labelSMTPSettings = new System.Windows.Forms.Label(); + this.panelSMTPSettings = new System.Windows.Forms.Panel(); + this.labelSMTPServer = new System.Windows.Forms.Label(); + this.textBoxSMTPServer = new System.Windows.Forms.TextBox(); + this.labelSMTPPort = new System.Windows.Forms.Label(); + this.textBoxSMTPPort = new System.Windows.Forms.TextBox(); + this.checkBoxSMTPUseAuthentication = new System.Windows.Forms.CheckBox(); + this.checkBoxSMTPUseSSL = new System.Windows.Forms.CheckBox(); + this.labelSMTPUsername = new System.Windows.Forms.Label(); + this.textBoxSMTPUsername = new System.Windows.Forms.TextBox(); + this.labelSMTPPassword = new System.Windows.Forms.Label(); + this.textBoxSMTPPassword = new System.Windows.Forms.TextBox(); + this.linkLabelSMTPDone = new System.Windows.Forms.LinkLabel(); this.panelDetails.SuspendLayout(); + this.panelSMTPSettings.SuspendLayout(); this.SuspendLayout(); // // comboBoxMinimumPriority @@ -99,6 +114,9 @@ private void InitializeComponent() // // panelDetails // + this.panelDetails.Controls.Add(this.panelSMTPSettings); + this.panelDetails.Controls.Add(this.linkLabelEditSMTPValues); + this.panelDetails.Controls.Add(this.labelSMTPValues); this.panelDetails.Controls.Add(this.checkBoxOnlyWhenIdle); this.panelDetails.Controls.Add(this.comboBoxMinimumPriority); this.panelDetails.Controls.Add(this.labelMinimumPriority); @@ -112,6 +130,26 @@ private void InitializeComponent() this.panelDetails.Size = new System.Drawing.Size(338, 168); this.panelDetails.TabIndex = 7; // + // linkLabelEditSMTPValues + // + this.linkLabelEditSMTPValues.AutoSize = true; + this.linkLabelEditSMTPValues.Location = new System.Drawing.Point(284, 62); + this.linkLabelEditSMTPValues.Name = "linkLabelEditSMTPValues"; + this.linkLabelEditSMTPValues.Size = new System.Drawing.Size(24, 13); + this.linkLabelEditSMTPValues.TabIndex = 12; + this.linkLabelEditSMTPValues.TabStop = true; + this.linkLabelEditSMTPValues.Text = "edit"; + this.linkLabelEditSMTPValues.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelEditSMTPValues_LinkClicked); + // + // labelSMTPValues + // + this.labelSMTPValues.Font = new System.Drawing.Font("Trebuchet MS", 9F); + this.labelSMTPValues.Location = new System.Drawing.Point(115, 60); + this.labelSMTPValues.Name = "labelSMTPValues"; + this.labelSMTPValues.Size = new System.Drawing.Size(149, 23); + this.labelSMTPValues.TabIndex = 11; + this.labelSMTPValues.Text = "[smtp values]"; + // // checkBoxOnlyWhenIdle // this.checkBoxOnlyWhenIdle.AutoSize = true; @@ -133,6 +171,129 @@ private void InitializeComponent() this.labelSMTPSettings.TabIndex = 6; this.labelSMTPSettings.Text = "SMTP Settings:"; // + // panelSMTPSettings + // + this.panelSMTPSettings.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panelSMTPSettings.Controls.Add(this.linkLabelSMTPDone); + this.panelSMTPSettings.Controls.Add(this.textBoxSMTPPassword); + this.panelSMTPSettings.Controls.Add(this.labelSMTPPassword); + this.panelSMTPSettings.Controls.Add(this.textBoxSMTPUsername); + this.panelSMTPSettings.Controls.Add(this.labelSMTPUsername); + this.panelSMTPSettings.Controls.Add(this.checkBoxSMTPUseSSL); + this.panelSMTPSettings.Controls.Add(this.checkBoxSMTPUseAuthentication); + this.panelSMTPSettings.Controls.Add(this.textBoxSMTPPort); + this.panelSMTPSettings.Controls.Add(this.labelSMTPPort); + this.panelSMTPSettings.Controls.Add(this.textBoxSMTPServer); + this.panelSMTPSettings.Controls.Add(this.labelSMTPServer); + this.panelSMTPSettings.Location = new System.Drawing.Point(22, 62); + this.panelSMTPSettings.Name = "panelSMTPSettings"; + this.panelSMTPSettings.Size = new System.Drawing.Size(286, 97); + this.panelSMTPSettings.TabIndex = 13; + // + // labelSMTPServer + // + this.labelSMTPServer.AutoSize = true; + this.labelSMTPServer.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelSMTPServer.Location = new System.Drawing.Point(2, 7); + this.labelSMTPServer.Name = "labelSMTPServer"; + this.labelSMTPServer.Size = new System.Drawing.Size(45, 16); + this.labelSMTPServer.TabIndex = 0; + this.labelSMTPServer.Text = "Server:"; + // + // textBoxSMTPServer + // + this.textBoxSMTPServer.Location = new System.Drawing.Point(45, 5); + this.textBoxSMTPServer.Name = "textBoxSMTPServer"; + this.textBoxSMTPServer.Size = new System.Drawing.Size(158, 20); + this.textBoxSMTPServer.TabIndex = 1; + // + // labelSMTPPort + // + this.labelSMTPPort.AutoSize = true; + this.labelSMTPPort.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelSMTPPort.Location = new System.Drawing.Point(209, 7); + this.labelSMTPPort.Name = "labelSMTPPort"; + this.labelSMTPPort.Size = new System.Drawing.Size(34, 16); + this.labelSMTPPort.TabIndex = 2; + this.labelSMTPPort.Text = "Port:"; + // + // textBoxSMTPPort + // + this.textBoxSMTPPort.Location = new System.Drawing.Point(242, 5); + this.textBoxSMTPPort.Name = "textBoxSMTPPort"; + this.textBoxSMTPPort.Size = new System.Drawing.Size(33, 20); + this.textBoxSMTPPort.TabIndex = 3; + this.textBoxSMTPPort.Text = "25"; + // + // checkBoxSMTPUseAuthentication + // + this.checkBoxSMTPUseAuthentication.AutoSize = true; + this.checkBoxSMTPUseAuthentication.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.checkBoxSMTPUseAuthentication.Location = new System.Drawing.Point(5, 27); + this.checkBoxSMTPUseAuthentication.Name = "checkBoxSMTPUseAuthentication"; + this.checkBoxSMTPUseAuthentication.Size = new System.Drawing.Size(123, 20); + this.checkBoxSMTPUseAuthentication.TabIndex = 4; + this.checkBoxSMTPUseAuthentication.Text = "Use Authentication"; + this.checkBoxSMTPUseAuthentication.UseVisualStyleBackColor = true; + this.checkBoxSMTPUseAuthentication.CheckedChanged += new System.EventHandler(this.checkBoxSMTPUseAuthentication_CheckedChanged); + // + // checkBoxSMTPUseSSL + // + this.checkBoxSMTPUseSSL.AutoSize = true; + this.checkBoxSMTPUseSSL.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.checkBoxSMTPUseSSL.Location = new System.Drawing.Point(211, 27); + this.checkBoxSMTPUseSSL.Name = "checkBoxSMTPUseSSL"; + this.checkBoxSMTPUseSSL.Size = new System.Drawing.Size(64, 20); + this.checkBoxSMTPUseSSL.TabIndex = 5; + this.checkBoxSMTPUseSSL.Text = "Use SSL"; + this.checkBoxSMTPUseSSL.UseVisualStyleBackColor = true; + // + // labelSMTPUsername + // + this.labelSMTPUsername.AutoSize = true; + this.labelSMTPUsername.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelSMTPUsername.Location = new System.Drawing.Point(22, 48); + this.labelSMTPUsername.Name = "labelSMTPUsername"; + this.labelSMTPUsername.Size = new System.Drawing.Size(61, 16); + this.labelSMTPUsername.TabIndex = 6; + this.labelSMTPUsername.Text = "Username:"; + // + // textBoxSMTPUsername + // + this.textBoxSMTPUsername.Location = new System.Drawing.Point(86, 46); + this.textBoxSMTPUsername.Name = "textBoxSMTPUsername"; + this.textBoxSMTPUsername.Size = new System.Drawing.Size(138, 20); + this.textBoxSMTPUsername.TabIndex = 7; + // + // labelSMTPPassword + // + this.labelSMTPPassword.AutoSize = true; + this.labelSMTPPassword.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelSMTPPassword.Location = new System.Drawing.Point(22, 69); + this.labelSMTPPassword.Name = "labelSMTPPassword"; + this.labelSMTPPassword.Size = new System.Drawing.Size(59, 16); + this.labelSMTPPassword.TabIndex = 8; + this.labelSMTPPassword.Text = "Password:"; + // + // textBoxSMTPPassword + // + this.textBoxSMTPPassword.Location = new System.Drawing.Point(86, 67); + this.textBoxSMTPPassword.Name = "textBoxSMTPPassword"; + this.textBoxSMTPPassword.Size = new System.Drawing.Size(138, 20); + this.textBoxSMTPPassword.TabIndex = 9; + // + // linkLabelSMTPDone + // + this.linkLabelSMTPDone.AutoSize = true; + this.linkLabelSMTPDone.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.linkLabelSMTPDone.Location = new System.Drawing.Point(243, 69); + this.linkLabelSMTPDone.Name = "linkLabelSMTPDone"; + this.linkLabelSMTPDone.Size = new System.Drawing.Size(32, 16); + this.linkLabelSMTPDone.TabIndex = 10; + this.linkLabelSMTPDone.TabStop = true; + this.linkLabelSMTPDone.Text = "done"; + this.linkLabelSMTPDone.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelSMTPDone_LinkClicked); + // // EmailForwardInputs // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -143,6 +304,8 @@ private void InitializeComponent() this.Controls.SetChildIndex(this.panelDetails, 0); this.panelDetails.ResumeLayout(false); this.panelDetails.PerformLayout(); + this.panelSMTPSettings.ResumeLayout(false); + this.panelSMTPSettings.PerformLayout(); this.ResumeLayout(false); } @@ -158,5 +321,19 @@ private void InitializeComponent() private System.Windows.Forms.Panel panelDetails; private System.Windows.Forms.Label labelSMTPSettings; private System.Windows.Forms.CheckBox checkBoxOnlyWhenIdle; + private System.Windows.Forms.Label labelSMTPValues; + private System.Windows.Forms.LinkLabel linkLabelEditSMTPValues; + private System.Windows.Forms.Panel panelSMTPSettings; + private System.Windows.Forms.TextBox textBoxSMTPPort; + private System.Windows.Forms.Label labelSMTPPort; + private System.Windows.Forms.TextBox textBoxSMTPServer; + private System.Windows.Forms.Label labelSMTPServer; + private System.Windows.Forms.Label labelSMTPPassword; + private System.Windows.Forms.TextBox textBoxSMTPUsername; + private System.Windows.Forms.Label labelSMTPUsername; + private System.Windows.Forms.CheckBox checkBoxSMTPUseSSL; + private System.Windows.Forms.CheckBox checkBoxSMTPUseAuthentication; + private System.Windows.Forms.LinkLabel linkLabelSMTPDone; + private System.Windows.Forms.TextBox textBoxSMTPPassword; } } diff --git a/Growl/Growl/UI/EmailForwardInputs.cs b/Growl/Growl/UI/EmailForwardInputs.cs index e1bf6ca..7b8feaf 100644 --- a/Growl/Growl/UI/EmailForwardInputs.cs +++ b/Growl/Growl/UI/EmailForwardInputs.cs @@ -12,16 +12,26 @@ public partial class EmailForwardInputs : ForwardDestinationSettingsPanel { private bool doValidation; private Color highlightColor = Color.FromArgb(254, 250, 184); + private SMTPConfiguration smtp = SMTPConfiguration.Local; public EmailForwardInputs() { InitializeComponent(); // localize text - this.labelDescription.Text = Properties.Resources.AddProwl_NameLabel; - this.labelEmail.Text = Properties.Resources.AddProwl_APIKeyLabel; - this.labelSMTPSettings.Text = Properties.Resources.AddProwl_APIKeyLabel; - this.labelMinimumPriority.Text = Properties.Resources.AddProwl_MinimumPriorityLabel; + this.labelDescription.Text = Properties.Resources.AddEmail_NameLabel; + this.labelEmail.Text = Properties.Resources.AddEmail_EmailAddressLabel; + this.labelSMTPSettings.Text = Properties.Resources.AddEmail_SMTPSettingsLabel; + this.labelMinimumPriority.Text = Properties.Resources.AddEmail_MinimumPriorityLabel; + this.checkBoxOnlyWhenIdle.Text = Properties.Resources.AddEmail_OnlyWhenIdle; + this.linkLabelEditSMTPValues.Text = Properties.Resources.AddEmail_EditSMTP; + this.labelSMTPServer.Text = Properties.Resources.AddEmail_SMTPServerLabel; + this.labelSMTPPort.Text = Properties.Resources.AddEmail_SMTPPortLabel; + this.checkBoxSMTPUseAuthentication.Text = Properties.Resources.AddEmail_SMTPUseAuthentication; + this.checkBoxSMTPUseSSL.Text = Properties.Resources.AddEmail_SMTPUseSSL; + this.labelSMTPUsername.Text = Properties.Resources.AddEmail_SMTPUsernameLabel; + this.labelSMTPPassword.Text = Properties.Resources.AddEmail_SMTPPasswordLabel; + this.linkLabelSMTPDone.Text = Properties.Resources.AddEmail_SMTPDone; } private void textBoxDescription_TextChanged(object sender, EventArgs e) @@ -38,6 +48,7 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem { this.doValidation = true; + this.panelSMTPSettings.Visible = false; this.textBoxDescription.HighlightColor = highlightColor; this.textBoxUsername.HighlightColor = highlightColor; @@ -65,10 +76,13 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem if (efd.MinimumPriority != null && efd.MinimumPriority.HasValue) this.comboBoxMinimumPriority.SelectedItem = PrefPriority.GetByValue(efd.MinimumPriority.Value); this.checkBoxOnlyWhenIdle.Checked = efd.OnlyWhenIdle; - // TODO: SMTP settings + this.smtp = efd.SMTPConfiguration; } + this.labelSMTPValues.Text = String.Format("{0}", this.smtp.Host); ValidateInputs(); + + this.textBoxDescription.Focus(); } public override ForwardDestination Create() @@ -76,7 +90,8 @@ public override ForwardDestination Create() Growl.Connector.Priority? priority = null; PrefPriority prefPriority = this.comboBoxMinimumPriority.SelectedItem as PrefPriority; if (prefPriority != null) priority = prefPriority.Priority.Value; - EmailForwardDestination efd = new EmailForwardDestination(this.textBoxDescription.Text, true, this.textBoxUsername.Text, null, priority, this.checkBoxOnlyWhenIdle.Checked); + + EmailForwardDestination efd = new EmailForwardDestination(this.textBoxDescription.Text, true, this.textBoxUsername.Text, this.smtp, priority, this.checkBoxOnlyWhenIdle.Checked); return efd; } @@ -90,17 +105,7 @@ public override void Update(ForwardDestination fd) efd.OnlyWhenIdle = this.checkBoxOnlyWhenIdle.Checked; PrefPriority prefPriority = this.comboBoxMinimumPriority.SelectedItem as PrefPriority; efd.MinimumPriority = (prefPriority != null ? prefPriority.Priority : null); - - /* // TODO: - SMTPConfiguration smtpConfig = new SMTPConfiguration(); - smtpConfig.Host; - smtpConfig.Port; - smtpConfig.Username; - smtpConfig.Password; - smtpConfig.UseAuthentication; - smtpConfig.UseSSL; - efd.SMTPConfiguration = smtpConfig; - * */ + efd.SMTPConfiguration = this.smtp; } } @@ -131,5 +136,39 @@ private void ValidateInputs() } OnValidChanged(valid); } + + private void linkLabelEditSMTPValues_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.textBoxSMTPServer.Text = this.smtp.Host; + this.textBoxSMTPPort.Text = this.smtp.Port.ToString(); + this.checkBoxSMTPUseAuthentication.Checked = this.smtp.UseAuthentication; + this.checkBoxSMTPUseSSL.Checked = this.smtp.UseSSL; + this.textBoxSMTPUsername.Text = this.smtp.Username; + this.textBoxSMTPPassword.Text = this.smtp.Password; + this.textBoxSMTPUsername.Enabled = this.smtp.UseAuthentication; + this.textBoxSMTPPassword.Enabled = this.smtp.UseAuthentication; + + this.panelSMTPSettings.Visible = true; + } + + private void linkLabelSMTPDone_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.smtp.Host = this.textBoxSMTPServer.Text; + this.smtp.Port = Convert.ToInt32(this.textBoxSMTPPort.Text); + this.smtp.UseAuthentication = this.checkBoxSMTPUseAuthentication.Checked; + this.smtp.UseSSL = this.checkBoxSMTPUseSSL.Checked; + this.smtp.Username = this.textBoxSMTPUsername.Text; + this.smtp.Password = this.textBoxSMTPPassword.Text; + + this.labelSMTPValues.Text = String.Format("{0}", this.smtp.Host); + this.panelSMTPSettings.Visible = false; + } + + private void checkBoxSMTPUseAuthentication_CheckedChanged(object sender, EventArgs e) + { + this.smtp.UseAuthentication = this.checkBoxSMTPUseAuthentication.Checked; + this.textBoxSMTPUsername.Enabled = this.smtp.UseAuthentication; + this.textBoxSMTPPassword.Enabled = this.smtp.UseAuthentication; + } } } diff --git a/Growl/Growl/UI/ForwardDestinationInputs.cs b/Growl/Growl/UI/ForwardDestinationInputs.cs index b4fa654..c4ab2d6 100644 --- a/Growl/Growl/UI/ForwardDestinationInputs.cs +++ b/Growl/Growl/UI/ForwardDestinationInputs.cs @@ -80,6 +80,7 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem this.textBoxPort.Enabled = false; this.comboBoxFormat.SelectedIndex = 0; this.comboBoxFormat.Enabled = false; + this.textBoxPassword.Focus(); } else { @@ -91,6 +92,7 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem this.textBoxPort.Enabled = true; this.comboBoxFormat.SelectedIndex = 0; this.comboBoxFormat.Enabled = true; + this.textBoxDescription.Focus(); } // edits @@ -125,6 +127,7 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem this.textBoxDescription.Enabled = false; this.textBoxAddress.Enabled = false; this.textBoxPort.Enabled = false; + this.textBoxPassword.Focus(); } UDPForwardDestination udp = fd as UDPForwardDestination; if (udp != null) @@ -150,7 +153,7 @@ public override ForwardDestination Create() ForwardDestination fc = null; if (this.isSubscription) { - Subscription subscription = new Subscription(textBoxDescription.Text, true, textBoxAddress.Text, Convert.ToInt32(textBoxPort.Text), textBoxPassword.Text); + Subscription subscription = new Subscription(textBoxDescription.Text, true, textBoxAddress.Text, Convert.ToInt32(textBoxPort.Text), textBoxPassword.Text, Properties.Settings.Default.EnableSubscriptions); fc = subscription; } else diff --git a/Growl/Growl/UI/ForwardListBox.cs b/Growl/Growl/UI/ForwardListBox.cs index 4d63f65..e180352 100644 --- a/Growl/Growl/UI/ForwardListBox.cs +++ b/Growl/Growl/UI/ForwardListBox.cs @@ -11,7 +11,6 @@ public class ForwardListBox : ListBox private const int IMAGE_SIZE = 48; private Color foreColor = Color.Black; - private int previouslySelectedIndex = -1; public ForwardListBox() : base() @@ -20,6 +19,9 @@ public ForwardListBox() this.DrawMode = DrawMode.OwnerDrawFixed; + // we cant use SelectionMode.One because that forces an automatic 'scroll into view' behavior that we dont want + this.SelectionMode = SelectionMode.MultiSimple; + this.DrawItem += new DrawItemEventHandler(BonjourListBox_DrawItem); this.ForeColorChanged += new EventHandler(BonjourListBox_ForeColorChanged); } @@ -72,16 +74,6 @@ public void AddItem(ForwardDestinationListItem item) this.Items.Add(item); } - protected override void OnSelectedIndexChanged(EventArgs e) - { - int currentlySelectedIndex = this.SelectedIndex; - if (currentlySelectedIndex != previouslySelectedIndex) - { - previouslySelectedIndex = currentlySelectedIndex; - base.OnSelectedIndexChanged(e); - } - } - private void InitializeComponent() { this.SuspendLayout(); @@ -104,13 +96,10 @@ private void BonjourListBox_MouseMove(object sender, MouseEventArgs e) i += this.TopIndex; if(this.SelectedIndex != i) { + this.SelectedIndices.Clear(); if (this.Items.Count > i) { - this.SelectedIndex = i; - } - else - { - this.SelectedIndices.Clear(); + this.SelectedIndices.Add(i); } } } @@ -118,11 +107,18 @@ private void BonjourListBox_MouseMove(object sender, MouseEventArgs e) private void BonjourListBox_MouseClick(object sender, MouseEventArgs e) { - if (this.SelectedItem != null) + /* we cant use any of the this.Selected* properites because we are using the MultiSimple selection mode + * instead, we have to determine which item was clicked on directly + * */ + + int i = 0; + if (e.Y > 0) { - if (this.SelectedItem is ForwardDestinationListItem) + i = e.Y / this.ItemHeight; + i += this.TopIndex; + if (this.Items.Count > i) { - ForwardDestinationListItem fli = (ForwardDestinationListItem)this.SelectedItem; + ForwardDestinationListItem fli = (ForwardDestinationListItem)this.Items[i]; fli.Select(); } } diff --git a/Growl/Growl/UI/ForwardListView.cs b/Growl/Growl/UI/ForwardListView.cs index 03f6e8a..878e15f 100644 --- a/Growl/Growl/UI/ForwardListView.cs +++ b/Growl/Growl/UI/ForwardListView.cs @@ -14,6 +14,7 @@ public class ForwardListView : ListView private ImageList imageList; private Dictionary computers; + private bool allDisabled = true; public ForwardListView() { @@ -34,6 +35,8 @@ public ForwardListView() this.imageList.Images.Add(ForwardDestinationPlatformType.Twitter.Name, ForwardDestinationPlatformType.Twitter.Icon); this.imageList.Images.Add(ForwardDestinationPlatformType.Other.Name, ForwardDestinationPlatformType.Other.Icon); + this.HoverSelection = false; + this.OwnerDraw = true; this.DoubleBuffered = true; @@ -60,15 +63,18 @@ public ForwardListView() void ForwardListView_MouseClick(object sender, MouseEventArgs e) { - ListViewHitTestInfo info = this.HitTest(e.Location); - if (info.Item != null) + if (e.Button == MouseButtons.Left) { - int y = info.Item.Bounds.Y + CHECKBOX_PADDING; - if (e.X > CHECKBOX_PADDING && e.X < (CHECKBOX_PADDING + CHECKBOX_SIZE) && e.Y > y && e.Y < (y + CHECKBOX_SIZE)) + ListViewHitTestInfo info = this.HitTest(e.Location); + if (info.Item != null) { - info.Item.Checked = !info.Item.Checked; - ForwardDestination fc = (ForwardDestination)info.Item.Tag; - fc.Enabled = info.Item.Checked; + int y = info.Item.Bounds.Y + CHECKBOX_PADDING; + if (e.X > CHECKBOX_PADDING && e.X < (CHECKBOX_PADDING + CHECKBOX_SIZE) && e.Y > y && e.Y < (y + CHECKBOX_SIZE)) + { + ForwardDestination fc = (ForwardDestination)info.Item.Tag; + fc.Enabled = !fc.Enabled; + this.Refresh(); + } } } } @@ -80,7 +86,6 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) int checkBoxAreaWidth = CHECKBOX_PADDING + CHECKBOX_SIZE + CHECKBOX_PADDING; System.Drawing.Rectangle bounds = new System.Drawing.Rectangle(e.Bounds.X + checkBoxAreaWidth, e.Bounds.Top, e.Bounds.Width - checkBoxAreaWidth, e.Bounds.Height); - // update information ForwardDestination fc = (ForwardDestination)e.Item.Tag; string display = Escape(fc.Display); @@ -89,8 +94,10 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) e.Item.ToolTipText = tooltip; // NOTE: dont set the .Text or .SubItem properties here - it causes an erratic exception - // draw the background and focus rectangle for selected and non-selected states - if (this.Enabled) + bool drawEnabled = ShouldDrawEnabled(fc); + + // draw the background for selected states + if(drawEnabled) { e.DrawBackground(); if ((e.State & ListViewItemStates.Selected) != 0) @@ -105,13 +112,11 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) e.Graphics.FillRectangle(backBrush, bounds); } } - if (e.Item.Selected) - ControlPaint.DrawFocusRectangle(e.Graphics, bounds); } - else - { - } + // draw the focus rectangle + if (e.Item.Selected) + ControlPaint.DrawFocusRectangle(e.Graphics, bounds); // draw icon int newX = bounds.X; @@ -121,7 +126,7 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) { int x = bounds.X; int y = bounds.Top; - if (this.Enabled && e.Item.Checked) + if(drawEnabled) e.Graphics.DrawImage(img, x, y); else ControlPaint.DrawImageDisabled(e.Graphics, img, x, y, System.Drawing.Color.Transparent); @@ -130,7 +135,7 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) } // draw main text - System.Drawing.Color textColor = (this.Enabled && e.Item.Checked ? e.Item.ForeColor : System.Drawing.Color.FromArgb(System.Drawing.SystemColors.GrayText.ToArgb())); + System.Drawing.Color textColor = (drawEnabled ? e.Item.ForeColor : System.Drawing.Color.FromArgb(System.Drawing.SystemColors.GrayText.ToArgb())); System.Drawing.RectangleF rect = new System.Drawing.RectangleF(newX, bounds.Top, bounds.Right - newX, e.Item.Font.Height); System.Drawing.StringFormat sf = new System.Drawing.StringFormat(); sf.Trimming = System.Drawing.StringTrimming.EllipsisCharacter; @@ -166,20 +171,10 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) // draw checkbox System.Windows.Forms.VisualStyles.CheckBoxState state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal; - if (this.Enabled) - { - if (e.Item.Checked) - state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal; - else - state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal; - } + if (fc.Enabled) + state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal; else - { - if (e.Item.Checked) - state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedDisabled; - else - state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedDisabled; - } + state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal; CheckBoxRenderer.DrawCheckBox(e.Graphics, new System.Drawing.Point(e.Bounds.Left + CHECKBOX_PADDING, e.Bounds.Top + CHECKBOX_PADDING), state); } else @@ -188,6 +183,18 @@ void ForwardListView_DrawItem(object sender, DrawListViewItemEventArgs e) } } + public bool AllDisabled + { + get + { + return this.allDisabled; + } + set + { + this.allDisabled = value; + } + } + public Dictionary Computers { get @@ -242,11 +249,18 @@ private void AddItem(ForwardDestination fc) string[] items = new string[] { display, address }; ListViewItem lvi = new ListViewItem(items, fc.Platform.Name); lvi.ToolTipText = tooltip; - lvi.Checked = fc.Enabled; lvi.Tag = fc; this.Items.Add(lvi); } + private bool ShouldDrawEnabled(ForwardDestination fd) + { + if (!this.allDisabled && fd.Enabled) + return true; + else + return false; + } + private static string Escape(string input) { string output = input; diff --git a/Growl/Growl/UI/ProwlForwardInputs.cs b/Growl/Growl/UI/ProwlForwardInputs.cs index 79174e2..30e83ea 100644 --- a/Growl/Growl/UI/ProwlForwardInputs.cs +++ b/Growl/Growl/UI/ProwlForwardInputs.cs @@ -68,6 +68,8 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem } ValidateInputs(); + + this.textBoxDescription.Focus(); } public override ForwardDestination Create() diff --git a/Growl/Growl/UI/TwitterForwardInputs.Designer.cs b/Growl/Growl/UI/TwitterForwardInputs.Designer.cs index e117cfd..975053f 100644 --- a/Growl/Growl/UI/TwitterForwardInputs.Designer.cs +++ b/Growl/Growl/UI/TwitterForwardInputs.Designer.cs @@ -86,7 +86,7 @@ private void InitializeComponent() this.textBoxFormat.Name = "textBoxFormat"; this.textBoxFormat.Size = new System.Drawing.Size(199, 20); this.textBoxFormat.TabIndex = 1; - this.textBoxFormat.TextChanged += new System.EventHandler(this.textBoxDescription_TextChanged); + this.textBoxFormat.TextChanged += new System.EventHandler(this.textBoxFormat_TextChanged); // // labelFormat // diff --git a/Growl/Growl/UI/TwitterForwardInputs.cs b/Growl/Growl/UI/TwitterForwardInputs.cs index e827f18..1aab313 100644 --- a/Growl/Growl/UI/TwitterForwardInputs.cs +++ b/Growl/Growl/UI/TwitterForwardInputs.cs @@ -25,17 +25,17 @@ public TwitterForwardInputs() this.checkBoxOnlyWhenIdle.Text = Properties.Resources.AddTwitter_OnlyWhenIdle; } - private void textBoxDescription_TextChanged(object sender, EventArgs e) + private void textBoxUsername_TextChanged(object sender, EventArgs e) { ValidateInputs(); } - private void textBoxUsername_TextChanged(object sender, EventArgs e) + private void textBoxPassword_TextChanged(object sender, EventArgs e) { ValidateInputs(); } - private void textBoxPassword_TextChanged(object sender, EventArgs e) + private void textBoxFormat_TextChanged(object sender, EventArgs e) { ValidateInputs(); } @@ -78,6 +78,8 @@ public override void Initialize(bool isSubscription, ForwardDestinationListItem } ValidateInputs(); + + this.textBoxUsername.Focus(); } public override ForwardDestination Create() diff --git a/Growl/Growl/_source/ActivityMonitor.cs b/Growl/Growl/_source/ActivityMonitor.cs index c01f41b..c941619 100644 --- a/Growl/Growl/_source/ActivityMonitor.cs +++ b/Growl/Growl/_source/ActivityMonitor.cs @@ -202,7 +202,7 @@ void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) int lastInputAt = GetIdleTime(); int diff = Environment.TickCount - lastInputAt; TimeSpan idleFor = new TimeSpan(0, 0, 0, 0, diff); - int idleForSeconds = idleFor.Seconds; + int idleForSeconds = Convert.ToInt32(idleFor.TotalSeconds); if (this.IsIdle) { diff --git a/Growl/Growl/_source/ApplicationMain.cs b/Growl/Growl/_source/ApplicationMain.cs index 6832eda..ddcf134 100644 --- a/Growl/Growl/_source/ApplicationMain.cs +++ b/Growl/Growl/_source/ApplicationMain.cs @@ -62,7 +62,7 @@ static void Main(string[] args) string debug = parameters["/debug"].Value.ToLower(); if (debug == "true") debugMode = true; Utility.DebugMode = debugMode; - MessageBox.Show("growl is now in debug mode"); + if(debugMode) MessageBox.Show("growl is now in debug mode"); } program = new Program(); @@ -136,11 +136,15 @@ private static Parameter GetParameterValue(string argument) { if (argument.StartsWith("/")) { + string val = ""; string[] parts = argument.Split(new char[] { ':' }, 2); - string val = parts[1]; - if (val.StartsWith("\"") && val.EndsWith("\"")) + if (parts.Length == 2) { - val = val.Substring(1, val.Length - 2); + val = parts[1]; + if (val.StartsWith("\"") && val.EndsWith("\"")) + { + val = val.Substring(1, val.Length - 2); + } } return new Parameter(parts[0], val); } diff --git a/Growl/Growl/_source/AutoUpdate/Updater.cs b/Growl/Growl/_source/AutoUpdate/Updater.cs index b5d2c85..1b76812 100644 --- a/Growl/Growl/_source/AutoUpdate/Updater.cs +++ b/Growl/Growl/_source/AutoUpdate/Updater.cs @@ -17,7 +17,7 @@ public class Updater : IDisposable public event EventHandler DownloadComplete; public event UpdateErrorEventHandler UpdateError; - private WebClient checker; + private WebClientEx checker; private string appPath; private string manifestFile; private string currentVersion; @@ -41,7 +41,7 @@ public Updater(string appPath, string currentVersion, string updateLocation) this.updateLocation = updateLocation; this.updateTempFolder = Path.Combine(Utility.UserSettingFolder, UPDATE_FOLDER); - this.checker = new WebClient(); + this.checker = new WebClientEx(); checker.Headers.Add("User-Agent", "Element.AutoUpdate.Updater"); checker.DownloadStringCompleted += new DownloadStringCompletedEventHandler(checker_DownloadStringCompleted); } @@ -107,7 +107,7 @@ public void Update() info.SetupFile = Path.Combine(updateTempFolder, "setup.exe"); info.Folder = updateTempFolder; - WebClient downloader = new WebClient(); + WebClientEx downloader = new WebClientEx(); using (downloader) { downloader.Headers.Add("User-Agent", "Element.AutoUpdate.Updater"); diff --git a/Growl/Growl/_source/Controller.cs b/Growl/Growl/_source/Controller.cs index d6a5605..ab5fe84 100644 --- a/Growl/Growl/_source/Controller.cs +++ b/Growl/Growl/_source/Controller.cs @@ -423,60 +423,16 @@ void display_NotificationCallback(Growl.Daemon.CallbackInfo cbInfo, Growl.CoreLi } else { - string data = cbInfo.GetUrlCallbackData(result); Growl.Connector.UrlCallbackTarget target = cbInfo.Context.GetUrlCallbackTarget(); - if (!String.IsNullOrEmpty(target.Url)) + if (target != null && !String.IsNullOrEmpty(target.Url)) { - /* - // if the method is APP, we want to use a custom application protocol handler, - // otherwise, it is a web-based callback and we handle it behind the scenes - if (target.Method == Growl.Connector.UrlCallbackTarget.APP) - { - System.UriBuilder ub = new UriBuilder(target.Url); - if (ub.Query != null && ub.Query.Length > 1) - ub.Query = ub.Query.Substring(1) + "&" + data; - else - ub.Query = data; - - System.Diagnostics.Process.Start(ub.Uri.AbsoluteUri); - } - else - { - System.Net.WebClient webclient = new System.Net.WebClient(); - using (webclient) - { - webclient.Encoding = Encoding.UTF8; - webclient.Headers.Add("user-agent", String.Format("{0} - Notification Callback", this.gntpListener.ServerName)); - Uri uri = new Uri(target.Url); - webclient.UploadStringAsync(uri, target.Method, data); - } - } - * */ - - /* - // TODO: - System.Net.WebClient webclient = new System.Net.WebClient(); - using (webclient) - { - webclient.Encoding = Encoding.UTF8; - webclient.Headers.Add("user-agent", String.Format("{0} - Notification Callback", this.gntpListener.ServerName)); - Uri uri = new Uri(target.Url); - webclient.UploadStringAsync(uri, target.Method, data); - } - * */ - - // TODO: for now, this will only fire on CLICK since that is the more expected behavior - // TODO: temporary - for now, we just launch the url that was specified + // this will only fire on CLICK since that is the more expected behavior // NOTE: there is probably a huge security risk by doing this (for now, I am relying on UriBuilder to protect us from from other types of commands) if (result == Growl.CoreLibrary.CallbackResult.CLICK) { try { System.UriBuilder ub = new UriBuilder(target.Url); - if (ub.Query != null && ub.Query.Length > 1) - ub.Query = ub.Query.Substring(1) + "&" + data; - else - ub.Query = data; // do this in another thread so the Process.Start doesnt block System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(ub.Uri.AbsoluteUri); @@ -485,7 +441,7 @@ void display_NotificationCallback(Growl.Daemon.CallbackInfo cbInfo, Growl.CoreLi catch { // TODO: this is temporary (and thus not localized either) // LOCALIZE: - SendSystemNotification("Callback failure", "An application requested a callback via url, but the url was invalid."); + SendSystemNotification("Callback failure", String.Format("An application requested a callback via url, but the url was invalid. The url was: {0}", target.Url)); } } } @@ -1270,13 +1226,12 @@ protected void HandleForwarding(Growl.Connector.Application application, List busyWebClients; - private string apiKey; private Growl.Connector.Priority? minimumPriority = null; private bool onlyWhenIdle; @@ -95,6 +92,8 @@ internal override void ForwardRegistration(Growl.Connector.Application applicati { // IGNORE REGISTRATION NOTIFICATIONS (since we have no way of filtering out already-registered apps at this point) //Send(application.Name, Properties.Resources.SystemNotification_AppRegistered_Title, String.Format(Properties.Resources.SystemNotification_AppRegistered_Text, application.Name)); + + requestInfo.SaveHandlingInfo("Forwarding to Prowl cancelled - Application Registrations are not forwarded."); } internal override void ForwardNotification(Growl.Connector.Notification notification, Growl.Daemon.CallbackInfo callbackInfo, Growl.Daemon.RequestInfo requestInfo, bool isIdle, Forwarder.ForwardedNotificationCallbackHandler callbackFunction) @@ -103,107 +102,105 @@ internal override void ForwardNotification(Growl.Connector.Notification notifica // if a minimum priority is set, check that if (this.MinimumPriority != null && this.MinimumPriority.HasValue && notification.Priority < this.MinimumPriority.Value) + { + requestInfo.SaveHandlingInfo(String.Format("Forwarding to Prowl ({0}) cancelled - Notification priority must be at least '{1}' (was actually '{2}').", this.Description, this.MinimumPriority.Value.ToString(), notification.Priority.ToString())); send = false; + } // if only sending when idle, check that - if (this.OnlyWhenIdle && !isIdle) + if (send && this.OnlyWhenIdle && !isIdle) + { + requestInfo.SaveHandlingInfo(String.Format("Forwarding to Prowl ({0}) cancelled - Currently only configured to forward when idle", this.Description)); send = false; + } if (send) { string text = notification.Text; - /* THIS IS NOT READY YET - * this appends the url from a url callback to the Prowl message (if specified) - * this allows the user to click the url right from their Prowl app - * + + /* NOT YET + // this appends the url from a url callback to the Prowl message (if specified) + // this allows the user to click the url right from their Prowl app if (callbackInfo != null && callbackInfo.Context != null) { Growl.Connector.UrlCallbackTarget target = callbackInfo.Context.GetUrlCallbackTarget(); - if (!String.IsNullOrEmpty(target.Url)) + if (target != null && !String.IsNullOrEmpty(target.Url)) { - string data = callbackInfo.GetUrlCallbackData(Growl.CoreLibrary.CallbackResult.CLICK); - System.UriBuilder ub = new UriBuilder(target.Url); - if (ub.Query != null && ub.Query.Length > 1) - ub.Query = ub.Query.Substring(1) + "&" + data; - else - ub.Query = data; - text += String.Format(" - {0}", ub.Uri.AbsoluteUri); + text += String.Format(" - {0}", target.Url); } } * */ + Send(notification.ApplicationName, notification.Title, text, notification.Priority); } } private void Send(string applicationName, string title, string text, Growl.Connector.Priority priority) + { + // data + System.Collections.Specialized.NameValueCollection data = new System.Collections.Specialized.NameValueCollection(); + data.Add("apikey", this.APIKey); + //data.Add("providerkey", ""); + data.Add("priority", ((int)priority).ToString()); + data.Add("application", applicationName); + data.Add("event", title); + data.Add("description", text); + + // send async (using threads instead of async WebClient methods since they seem to have a bug with KeepAlives in infrequent cases) + System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(SendAsync), data); + } + + private void SendAsync(object state) { try { // data - System.Collections.Specialized.NameValueCollection data = new System.Collections.Specialized.NameValueCollection(); - data.Add("apikey", this.APIKey); - //data.Add("providerkey", ""); - data.Add("priority", ((int) priority).ToString()); - data.Add("application", applicationName); - data.Add("event", title); - data.Add("description", text); + System.Collections.Specialized.NameValueCollection data = (System.Collections.Specialized.NameValueCollection)state; // prepare the WebClient Uri uri = new Uri(URL); - System.Net.WebClient wc = new System.Net.WebClient(); - wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, "Growl for Windows/2.0"); - wc.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); - wc.UploadValuesCompleted += new UploadValuesCompletedEventHandler(wc_UploadValuesCompleted); - - /* - // no proxy - WebProxy proxy = null; + WebClientEx wc = new WebClientEx(); + using (wc) + { + wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, "Growl for Windows/2.0"); + wc.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); - // auto-detect (use IE settings) - this is the default, so really not needed - WebProxy proxy = WebRequest.DefaultWebProxy; + /* + // no proxy + WebProxy proxy = null; - // custom proxy - WebProxy proxy = new WebProxy(); - proxy.Address = "http://localhost:8080"; - proxy.BypassProxyOnLocal = true; - proxy.Credentials = new NetworkCredential("username", "password"); + // auto-detect (use IE settings) - this is the default, so really not needed + WebProxy proxy = WebRequest.DefaultWebProxy; - wc.Proxy = proxy; + // custom proxy + WebProxy proxy = new WebProxy(); + proxy.Address = "http://localhost:8080"; + proxy.BypassProxyOnLocal = true; + proxy.Credentials = new NetworkCredential("username", "password"); - Console.WriteLine(wc.Proxy); - * */ + wc.Proxy = proxy; - // save the WebClient so we can dispose of it when it completes - if (this.busyWebClients == null) this.busyWebClients = new Dictionary(); - string key = System.Guid.NewGuid().ToString(); - this.busyWebClients.Add(key, wc); + Console.WriteLine(wc.Proxy); + * */ - // do it - wc.UploadValuesAsync(uri, "POST", data, key); - // not sure why, but either this code is bad or the Prowl servers are flakey - // but if this method exits immediately, then it will often result in a 'connection failed' exception - System.Threading.Thread.Sleep(100); + // do it + try + { + byte[] bytes = wc.UploadValues(uri, "POST", data); + string response = System.Text.Encoding.ASCII.GetString(bytes); + Utility.WriteDebugInfo(String.Format("Prowl forwarding response: {0}", response)); + } + catch(Exception ex) + { + Utility.WriteDebugInfo(String.Format("Prowl forwarding failed: {0}", ex.Message)); + } + } } catch(Exception ex) { Console.WriteLine(ex); } } - - void wc_UploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e) - { - string key = (string)e.UserState; - if (!String.IsNullOrEmpty(key)) - { - if (this.busyWebClients.ContainsKey(key)) - { - WebClient wc = this.busyWebClients[key]; - wc.Dispose(); - wc = null; - this.busyWebClients.Remove(key); - } - } - } } } diff --git a/Growl/Growl/_source/Subscription.cs b/Growl/Growl/_source/Subscription.cs index 2b7b428..5a11268 100644 --- a/Growl/Growl/_source/Subscription.cs +++ b/Growl/Growl/_source/Subscription.cs @@ -33,9 +33,10 @@ public class Subscription : GNTPForwardDestination, IDeserializationCallback, ID [NonSerialized] private bool disposed; - public Subscription(string name, bool enabled, string ipAddress, int port, string password) + public Subscription(string name, bool enabled, string ipAddress, int port, string password, bool allowed) : base(name, enabled, ipAddress, port, password) { + this.allowed = allowed; Subscribe(); } @@ -106,18 +107,21 @@ public void Update() private void Subscribe() { - EnsureTimer(); - StopRetryTimer(); + if (this.Allowed) + { + EnsureTimer(); + StopRetryTimer(); - if (this.subscriberID == null) this.subscriberID = Growl.Daemon.Subscriber.GenerateID(); - this.AdditionalOfflineDisplayInfo = "connecting..."; - if (this.sc != null) this.sc = null; - Growl.Daemon.Subscriber subscriber = new Growl.Daemon.Subscriber(this.subscriberID, Environment.MachineName, Growl.Connector.GrowlConnector.TCP_PORT); - this.sc = new Growl.Daemon.SubscriptionConnector(subscriber, this.Password, this.IPAddress, this.Port); - this.sc.EncryptionAlgorithm = Growl.Connector.Cryptography.SymmetricAlgorithmType.PlainText; - this.sc.OKResponse += new Growl.Daemon.SubscriptionConnector.ResponseEventHandler(sc_OKResponse); - this.sc.ErrorResponse += new Growl.Daemon.SubscriptionConnector.ResponseEventHandler(sc_ErrorResponse); - this.sc.Subscribe(); + if (this.subscriberID == null) this.subscriberID = Growl.Daemon.Subscriber.GenerateID(); + this.AdditionalOfflineDisplayInfo = "connecting..."; + if (this.sc != null) this.sc = null; + Growl.Daemon.Subscriber subscriber = new Growl.Daemon.Subscriber(this.subscriberID, Environment.MachineName, Growl.Connector.GrowlConnector.TCP_PORT); + this.sc = new Growl.Daemon.SubscriptionConnector(subscriber, this.Password, this.IPAddress, this.Port); + this.sc.EncryptionAlgorithm = Growl.Connector.Cryptography.SymmetricAlgorithmType.PlainText; + this.sc.OKResponse += new Growl.Daemon.SubscriptionConnector.ResponseEventHandler(sc_OKResponse); + this.sc.ErrorResponse += new Growl.Daemon.SubscriptionConnector.ResponseEventHandler(sc_ErrorResponse); + this.sc.Subscribe(); + } } internal void Kill() @@ -133,9 +137,12 @@ internal void Kill() void sc_OKResponse(Growl.Daemon.SubscriptionResponse response) { + if (this.Enabled) + { + this.AdditionalOfflineDisplayInfo = null; + this.AdditionalOnlineDisplayInfo = String.Format("TTL: {0}", response.TTL); + } this.Platform = ForwardDestinationPlatformType.FromString(response.PlatformName); - this.AdditionalOfflineDisplayInfo = null; - this.AdditionalOnlineDisplayInfo = String.Format("TTL: {0}", response.TTL); this.available = true; OnStatusChanged(); @@ -144,8 +151,11 @@ void sc_OKResponse(Growl.Daemon.SubscriptionResponse response) void sc_ErrorResponse(Growl.Daemon.SubscriptionResponse response) { - this.AdditionalOfflineDisplayInfo = (response.ErrorCode == Growl.Connector.ErrorCode.NOT_AUTHORIZED ? "invalid password" : "server unavailable"); - this.AdditionalOnlineDisplayInfo = null; + if (this.Enabled) + { + this.AdditionalOfflineDisplayInfo = (response.ErrorCode == Growl.Connector.ErrorCode.NOT_AUTHORIZED ? "invalid password" : "server unavailable"); + this.AdditionalOnlineDisplayInfo = null; + } this.available = false; OnStatusChanged(); diff --git a/Growl/Growl/_source/TwitterForwardDestination.cs b/Growl/Growl/_source/TwitterForwardDestination.cs index d2ce4ea..03db692 100644 --- a/Growl/Growl/_source/TwitterForwardDestination.cs +++ b/Growl/Growl/_source/TwitterForwardDestination.cs @@ -136,6 +136,7 @@ public override ForwardDestination Clone() internal override void ForwardRegistration(Growl.Connector.Application application, List notificationTypes, Growl.Daemon.RequestInfo requestInfo, bool isIdle) { // IGNORE REGISTRATION NOTIFICATIONS + requestInfo.SaveHandlingInfo("Forwarding to Twitter cancelled - Application Registrations are not forwarded."); } internal override void ForwardNotification(Growl.Connector.Notification notification, Growl.Daemon.CallbackInfo callbackInfo, Growl.Daemon.RequestInfo requestInfo, bool isIdle, Forwarder.ForwardedNotificationCallbackHandler callbackFunction) @@ -144,11 +145,17 @@ internal override void ForwardNotification(Growl.Connector.Notification notifica // if a minimum priority is set, check that if (this.MinimumPriority != null && this.MinimumPriority.HasValue && notification.Priority < this.MinimumPriority.Value) + { + requestInfo.SaveHandlingInfo(String.Format("Forwarding to Twitter ({0}) cancelled - Notification priority must be at least '{1}' (was actually '{2}').", this.Username, this.MinimumPriority.Value.ToString(), notification.Priority.ToString())); send = false; + } // if only sending when idle, check that if (this.OnlyWhenIdle && !isIdle) + { + requestInfo.SaveHandlingInfo(String.Format("Forwarding to Twitter ({0}) cancelled - Currently only configured to forward when idle", this.Username)); send = false; + } if (send) { @@ -159,17 +166,21 @@ internal override void ForwardNotification(Growl.Connector.Notification notifica message = message.Replace(PLACEHOLDER_PRIORITY, PrefPriority.GetFriendlyName(notification.Priority)); message = message.Replace(PLACEHOLDER_SENDER, notification.MachineName); //Console.WriteLine(message); - Send(message); + + // trim + if (message.Length > 140) message = message.Substring(0, 140); + byte[] bytes = System.Text.Encoding.UTF8.GetBytes("status=" + message); + + // send async (using threads instead of async WebClient/HttpWebRequest methods since they seem to have a bug with KeepAlives in infrequent cases) + System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(SendAsync), bytes); } } - private void Send(string message) + private void SendAsync(object state) { try { - // trim - if (message.Length > 140) message = message.Substring(0, 140); - byte[] bytes = System.Text.Encoding.UTF8.GetBytes("status=" + message); + byte[] data = (byte[])state; string url = "http://twitter.com/statuses/update.xml"; @@ -177,17 +188,53 @@ private void Send(string message) string encodedCredentials = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(credentials)); string authorizationHeaderValue = String.Format("Basic {0}", encodedCredentials); + WebClientEx wex = new WebClientEx(); + wex.Headers.Add(System.Net.HttpRequestHeader.UserAgent, "Growl for Windows/2.0"); + wex.Headers.Add(System.Net.HttpRequestHeader.Authorization, authorizationHeaderValue); + wex.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); + + try + { + byte[] bytes = wex.UploadData(url, "POST", data); + string response = System.Text.Encoding.ASCII.GetString(bytes); + Utility.WriteDebugInfo(String.Format("Twitter forwarding response: {0}", response)); + } + catch (Exception ex) + { + Utility.WriteDebugInfo(String.Format("Twitter forwarding failed: {0}", ex.Message)); + } + + + + /* System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url); request.ServicePoint.Expect100Continue = false; + request.ServicePoint.MaxIdleTime = 1000; + request.KeepAlive = false; + request.ProtocolVersion = System.Net.HttpVersion.Version10; request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.UserAgent = "Growl for Windows/2.0"; request.Headers.Add("Authorization", authorizationHeaderValue); request.ContentLength = bytes.Length; + System.IO.Stream requestStream = request.GetRequestStream(); + using (requestStream) + { + requestStream.Write(bytes, 0, bytes.Length); + } + + System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse(); + System.IO.Stream responseStream = response.GetResponseStream(); + using (responseStream) + { + byte[] responseBytes = responseStream.r + } + AsyncCallback requestCallback = new AsyncCallback(EndGetRequestStream); State state = new State(request, bytes); request.BeginGetRequestStream(requestCallback, state); + * */ } catch (Exception ex) { @@ -195,6 +242,7 @@ private void Send(string message) } } + /* private void EndGetRequestStream(IAsyncResult iar) { try @@ -240,5 +288,6 @@ public State(System.Net.HttpWebRequest request, byte[] bytes) public System.Net.HttpWebRequest Request; public byte[] Bytes; } + * */ } } diff --git a/Growl/Growl/_source/Utility.cs b/Growl/Growl/_source/Utility.cs index 26d5e83..efbadc2 100644 --- a/Growl/Growl/_source/Utility.cs +++ b/Growl/Growl/_source/Utility.cs @@ -98,13 +98,23 @@ public static bool DebugMode public static void WriteDebugInfo(string info) { - string debugFile = System.IO.Path.Combine(UserSettingFolder, "debug.txt"); - lock (debugLock) + bool ok = DebugMode; + +// always write debug info in debug builds +#if (DEBUG) + ok = true; +#endif + + if (ok) { - System.IO.StreamWriter w = System.IO.File.AppendText(debugFile); - using (w) + string debugFile = System.IO.Path.Combine(UserSettingFolder, "debug.txt"); + lock (debugLock) { - w.WriteLine("{0} {1}", DateTime.Now, info); + System.IO.StreamWriter w = System.IO.File.AppendText(debugFile); + using (w) + { + w.WriteLine("{0} {1}", DateTime.Now, info); + } } } } diff --git a/Growl/Growl/_source/WebClientEx.cs b/Growl/Growl/_source/WebClientEx.cs new file mode 100644 index 0000000..0107ba9 --- /dev/null +++ b/Growl/Growl/_source/WebClientEx.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; + +namespace Growl +{ + public class WebClientEx : WebClient + { + static WebClientEx() + { + //ServicePointManager.MaxServicePointIdleTime = 1000; + } + + protected override WebRequest GetWebRequest(Uri address) + { + HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address); + request.KeepAlive = false; + request.ProtocolVersion = HttpVersion.Version10; + request.ServicePoint.MaxIdleTime = 1000; + return request; + } + } +} diff --git a/Growl/Growl/release_notes.txt b/Growl/Growl/release_notes.txt index 5a20b36..f6a28c6 100644 --- a/Growl/Growl/release_notes.txt +++ b/Growl/Growl/release_notes.txt @@ -1,3 +1,17 @@ +Beta 19 changes +------------------------------ +- added email forwarding option +- updated url callback handling to be compatible with current GNTP spec (open url using GET, no notification data appeneded, on click only) +- improved Prowl and Twitter forwarding mechanism to be more robust +- fixed a bug that caused Growl to never consider you idle if your preference was set over 59 seconds +- fixed a bug that caused disabled forwarding entries to sometimes show as enabled (but still act disabled) +- fixed a bug that caused per-notification forwarding preferences to overwrite the default forwarding preferences +- fixed a bug that caused Prowl notifications to infrequently be dropped +- fixed a bug related to display SettingsPanel being instantiated twice +- fixed some bugs related to disabled subscriptions +- updated growlnotify to allow registering multiple notification types +- added HTTP Monitoring to System Monitor + Beta 18 changes ------------------------------ - fixed a bug in Detector.DetectIfGrowlIsRunning() that could cause a crash diff --git a/Growl/Growl/update.manifest b/Growl/Growl/update.manifest index 82e53f2..dbe0935 100644 --- a/Growl/Growl/update.manifest +++ b/Growl/Growl/update.manifest @@ -1,7 +1,7 @@ - 2.0.0.18 + 2.0.0.19 True http://www.growlforwindows.com/gfw/updates/gfw2.manifest - http://www.growlforwindows.com/gfw/d.ashx?f=Growl_v2.0b18.msi + http://www.growlforwindows.com/gfw/d.ashx?f=Growl_v2.0b19.msi \ No newline at end of file diff --git a/Growl/Test App/Form1.cs b/Growl/Test App/Form1.cs index 949d506..a1e6853 100644 --- a/Growl/Test App/Form1.cs +++ b/Growl/Test App/Form1.cs @@ -41,7 +41,7 @@ public Form1() Growl.CoreLibrary.Detector detector = new Detector(); - if (detector.IsAvailable) + if (detector.IsInstalled) { InvokeWrite(String.Format("Growl (v{0}; f{1}; a{2}) is installed at {3} ({4})", detector.FileVersion.ProductVersion, detector.FileVersion.FileVersion, detector.AssemblyVersion.ToString(), detector.InstallationFolder, detector.DisplaysFolder)); } @@ -128,10 +128,10 @@ private void button2_Click(object sender, EventArgs e) callback.Data = "context-data"; callback.Type = "string"; UrlCallbackTarget target = new UrlCallbackTarget(); - target.Method = "POST"; + target.Method = "GET"; //target.Method = "APP"; - target.Url = "http://localhost/growl-callback.aspx"; - //target.Url = "itpc:http://www.npr.org/rss/podcast.php?id=35"; + //target.Url = "http://localhost/growl-callback.aspx"; + target.Url = "itpc:http://www.npr.org/rss/podcast.php?id=35"; //target.Url = "mailto:brian@elementcodeproject.com"; //target.Url = "itms:music fake"; //target.Url = "delete"; diff --git a/Growl/Windows Deployment/Windows Deployment.vdproj b/Growl/Windows Deployment/Windows Deployment.vdproj index 0f8da79..1be277d 100644 --- a/Growl/Windows Deployment/Windows Deployment.vdproj +++ b/Growl/Windows Deployment/Windows Deployment.vdproj @@ -1425,14 +1425,14 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:Growl for Windows" - "ProductCode" = "8:{8870D0D8-4427-49BC-A0E7-ABAE34227983}" - "PackageCode" = "8:{0F9A3482-0509-4359-8949-437454476D80}" + "ProductCode" = "8:{596935F4-8DC0-4B94-B4CA-38CAE09C7A13}" + "PackageCode" = "8:{27F14D25-4475-42B7-A19E-C35BDFE0A569}" "UpgradeCode" = "8:{54381489-14E3-47B6-8B92-DEB266DCF6E9}" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:2.0.00180" + "ProductVersion" = "8:2.0.00191" "Manufacturer" = "8:Growl" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"