function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jvolkovjvolkov 

Chatter MiniFeed Mod

This is a very slight modification to the chatterMiniFeed class from the Chatter MiniFeed app, part of the Chatter Combo app.  I'm not sure if this was the most efficient method to add the body but it works.

 

 

// Jonathan Hersh - jhersh@salesforce.com - 2/26/2010
public class chatterMiniFeed {
    public notification[] notes { get; set; }
    public Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
    public Map<string,string> prefixes       = getSObjectPrefixes();
    
    public chatterMiniFeed() {
        doRefresh();
    }
    
    public pageReference doRefresh() {
        string uID = UserInfo.getUserId();
        string ptype;
        
        notes = new notification[] {};
        
        NewsFeed[] nfs = [select id, createdbyid, createddate, createdby.name, type, feedpost.type,
            parentid, parent.name, FeedPost.Body,  /*added FeedPost.Body on 10/11/2010 by JV*/
                (select createddate, createdbyid, parentid, createdby.name, feeditemid
                    from FeedComments 
                    where createdbyid <> :uID
                    order by createddate desc limit 30),
                (select FieldName from FeedTrackedChanges ORDER BY Id DESC)
            from NewsFeed
            where not FeedPost.Body like '%Google Alert%'  /*added FeedPost.Body on 10/11/2010 by JV*/
            order by createddate desc limit 200];
        
        for( NewsFeed nf : nfs ) {
            if( nf.type == 'LinkPost' )
                ptype = 'link';
            else if( nf.type == 'TextPost' )
                ptype = 'note';
            else if( nf.type == 'ContentPost' )
                ptype = 'file';
            else if( nf.type == 'UserStatus' )
                ptype = 'status update';
                
            if( nf.type == 'TrackedChange' && nf.feedtrackedchanges.isEmpty() )
                continue;
                
            string obtype = getPrefix( nf.parentid, 0 );
            string postURL;
            
            if( obtype == 'User' )
              postURL = '/_ui/core/userprofile/UserProfilePage?u='+ nf.parentid + '&';
            else if( obtype == 'CollaborationGroup' )
              postURL = '/_ui/core/chatter/groups/GroupProfilePage?g='+ nf.parentid + '&';
            else
              postURL = '/' + nf.parentid + '?';
              
            postURL += 'ChatterFeedItemId=' + nf.id;
            
            // Tracked change from someone else on a record that we follow
            if( nf.type == 'TrackedChange' && nf.createdbyid != uId ) {
              if( nf.FeedTrackedChanges[0].fieldname == 'created' )
                  notes.add( new notification( (''+nf.createdbyid), nf.createdby.name, ' created a new <b>'+
                  getPrefix( nf.parentid, 1 ) +'</b>: <a href="' + postURL +'" target="_top">'+ nf.parent.name +'</a>.', nf.FeedPost.Body, nf.createddate ) );
                else
                  notes.add( new notification( (''+nf.createdbyid), nf.createdby.name, ' updated <b>'+ nf.feedtrackedchanges[0].fieldname +'</b> on'+
                  ' <a href="' + postURL +'" target="_top">'+ nf.parent.name +'</a>.', nf.FeedPost.Body, nf.createddate ) );
            // Post from someone else on another object that we follow
            } else if( nf.parentid != uId && nf.CreatedById != uID )
                notes.add( new notification( (''+nf.createdbyid), nf.createdby.name, ' posted a '+ 
                  ( ptype != 'status update' ? ptype + ' on <a href="' + postURL +'" target="_top">'+ nf.parent.name +'</a>.' : 
                  '<a href="'+ postURL +'" target="_top">' + ptype + '</a>.' ), nf.FeedPost.Body, nf.createddate ) );
            // We don't show our own wall posts...
            else if( nf.createdbyid != uId && nf.parentid == uId )
                notes.add( new notification( (''+nf.createdbyid), nf.createdby.name, ' posted a '+ ptype +' on <a href="' + postURL +'" target="_top">your profile</a>.', nf.FeedPost.Body, nf.createddate ) );
            
            // ...but we do show comments from other people about them
            for( FeedComment fc : nf.feedcomments )
                if( fc.createdbyid != uID )
                    notes.add( new notification( (''+fc.createdbyid), fc.createdby.name, ' commented on '+
                        ( nf.createdbyid == uID ? 'your' : 'a' ) + ' post on '+
                        ( nf.parentid == uID ? '<a href="'+ postURL +'" target="_top">your profile</a>.' : 
                            '<a href="' + postURL +'" target="_top">'+ nf.parent.name +'</a>.' ),
                        nf.FeedPost.Body, fc.createddate ) );
        }
            
        // This will error if you haven't deployed the chatter messages objects, so we'll try to detect
        // ahead of time if it's been deployed
        // All messages and replies sent to us      
        /*if( Schema.SObjectType.Chatter_Message_Recipient__c.fields.chatter_message__c.isAccessible() ) {
            Chatter_Message_Recipient__c[] recips = [select chatter_message__c, chatter_message__r.ownerid, chatter_message__r.owner.name,
                chatter_message__r.parent__c, chatter_message__r.parent__r.ownerid, createddate, chatter_message__r.subject__c
                from Chatter_Message_Recipient__c
                where recipient__c = :UserInfo.getUserId()
                and chatter_message__r.ownerid <> :UserInfo.getUserId()
                order by createddate desc limit 200];
                
            for( Chatter_Message_Recipient__c cmr : recips ) {           
                if( cmr.chatter_message__r.parent__c != null && cmr.chatter_message__r.parent__r.ownerid == UserInfo.getUserId() )
                    notes.add( new notification( ''+ cmr.chatter_message__r.ownerid, cmr.chatter_message__r.owner.name,
                        ' replied to your ',
                        cmr.createddate, cmr.chatter_message__c, 'message', cmr.chatter_message__r.subject__c, '/apex/chatterMessages' ) );
                else if( cmr.chatter_message__r.parent__c != null )
                    notes.add( new notification( ''+ cmr.chatter_message__r.ownerid, cmr.chatter_message__r.owner.name,
                        ' replied to a ',
                        cmr.createddate, cmr.chatter_message__c, 'message', cmr.chatter_message__r.subject__c, '/apex/chatterMessages' ) );
                else
                    notes.add( new notification( ''+ cmr.chatter_message__r.ownerid, cmr.chatter_message__r.owner.name,
                        ' sent you a ',
                        cmr.createddate, cmr.chatter_message__c, 'message', cmr.chatter_message__r.subject__c, '/apex/chatterMessages' ) );
                
            }
        }*/
    
        // Sort in descending chronological order
        sortNotes( notes );
        
        return null;
    }
    
    public class notification {
        public string uid       { get; set; }
        public string uname     { get; set; }
        public string msg       { get; set; }
        public string body      { get; set; }  /*added FeedPost.Body on 10/11/2010 by JV*/
        public string timestr   { get; set; }
        
        public long timestamp   { get; set; }
        
        public notification( string uid2, string uname2, string msg2, string body2, Datetime dt ) {
            uid = uid2;
            uname = uname2;
            msg = msg2;
            body = body2;  /*added FeedPost.Body on 10/11/2010 by JV*/
            timestr = relativeTime( dt );
            timestamp = dt.getTime() / 1000;
        }
        
        public string relativeTime( Datetime dt ) {
            long diff =  ( Datetime.now().getTime() - dt.getTime() ) / 1000;
            string unit;
            
            if( diff < 60 )
                unit = 'second';
            else if( diff < 60 * 60 ) {
                diff /= 60;
                unit = 'minute';
            } else if( diff < 60 * 60 * 24 ) {
                diff = diff / 60 / 60;
                unit = 'hour';
            } else {
                diff = diff / 60 / 60 / 24;
                unit = 'day';
            }
            
            if( diff > 1 )
                unit += 's';
                
            return diff + ' ' + unit + ' ago';
        }
    }
    
    public static void sortNotes(List<notification> items){
        List<notification> resultList = new List<notification>();
            
        //Create a map that can be used for sorting 
        Map<long, List<notification>> noteMap = new Map<long, List<notification>>();
            
            for(notification ob : items){
                    if(noteMap.get(ob.timestamp) == null)
                        noteMap.put(ob.timestamp, new List<notification>()); 

                    noteMap.get(ob.timestamp).add(ob);
            }
        
            //Sort the keys
        
            List<long> keys = new List<long>(noteMap.keySet());
            keys.sort();       
            
            for(long key : keys)
                resultList.addAll(noteMap.get(key));      
        
        //Apply the sorted values to the source list. descending order
        items.clear();
        
        for(integer i = resultList.size()-1; i >= 0; i--)
            items.add(resultList[i]);   
    }
    
    public string getPrefix( ID obID, integer t ) {
      string pref = (''+obID).substring(0,3);
      
      if( !prefixes.containsKey( pref ) )
        return '';
        
      return prefixes.get( pref ).split(':').get( t == 0 ? 0 : 1 );
    }
    
    // Calculate 3-letter prefixes for objects in this org
    // so we can decode IDs that are passed to us
    public Map<string,string> getsObjectPrefixes() {
      Map<string,string> ret = new Map<string,string> ();
      
      for( string s : gd.keySet() ) {
          Schema.Sobjecttype ob = gd.get( s );
          Schema.Describesobjectresult sob = ob.getDescribe();
          
          if( sob.getKeyPrefix() == null )
              continue;
              
          if( !sob.isFeedEnabled() )
              continue;
          
          ret.put( sob.getKeyPrefix(), sob.getName() + ':' + sob.getLabel() );
      }
  
      return ret;
    }
    
    public static testmethod void runTest() {
      Profile p = [select id from Profile where usertype='Standard' limit 1];
      User u = new User(alias = 'standt', email='standarduser@kwutang.demo', 
                        emailencodingkey='UTF-8', lastname='Testing1', firstname='Testing', languagelocalekey='en_US', 
                        localesidkey='en_US', profileid = p.Id, 
                        timezonesidkey='America/Los_Angeles', username='standarduser@kwutang.demo');        
        
        try {
          insert u;
          insert new EntitySubscription( subscriberid = userinfo.getuserid(), parentid = u.id );
        } catch( Exception e ) {}
        
        system.assertNotEquals( null, u.id );
        
        system.runAs( u ) {
        FeedPost fp = new FeedPost();
        fp.body = 'Testing search';
        fp.linkurl = 'http://google.com';
        fp.title = 'google';
        fp.ParentId = userinfo.getuserid();
        insert fp;
        
        UserFeed uf = [select id from UserFeed
          where parentid = :userinfo.getuserid()
          and feedpost.body = 'Testing search'];
        
        FeedComment fc = new FeedComment();
        fc.feeditemid = uf.id;
        fc.commentbody = 'new search comment!';
        
        insert fc;
        }
      
        chatterMiniFeed cmf = new chatterMiniFeed();
    }
}