Write a Steemit Web App: Part 2 - Followers and Following

(Previous Post: Part 1)

Follower/Following Counts

Steemit uses the concept of Followers to generate default feeds (e.g., @ned/feed).

We can get the count of followers and followings for an account by using the getFollowCount API function (or getFollowCountAsync if using Promises instead of Node-style callbacks):

function refreshAccountData(accountName) {
  return steem.api.getAccountsAsync([accountName])
    .then(function (result) {
...
      steem.api.getFollowCountAsync(accountName)
        .then(function (result) {
          vm.$set(vm.userData, 'follower_count', result.follower_count)
          vm.$set(vm.userData, 'following_count', result.following_count)
        })
      .catch(console.error)
...


For this to work correctly, add a follower_count and following_count property to the viewmodel's userData object defined in Part 1 of this series:

...
          userData: {
            profile_image: "",
            level: 0,
            xp: 0,
            power: 0,
            following_count: 0,
            follower_count: 0
          }
...

Enumerating


Getting the actual list of followers/followings (as well as "muted" users that you never want to see content from) is a bit trickier. First, let's add some array properties to the viewmodel data to hold our lists:

        data: {
          user: 'jfollas',
          userData: {
            profile_image: "",
            level: 0,
            xp: 0,
            power: 0,
            following_count: 0,
            follower_count: 0
          },
          followers: [],
          following: [],
          ignored: []
        }


Now fetch the list of 'followers'. You have to chunk through followers 1000 items at a time, so we can use a generator function in JavaScript to retrieve the entire list:

let getFollowersList = P.coroutine(function* () {
  let start = '', count = 0
  vm.followers = []
  do {
    yield steem.api.getFollowersAsync(vm.user, start, 'blog', 1000)
      .then(function (result) {
        start = ''
        count = result.length

        for (let i = 0; i < count; i++) {
          let entry = { name: result[i].follower }
          start = entry.name
          vm.followers.push(entry)
        }
      })
  } while (count === 1000);
})


The 'following' list works the same, except it has to be chunked 100 items at a time instead of 1000:

let getFollowingList = P.coroutine(function* () {
  let start = '', count = 0
  vm.following = []
  do {
    yield steem.api.getFollowingAsync(vm.user, start, 'blog', 100)
      .then(function (result) {
        start = ''
        count = result.length

        for (let i = 0; i < count; i++) {
          let entry = { name: result[i].following }
          start = entry.name
          vm.following.push(entry)
        }
      })
  } while (count === 100);
})


Note that in both of these, we are using "blog" as the follow type. Also, on each iteration, we pass the last name from the previous iteration as the "start" value.

"Muted" users are maintained in a follow type of "ignore" instead of "blog". Otherwise, the function works identically to the getFollowingList:

let getIgnoredList = P.coroutine(function* () {
  let start = '', count = 0
  vm.ignored = []
  do {
    yield steem.api.getFollowingAsync(vm.user, start, 'ignore', 100)
      .then(function (result) {
        start = ''
        count = result.length

        for (let i = 0; i < count; i++) {
          let entry = { name: result[i].following }
          start = entry.name
          vm.ignored.push(entry)
        }
      })
  } while (count === 100);
})


Okay, we have functions to retrieve the data and populate our viewmodel, but nothing is actually calling these functions. So, let's add function calls to our refreshAccountData() logic:

function refreshAccountData(accountName) {
  return steem.api.getAccountsAsync([accountName])
    .then(function (result) {
...
      getFollowersList()
      getFollowingList()
      getIgnoredList()
    })
...

Displaying Results

Finally, let's add some HTML and Vue bindings to show our newly populated lists. Within the container element, insert this block of html:

    <div class="row">

      <div class="col-4">
        <h2>Followers</h2>
        <ul class="list-group">
          <li class="list-group-item" v-for="p in followers">
            {{ p.name }}
          </li>
        </ul>        
      </div>

      <div class="col-4">
        <h2>Following</h2>
        <ul class="list-group">
          <li class="list-group-item" v-for="p in following">
            {{ p.name }}
          </li>
        </ul>        
      </div>

      <div class="col-4">
        <h2>Muted</h2>
        <ul class="list-group">
          <li class="list-group-item" v-for="p in ignored">
            {{ p.name }}
          </li>
        </ul>        
      </div>

    </div>


Example (names have been obfuscated):
steemit-tutorial-2.PNG

(Next Post: Part 3)

H2
H3
H4
3 columns
2 columns
1 column
7 Comments