! Added Unread PM Favicon SMF mod
Jeremy D

Jeremy D commited on 2012-03-31 22:29:26
Showing 9 changed files, with 188 additions and 0 deletions.

... ...
@@ -0,0 +1,24 @@
1
+Copyright (c) 2012, SleePy (smf-mods-license@sleepycode.com)
2
+All rights reserved.
3
+
4
+Redistribution and use in source and binary forms, with or without
5
+modification, are permitted provided that the following conditions are met:
6
+    * Redistributions of source code must retain the above copyright
7
+      notice, this list of conditions and the following disclaimer.
8
+    * Redistributions in binary form must reproduce the above copyright
9
+      notice, this list of conditions and the following disclaimer in the
10
+      documentation and/or other materials provided with the distribution.
11
+    * Neither the name of the <organization> nor the
12
+      names of its contributors may be used to endorse or promote products
13
+      derived from this software without specific prior written permission.
14
+
15
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
19
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 25
\ No newline at end of file
... ...
@@ -0,0 +1,16 @@
1
+SMF 2.0+ Modification.  I will not back support this mod to older versions.
2
+
3
+This modification adds a unread PM counter to the favicon.  In addition it continues to check for PMs at a specified interval.  Setting this variable to lower can result in server degration/performance issues.  Use with caution.  The default timeout is 1 minute (60 seconds).
4
+
5
+Prior to asking for support, check out the wiki: https://github.com/jdarwood007/smf-unreadPM_count/wiki
6
+
7
+Credits for this ability go to Tom Moor for creating Tinycon: https://github.com/tommoor/tinycon
8
+
9
+Browsers that support this:
10
+Chrome 15+
11
+Firefox 9+
12
+Opera 11+
13
+
14
+The following browsers will fall back to changing the title due to lack of support for this:
15
+Internet Explorer 9
16
+Safari 5
0 17
\ No newline at end of file
... ...
@@ -0,0 +1,62 @@
1
+<?php
2
+
3
+// This adds a hook to our action=.
4
+function uPMs_hook_actionArray($actionArray)
5
+{
6
+	global $modSettings;
7
+
8
+	$actionArray['unreadpms'] = array('UnreadPMs.php', 'UnreadPMsXML');
9
+}
10
+
11
+// Adds a hook to the end of loadTheme();
12
+function uPMs_hook_load_theme()
13
+{
14
+	global $context, $settings, $modSettings;
15
+
16
+	// Default the setting to 1 minute.
17
+	if (!isset($modSettings['unreadPMstimeout']))
18
+		$modSettings['unreadPMstimeout'] = '60';
19
+	elseif (empty($modSettings['unreadPMstimeout']) || $context['user']['is_guest'])
20
+		return;
21
+
22
+	// Append the html headers.
23
+	$context['html_headers'] .= '
24
+	<script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/tinycon.min.js?fnl1"></script>
25
+	<script type="text/javascript"><!-- // --><![CDATA[
26
+		var funreadPMs = function ()
27
+		{
28
+			window.setTimeout(\'funreadPMs();\', ' . $modSettings['unreadPMstimeout'] * 600 . ');
29
+
30
+			var oNewPms = getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + \'action=unreadpms\');
31
+
32
+			if (oNewPms.responseXML)
33
+			{
34
+				var newCount = oNewPms.responseXML.getElementsByTagName(\'smf\')[0].getElementsByTagName(\'unreadpms\')[0].firstChild.nodeValue;
35
+				Tinycon.setBubble(newCount);
36
+			}
37
+		}
38
+		addLoadEvent(funreadPMs);
39
+	// ]]></script>';
40
+}
41
+
42
+
43
+// Adds a hook to the general mod settings so we can manage the setting.
44
+function uPMs_hook_general_mod_settings($config_vars)
45
+{
46
+	$config_vars[] = array('int', 'unreadPMstimeout', 'postinput' => $txt['unreadPMstimeout_post']);
47
+}
48
+
49
+// Provides the XML for our javascript to read.
50
+function UnreadPMsXML()
51
+{
52
+	global $user_info, $context;
53
+
54
+	header('Content-Type: text/xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
55
+
56
+	echo '<', '?xml version="1.0" encoding="', $context['character_set'], '"?', '>
57
+<smf>
58
+	<unreadpms>', $user_info['unread_messages'], '</unreadpms>
59
+</smf>';
60
+
61
+	obExit(false, false, false);
62
+}
... ...
@@ -0,0 +1,19 @@
1
+<?php
2
+error_reporting(E_ALL);
3
+
4
+// Hopefully we have the goodies.
5
+if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
6
+{
7
+	$using_ssi = true;
8
+	require_once(dirname(__FILE__) . '/SSI.php');
9
+}
10
+elseif (!defined('SMF'))
11
+	exit('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
12
+
13
+add_integration_function('integrate_pre_include', '$sourcedir/UnreadPMs.php');
14
+add_integration_function('integrate_actions', 'uPMs_hook_actionArray');
15
+add_integration_function('integrate_load_theme', 'uPMs_hook_load_theme');
16
+add_integration_function('integrate_general_mod_settings', 'uPMs_hook_general_mod_settings');
17
+
18
+if(!empty($using_ssi))
19
+	echo 'If no errors, Success!';
0 20
\ No newline at end of file
... ...
@@ -0,0 +1,19 @@
1
+<?php
2
+error_reporting(E_ALL);
3
+
4
+// Hopefully we have the goodies.
5
+if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
6
+{
7
+	$using_ssi = true;
8
+	require_once(dirname(__FILE__) . '/SSI.php');
9
+}
10
+elseif (!defined('SMF'))
11
+	exit('<b>Error:</b> Cannot uninstall - please verify you put this in the same place as SMF\'s index.php.');
12
+
13
+remove_integration_function('integrate_pre_include', '$sourcedir/UnreadPMs.php');
14
+remove_integration_function('integrate_actions', 'uPMs_hook_actionArray');
15
+remove_integration_function('integrate_load_theme', 'uPMs_hook_load_theme');
16
+remove_integration_function('integrate_general_mod_settings', 'uPMs_hook_general_mod_settings');
17
+
18
+if(!empty($using_ssi))
19
+	echo 'If no errors, Success!';
0 20
\ No newline at end of file
... ...
@@ -0,0 +1,16 @@
1
+<?xml version="1.0"?>
2
+<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification">
3
+<!-- This package was generated by SleePys Modification Maker at http://sleepycode.com -->
4
+<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/">
5
+	<id>sleepy:unreadpmfav</id>
6
+	<version>1.0</version>
7
+
8
+	<file name="$languagedir/Modifications.english.php">
9
+		<operation>
10
+			<search position="end"/>
11
+			<add><![CDATA[// Unread PMs strings.
12
+$txt['unreadPMstimeout'] = 'Unread PMs Favicon Counter';
13
+$txt['unreadPMstimeout_post'] = 'seconds between checks (setting this to low may cause performance issues)';]]></add>
14
+		</operation>
15
+	</file>
16
+</modification>
0 17
\ No newline at end of file
... ...
@@ -0,0 +1,23 @@
1
+<!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info">
2
+<!-- This package was generated by SleePys Package Maker at http://sleepycode.com -->
3
+<package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/">
4
+	<id>sleepy:unreadpmfav</id>
5
+	<name>Unread PMs Favicon</name>
6
+	<version>1.0</version>
7
+	<type>modification</type>
8
+
9
+	<install for="SMF 2.0-2.0.99">
10
+		<code>hooks_add.php</code>
11
+		<move-file name="UnreadPMs.php" destination="$sourcedir/" />
12
+		<move-file name="tinycon.min.js" destination="$themedir/scripts/" />
13
+		<modification>language.xml</modification>
14
+	</install>
15
+
16
+	<uninstall for="SMF 2.0-2.0.99">
17
+		<code>hooks_remove.php</code>
18
+		<remove-file name="$themedir/scripts/tinycon.min.js" />
19
+		<remove-file name="$sourcedir/UnreadPMs.php" />
20
+		<modification reverse="true">language.xml</modification>
21
+	</uninstall>
22
+
23
+</package-info>
0 24
\ No newline at end of file
... ...
@@ -0,0 +1,9 @@
1
+/*
2
+ * Tinycon - A small library for manipulating the Favicon
3
+ * Tom Moor, http://tommoor.com
4
+ * Copyright (c) 2012 Tom Moor
5
+ * MIT Licensed
6
+ * @version 0.2.6
7
+*/
8
+
9
+(function(){var Tinycon={};var currentFavicon=null;var originalFavicon=null;var originalTitle=document.title;var faviconImage=null;var canvas=null;var options={};var defaults={width:7,height:9,font:'10px arial',colour:'#ffffff',background:'#F03D25',fallback:true};var ua=(function(){var agent=navigator.userAgent.toLowerCase();return function(browser){return agent.indexOf(browser)!==-1}}());var browser={chrome:ua('chrome'),webkit:ua('chrome')||ua('safari'),safari:ua('safari')&&!ua('chrome'),mozilla:ua('mozilla')&&!ua('chrome')&&!ua('safari')};var getFaviconTag=function(){var links=document.getElementsByTagName('link');for(var i=0,len=links.length;i<len;i++){if((links[i].getAttribute('rel')||'').match(/\bicon\b/)){return links[i]}}return false};var removeFaviconTag=function(){var links=document.getElementsByTagName('link');var head=document.getElementsByTagName('head')[0];for(var i=0,len=links.length;i<len;i++){var exists=(typeof(links[i])!=='undefined');if(exists&&links[i].getAttribute('rel')==='icon'){head.removeChild(links[i])}}};var getCurrentFavicon=function(){if(!originalFavicon||!currentFavicon){var tag=getFaviconTag();originalFavicon=currentFavicon=tag?tag.getAttribute('href'):'/favicon.ico'}return currentFavicon};var getCanvas=function(){if(!canvas){canvas=document.createElement("canvas");canvas.width=16;canvas.height=16}return canvas};var setFaviconTag=function(url){removeFaviconTag();var link=document.createElement('link');link.type='image/x-icon';link.rel='icon';link.href=url;document.getElementsByTagName('head')[0].appendChild(link)};var log=function(message){if(window.console)window.console.log(message)};var drawFavicon=function(num,colour){if(!getCanvas().getContext||browser.safari||options.fallback==='force'){return updateTitle(num)}var context=getCanvas().getContext("2d");var colour=colour||'#000000';var num=num||0;var src=getCurrentFavicon();faviconImage=new Image();faviconImage.onload=function(){context.clearRect(0,0,16,16);context.drawImage(faviconImage,0,0,faviconImage.width,faviconImage.height,0,0,16,16);if(num>0)drawBubble(context,num,colour);refreshFavicon()};if(!src.match(/^data/)){faviconImage.crossOrigin='anonymous'}faviconImage.src=src};var updateTitle=function(num){if(options.fallback){if(num>0){document.title='('+num+') '+originalTitle}else{document.title=originalTitle}}};var drawBubble=function(context,num,colour){var len=(num+"").length-1;var width=options.width+(6*len);var w=16-width;var h=16-options.height;context.font=(browser.webkit?'bold ':'')+options.font;context.fillStyle=options.background;context.strokeStyle=options.background;context.lineWidth=1;context.fillRect(w,h,width-1,options.height);context.beginPath();context.moveTo(w-0.5,h+1);context.lineTo(w-0.5,15);context.stroke();context.beginPath();context.moveTo(15.5,h+1);context.lineTo(15.5,15);context.stroke();context.beginPath();context.strokeStyle="rgba(0,0,0,0.3)";context.moveTo(w,16);context.lineTo(15,16);context.stroke();context.fillStyle=options.colour;context.textAlign="right";context.textBaseline="top";context.fillText(num,15,browser.mozilla?7:6)};var refreshFavicon=function(){if(!getCanvas().getContext)return;setFaviconTag(getCanvas().toDataURL())};Tinycon.setOptions=function(custom){options={};for(var key in defaults){options[key]=custom.hasOwnProperty(key)?custom[key]:defaults[key]}return this};Tinycon.setImage=function(url){currentFavicon=url;refreshFavicon();return this};Tinycon.setBubble=function(num,colour){if(isNaN(parseFloat(num))||!isFinite(num))return log('Bubble must be a number');drawFavicon(num,colour);return this};Tinycon.reset=function(){Tinycon.setImage(originalFavicon)};Tinycon.setOptions(defaults);window.Tinycon=Tinycon})();
0 10
\ No newline at end of file
1 11