From f3572aec7f159231ca2b63be1d2c5466a3ff7208 Mon Sep 17 00:00:00 2001
From: csarven <csarven@controlyourself.ca>
Date: Sat, 15 Nov 2008 21:27:35 -0500
Subject: [PATCH] Nudge feature

darcs-hash:20081116022735-eefa4-366f6deb85942f859ebd532e477b57737bcafbf8.gz
---
 actions/emailsettings.php              |   5 +++
 actions/showstream.php                 |  15 +++++++--
 db/laconica.sql                        |   1 +
 db/laconica_pg.sql                     |   2 ++
 js/util.js                             |   5 +++
 lib/mail.php                           |  23 ++++++++++++++
 lib/util.php                           |  21 +++++++++++++
 theme/default/display.css              |  42 +++++++++++++++++++++++++
 theme/default/icon_checkmark.png       | Bin 0 -> 781 bytes
 theme/default/icon_emote-wink.png      | Bin 0 -> 914 bytes
 theme/default/icon_process-working.gif | Bin 0 -> 1849 bytes
 theme/default/ie7.css                  |  12 +++++--
 12 files changed, 121 insertions(+), 5 deletions(-)
 create mode 100644 theme/default/icon_checkmark.png
 create mode 100644 theme/default/icon_emote-wink.png
 create mode 100644 theme/default/icon_process-working.gif

diff --git a/actions/emailsettings.php b/actions/emailsettings.php
index 6e189a909d..bc79c14f94 100644
--- a/actions/emailsettings.php
+++ b/actions/emailsettings.php
@@ -94,6 +94,9 @@ class EmailsettingsAction extends SettingsAction {
 		common_checkbox('emailnotifymsg',
 		                _('Send me email when someone sends me a private message.'),
 		                $user->emailnotifymsg);
+		common_checkbox('emailnotifynudge',
+		                _('Send me an email when someone nudges me.'),
+		                $user->emailnotifnudge);
 		common_checkbox('emailpost',
 						_('I want to post notices by email.'),
 						$user->emailpost);
@@ -150,6 +153,7 @@ class EmailsettingsAction extends SettingsAction {
 		$emailnotifysub = $this->boolean('emailnotifysub');
 		$emailnotifyfav = $this->boolean('emailnotifyfav');
 		$emailnotifymsg = $this->boolean('emailnotifymsg');
+		$emailnotifynudge = $this->boolean('emailnotifynudge');
 		$emailmicroid = $this->boolean('emailmicroid');
 		$emailpost = $this->boolean('emailpost');
 
@@ -164,6 +168,7 @@ class EmailsettingsAction extends SettingsAction {
 		$user->emailnotifysub = $emailnotifysub;
 		$user->emailnotifyfav = $emailnotifyfav;
 		$user->emailnotifymsg = $emailnotifymsg;
+		$user->emailnotifynudge = $emailnotifynudge;
 		$user->emailmicroid = $emailmicroid;
 		$user->emailpost = $emailpost;
 
diff --git a/actions/showstream.php b/actions/showstream.php
index 9db31c108e..56858b477d 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -64,7 +64,6 @@ class ShowstreamAction extends StreamAction {
 	}
 
 	function show_top($user) {
-
 		$cur = common_current_user();
 
 		if ($cur && $cur->id == $user->id) {
@@ -167,6 +166,10 @@ class ShowstreamAction extends StreamAction {
 									'width' => AVATAR_PROFILE_SIZE,
 									'height' => AVATAR_PROFILE_SIZE,
 									'alt' => $profile->nickname));
+
+        common_element_start('ul', array('id' => 'profile_actions'));
+
+        common_element_start('li', array('id' => 'profile_subscribe'));
 		$cur = common_current_user();
 		if ($cur) {
 			if ($cur->id != $profile->id) {
@@ -179,13 +182,20 @@ class ShowstreamAction extends StreamAction {
 		} else {
 			$this->show_remote_subscribe_link($profile);
 		}
+        common_element_end('li');
 		
 		$user = User::staticGet('id', $profile->id);
 		
 		if ($cur && $cur->id != $user->id && $cur->mutuallySubscribed($user)) {
+            common_element_start('li', array('id' => 'profile_send_a_new_message'));
 			common_element('a', array('href' => common_local_url('newmessage', array('to' => $user->id))),
 						   _('Send a message'));
+            common_element_end('li');
+            common_element_start('li', array('id' => 'profile_nudge'));
+            common_nudge_form($user);
+            common_element_end('li');
 		}
+        common_element_end('ul');
 		
 		common_element_end('div');
 
@@ -475,7 +485,8 @@ class ShowstreamAction extends StreamAction {
 			common_raw('&times;');
 			common_element_end('a');
 		}
+		
 		common_element_end('p');
 		common_element_end('li');
 	}
-}
\ No newline at end of file
+}
diff --git a/db/laconica.sql b/db/laconica.sql
index 87ac6e26db..4f4c37bd6a 100644
--- a/db/laconica.sql
+++ b/db/laconica.sql
@@ -48,6 +48,7 @@ create table user (
     incomingemail varchar(255) unique key comment 'email address for post-by-email',
     emailnotifysub tinyint default 1 comment 'Notify by email of subscriptions',
     emailnotifyfav tinyint default 1 comment 'Notify by email of favorites',
+    emailnotifynudge tinyint default 1 comment 'Notify by email of nudges',
     emailnotifymsg tinyint default 1 comment 'Notify by email of direct messages',
     emailmicroid tinyint default 1 comment 'whether to publish email microid',
     language varchar(50) comment 'preferred language',
diff --git a/db/laconica_pg.sql b/db/laconica_pg.sql
index d027dc0af0..e784bb1699 100644
--- a/db/laconica_pg.sql
+++ b/db/laconica_pg.sql
@@ -47,6 +47,8 @@ create table "user" (
     email varchar(255) unique /* comment 'email address for password recovery etc.' */,
     incomingemail varchar(255) unique /* comment 'email address for post-by-email' */,
     emailnotifysub integer default 1 /* comment 'Notify by email of subscriptions' */,
+    emailnotifyfav integer default 1 /* comment 'Notify by email of favorites' */,
+    emailnotifynudge integer default 1 /* comment 'Notify by email of nudges' */,
     emailmicroid integer default 1 /* comment 'whether to publish email microid' */,
     language varchar(50) /* comment 'preferred language' */,
     timezone varchar(50) /* comment 'timezone' */,
diff --git a/js/util.js b/js/util.js
index 151c0d1114..d0673b8397 100644
--- a/js/util.js
+++ b/js/util.js
@@ -85,6 +85,11 @@ $(document).ready(function(){
 	$("form.disfavor").ajaxForm(disoptions);
 	$("form.favor").each(addAjaxHidden);
 	$("form.disfavor").each(addAjaxHidden);
+
+	$("#nudge").ajaxForm ({ dataType: 'xml',
+							success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); }
+						 });
+	$("#nudge .submit").bind('click', function(e) {	$(this).addClass("processing"); }); 
 });
 
 function doreply(nick,id) {
diff --git a/lib/mail.php b/lib/mail.php
index b96bc7161d..a4764bfb54 100644
--- a/lib/mail.php
+++ b/lib/mail.php
@@ -232,6 +232,29 @@ function mail_confirm_sms($code, $nickname, $address) {
 	mail_send($recipients, $headers, $body);
 }
 
+
+function mail_notify_nudge($from, $to) {
+
+	$subject = sprintf(_('You\'ve been nudged by %s'), $from->nickname);
+
+	$from_profile = $from->getProfile();
+
+	$body = sprintf(_("%1\$s (%2\$s) is wondering what you are up to these days and is inviting you to post some news.\n\n".
+					  "You can reply to their message here:\n\n".
+					  "%3\$s\n\n".
+					  "Don't reply to this email; it won't get to them.\n\n".
+					  "With kind regards,\n".
+					  "%4\$s\n"),
+					$from_profile->getBestName(),
+					$from->nickname,
+					common_local_url('newmessage', array('to' => $from->id)),
+					common_config('site', 'name'));
+
+	return mail_to_user($to, $subject, $body);
+}
+
+
+
 function mail_notify_message($message, $from=NULL, $to=NULL) {
 
 	if (is_null($from)) {
diff --git a/lib/util.php b/lib/util.php
index e958a87bab..43e565fbf3 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -978,6 +978,8 @@ function common_fancy_url($action, $args=NULL) {
 		} else {
 			return common_path('main/remote');
 		}
+	 case 'nudge':
+	 	return common_path($args['nickname'].'/nudge');
 	 case 'openidlogin':
 		return common_path('main/openid');
 	 case 'profilesettings':
@@ -1861,6 +1863,25 @@ function common_favor_form($notice) {
 	common_element_end('form');
 }
 
+function common_nudge_form($profile) {
+	common_element_start('form', array('id' => 'nudge', 'method' => 'post',
+									   'action' => common_local_url('nudge', array('nickname' => $profile->nickname))));
+	common_hidden('token', common_session_token()); //Is this necessary?
+//	common_element('input', array('id' => 'nudge_nickname',
+//								  'name' => 'nudge_nickname',
+//								  'type' => 'hidden',
+//								  'value' => $profile->nickname));
+	common_element('input', array('type' => 'submit',
+								  'class' => 'submit',
+								  'value' => _('Send a nudge')));
+	common_element_end('form');
+}
+
+function common_nudge_response() {
+	common_element('p', array('id' => 'nudge_response'), _('Nudge sent!'));
+}
+
+
 function common_cache_key($extra) {
 	return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra;
 }
diff --git a/theme/default/display.css b/theme/default/display.css
index 91cc057fa0..19ec7b48da 100644
--- a/theme/default/display.css
+++ b/theme/default/display.css
@@ -208,6 +208,48 @@ input#disfavor, input.disfavor {
 }
 
 
+/*profile_actions*/
+#profile_actions {
+padding-left:0;
+list-style-type:none;
+margin:0;
+}
+#profile_actions li {
+margin-bottom:0.5em;
+clear:both;
+}
+
+#profile_actions #profile_nudge input.submit {
+margin:0;
+padding:0;
+padding-left:17px;
+background:transparent url(icon_emote-wink.png) 0 1px no-repeat;
+color:#C15D42;
+font-family:Georgia,"Times New Roman",Times,serif;
+font-weight:normal;
+font-size:14px;
+text-align:left;
+float:left;
+line-height:18px;
+}
+#profile_actions #profile_nudge input.submit:hover {
+background-color:transparent;
+color:#C15D42;
+}
+
+#wrap #content input.processing {
+padding-left:17px;
+background:transparent url(icon_process-working.gif) 0 1px no-repeat;
+line-height:18px;
+}
+
+#wrap p#nudge_response {
+padding-left:20px;
+background:transparent url(icon_checkmark.png) 0 1px no-repeat;
+line-height:18px;
+font-size:14px;
+}
+
 
 /* ----- Nav Footer ----- */
 #nav_sub {
diff --git a/theme/default/icon_checkmark.png b/theme/default/icon_checkmark.png
new file mode 100644
index 0000000000000000000000000000000000000000..818e3b5f8b10599d4865c1a01b00a1c958e597cc
GIT binary patch
literal 781
zcmV+o1M>WdP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|Aaq4obW?9;ba!ELWdKcKV{&h8Wn^h#
zAVz6&Wp{6KYjYq?Si6xbBme*a7IZ~ebVG7wVRUJ4ZXi@?ZDjy4F)uJRFEBUVx{2EW
z00Lo2L_t(|oQ;#uOVm*m#Xs+T$I+3|w8<7~A&7#4WoWKi6oeooD6}zx>@P^Dl~9%-
z6tu8qZOV=A(%c9Uh}0rXG!=&^M9~>DO#Ct9INzCh@3xp4XCSPzd+(id&%Nhym57jy
zx~1#qyejXJBf8l^R~l<@Z6f5_<cw<*ed|pV3)y^?U7#^|W7JW)W6j-U$3!p~030-a
zd<3MJq)m;jwM=y86u1`}ESQSSe*2l)tz1oPa2x`r2%qtWDh^K8e7rgm*8uPKr$_!r
z46yA)h^oWN<$}!-0M#74dC?-%v#~G#6n6*OSxJPMip+BAz>l@IMaOMoV9nh;R(QFn
ziIs+N1YzpOCvYuMZ=9qu1KOwZ>vv2fL$30c(^y!WIS-z>%Vh0y2E)S)Exk@(=4)J!
zK_#VLi%7+vv;kgL_0e70PKo##t$xa#(_M^hP4aAE2>cEdIsk|gtg#j9!a|qKCB6dC
zSXj$k-7o+<seMX4#q6dcRK0Cw&l7_{Ue0K~EsaiD6L!!5+zMRFJeGQj0q9wH!k&pj
zX|7la7;C~hYGXk^J^&tWyx`UM@eFA-w!zT)8z}Mc+vBJ}9E`^Xb)I#41Cn;zGf{4b
z`srS}&u%h8&*Ee7sLb5i&=G@8nqDO$oSkkPjS=tIc8-4IysBnC989<F%eB}07KxiN
z+cw{+0czaxE}!v+N|J>c(!4A~nfLGFm<h?sVOKhftYs?uaAg!L9Z_!_*JBVRnZQ&$
z-L}Dw*|z!IWy;2h_m>(l(l17uC1op(SPUj)l%26k9@y5;i`o2NVj?d(?t}+t00000
LNkvXXu0mjf%`sil

literal 0
HcmV?d00001

diff --git a/theme/default/icon_emote-wink.png b/theme/default/icon_emote-wink.png
new file mode 100644
index 0000000000000000000000000000000000000000..46be685577ce2122c83c5190cd1c6dedb87ef82c
GIT binary patch
literal 914
zcmV;D18w|?P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)e8p{8yT`vMq&T}05x<)
zSad^gZEa<4bO0!0DIhX1Ff<@aVQY0_AX9W@X>Mh53JODVWnpw>WFU8GbZ8({Xk{Qr
zNlj3Y*^6%g00Q1gL_t(I%cYY~Xp?6g$3M^WzIoGFO>1gmZAFGtY-`OxW6ZQ}LMJSA
zf*`f9gVM`->B<nj4P>y(C~S;QFo!X`2-2ws^`fBDL0h`4u2tzs2cs%xMw_OtZQg%*
z9uGmB_PFo)_xtkY`$zB=#{21&zU&sRNZ^YICPi(jtO_uk98y2MeJ}p=7?+O7G$y-J
z4f}csL|Z}Df;*4*^geT=7y0MzjWK1ZzT^)~y+JVEPuy4(H(CbH#DbAEsQFt6!vt-D
z@1k87>QXqx61gA0ET}LCcYm*@03?8P$h3Su6bo3hX!{-_{4Rvwfi)W;ya`da8J4E8
z^ekJCpN@&L%Dhq_$NTAR-1TwFT3ZVS5Ud4Nfn^sF-p;_+x4D_kBiHQ&LlX>#Sl_lk
z_4^647eGpn?uL$|sD%-P0XKhr!guE;N%WitQ!+B~h{@b@Ff7197w!;Aeu6Gnx&ch#
zkO)NEP>=5*42#Z#?Q|a6%!!i%sIWJ&iO$ZCs&;9>UnUT1LzH!*>VZ$hS4(KG#PrNl
zsQ9llvL7-uIKX=?G4#Sca(_Pqy9mM6;1dBbF)5n5CR%Y`aP9VWM*m2Y+FhV=eI4bp
z$Dh+vMC$^aJ)h-pM>AU@OK7_UCPe^K*N}Dd6KUzV97%u3qbDUUUHOH{oX2e5p*dDd
z`?e-}(s9}nhY-bE`1uFukjR3@q{bMY8@ZT{esF;1XFszp9wD{o0A^@AQfxrfG=XoU
z7iLh;e?u9om>a!{2pPlRSBsSWjL~hMo=#cbeJab7U|I+%k-iDOhjwk0U5(WZ?O^8e
z;8-HV`>%^sZ}sKQeN}LbR*a@&$VH7PEumk`qZa=KS0J|>!&}wPUl#@ovOd_iVha<e
zthicmGqKi=R70{0GuDa-hQTS}<sUFNevQJ+*qE#j_U-(}nOZ^c3fV7=UhGP@uu0%k
oU1LaOMaUT5^{u~RjsF`j0ixU^2n2_zod5s;07*qoM6N<$f(_Z2(EtDd

literal 0
HcmV?d00001

diff --git a/theme/default/icon_process-working.gif b/theme/default/icon_process-working.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d42f72c723644bbf8cf8d6e1b7ff0bea7ddd305a
GIT binary patch
literal 1849
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

literal 0
HcmV?d00001

diff --git a/theme/default/ie7.css b/theme/default/ie7.css
index 99bc4e79f1..14534c05e8 100644
--- a/theme/default/ie7.css
+++ b/theme/default/ie7.css
@@ -1,7 +1,5 @@
 @charset "UTF-8";
 /* CSS Document */
-
-
 input.disfavor,
 input.favor {
 	text-indent:0;
@@ -9,11 +7,19 @@ input.favor {
 	padding-left:25px;
 }
 
+#profile_actions li {
+float:left;
+clear:both;
+}
+#profile_actions #profile_nudge input.submit {
+margin-left:0;
+width:100px;
+}
+
 #statistics dd {
 	clear: both;
 	}		
 	
-	
 #subscriptions_avatars li {
 	float: left;
 	}
-- 
2.39.5